]> git.donarmstrong.com Git - lilypond.git/blob - lily/breathing-sign.cc
* input/regression/hairpin-dashed.ly: new file.
[lilypond.git] / lily / breathing-sign.cc
1 /*
2   breathing_sign.cc -- implement Breathing_sign
3
4   (c)  1999--2003 Michael Krause
5
6   written for the GNU LilyPond music typesetter
7
8   TODO: --> see breathing-sign-engraver.cc
9
10   Extensions for ancient notation (c)  2003 by Juergen Reuter
11 */
12
13 #include "staff-symbol-referencer.hh"
14 #include "directional-element-interface.hh"
15 #include "breathing-sign.hh"
16 #include "string.hh"
17 #include "molecule.hh"
18 #include "paper-def.hh"
19 #include "lookup.hh"
20
21 #include "dimensions.hh"
22 #include "direction.hh"
23 #include "text-item.hh"
24 #include "font-interface.hh"
25
26 /*
27   TODO: thickness should be a grob property (unit: stafflinethickness)
28  rather than hardwired to (staff_space / 6).
29  */
30
31   
32
33 /*
34   Gregorian chant divisio minima.  (Actually, this was the original
35   breathing sign by Michael. -- jr)
36  */
37 MAKE_SCHEME_CALLBACK (Breathing_sign,divisio_minima,1);
38 SCM 
39 Breathing_sign::divisio_minima (SCM smob)
40 {
41   Grob *me = unsmob_grob (smob);
42   Real staff_space = Staff_symbol_referencer::staff_space (me);
43   Real staff_size;
44   Real thickness = me->get_paper ()->get_realvar (ly_symbol2scm ("linethickness"));
45   SCM lt =  me->get_grob_property ("thickness");
46   if (gh_number_p (lt))
47     thickness *= gh_scm2double (lt);
48   if (Staff_symbol_referencer::get_staff_symbol (me))
49     {
50       staff_size = (Staff_symbol_referencer::line_count (me) - 1) * staff_space;
51     }
52   else
53     staff_size = 0.0;
54
55   Real blotdiameter = me->get_paper ()->get_realvar (ly_symbol2scm ("blotdiameter"));
56
57   /*
58    * Draw a small vertical line through the uppermost (or, depending
59    * on direction, lowermost) staff line.
60    */
61   Interval xdim (0, thickness);
62   Interval ydim (-0.5 * staff_space, +0.5 * staff_space);
63   Box b (xdim, ydim);
64   Molecule out = Lookup::round_filled_box (b, blotdiameter);
65   return out.smobbed_copy ();
66 }
67
68 /*
69   Gregorian chant divisio maior.
70  */
71 MAKE_SCHEME_CALLBACK (Breathing_sign,divisio_maior,1);
72 SCM 
73 Breathing_sign::divisio_maior (SCM smob)
74 {
75   Grob *me = unsmob_grob (smob);
76   Real staff_space = Staff_symbol_referencer::staff_space (me);
77   Real staff_size;
78   Real thickness = me->get_paper ()->get_realvar (ly_symbol2scm ("linethickness"));
79   SCM lt =  me->get_grob_property ("thickness");
80   if (gh_number_p (lt))
81     thickness *= gh_scm2double (lt);
82   if (Staff_symbol_referencer::get_staff_symbol (me))
83     {
84       staff_size = (Staff_symbol_referencer::line_count (me) - 1) * staff_space;
85     }
86   else
87     staff_size = 0.0;
88
89   Real blotdiameter = me->get_paper ()->get_realvar (ly_symbol2scm ("blotdiameter"));
90
91   /*
92    * Draw a vertical line that is vertically centered in the staff
93    * (just like a bar).  The height of this line should be a little
94    * more than half the size of the staff, such that the endings of
95    * the line are in the middle of a staff space.
96    */
97   int lines = Staff_symbol_referencer::line_count (me);
98   int height = lines / 2; // little more than half of staff size
99   if ((lines & 1) != (height & 1))
100     height++; // ensure endings are centered in staff space
101
102   Interval xdim (0, thickness);
103   Interval ydim (-0.5 * height, +0.5 * height);
104   Box b (xdim, ydim);
105   Molecule out = Lookup::round_filled_box (b, blotdiameter);
106   return out.smobbed_copy ();
107 }
108
109 /*
110   Gregorian chant divisio maxima.
111  */
112 MAKE_SCHEME_CALLBACK (Breathing_sign,divisio_maxima,1);
113 SCM 
114 Breathing_sign::divisio_maxima (SCM smob)
115 {
116   Grob *me = unsmob_grob (smob);
117   Real staff_space = Staff_symbol_referencer::staff_space (me);
118   Real staff_size;
119   Real thickness = me->get_paper ()->get_realvar (ly_symbol2scm ("linethickness"));
120   SCM lt =  me->get_grob_property ("thickness");
121   if (gh_number_p (lt))
122     thickness *= gh_scm2double (lt);
123   if (Staff_symbol_referencer::get_staff_symbol (me))
124     {
125       staff_size = (Staff_symbol_referencer::line_count (me) - 1) * staff_space;
126     }
127   else
128     staff_size = 0.0;
129
130   Real blotdiameter = me->get_paper ()->get_realvar (ly_symbol2scm ("blotdiameter"));
131
132   // like a "|" type bar
133   Interval xdim (0, thickness);
134   Interval ydim (-0.5 * staff_size, +0.5 * staff_size);
135   Box b (xdim, ydim);
136   Molecule out = Lookup::round_filled_box (b, blotdiameter);
137   return out.smobbed_copy ();
138 }
139
140 /*
141   Gregorian chant finalis.
142  */
143 MAKE_SCHEME_CALLBACK (Breathing_sign,finalis,1);
144 SCM 
145 Breathing_sign::finalis (SCM smob)
146 {
147   Grob *me = unsmob_grob (smob);
148   Real staff_space = Staff_symbol_referencer::staff_space (me);
149   Real staff_size;
150   Real thickness = me->get_paper ()->get_realvar (ly_symbol2scm ("linethickness"));
151   SCM lt =  me->get_grob_property ("thickness");
152   if (gh_number_p (lt))
153     thickness *= gh_scm2double (lt);
154   if (Staff_symbol_referencer::get_staff_symbol (me))
155     {
156       staff_size = (Staff_symbol_referencer::line_count (me) - 1) * staff_space;
157     }
158   else
159     staff_size = 0.0;
160
161   Real blotdiameter = me->get_paper ()->get_realvar (ly_symbol2scm ("blotdiameter"));
162
163   // like a "||" type bar
164   Interval xdim (0, thickness);
165   Interval ydim (-0.5 * staff_size, +0.5 * staff_size);
166   Box b (xdim, ydim);
167   Molecule line1 = Lookup::round_filled_box (b, blotdiameter);
168   Molecule line2 (line1);
169   line2.translate_axis (0.5 * staff_space, X_AXIS);
170   line1.add_molecule (line2);
171
172   return line1.smobbed_copy ();
173 }
174
175 MAKE_SCHEME_CALLBACK (Breathing_sign,offset_callback,2);
176 SCM
177 Breathing_sign::offset_callback (SCM element_smob, SCM)
178 {
179   Grob *me = unsmob_grob (element_smob);
180   
181   Direction d = Directional_element_interface::get (me);
182   if (!d)
183     {
184       d = UP;
185       Directional_element_interface::set (me, d);
186     }
187
188   Real inter_f = Staff_symbol_referencer::staff_space (me)/2;
189   int sz = Staff_symbol_referencer::line_count (me)-1;
190   return gh_double2scm (inter_f * sz * d);
191 }
192
193 ADD_INTERFACE(Breathing_sign, "breathing-sign-interface",
194               "A breathing sign.",
195               "direction");