]> git.donarmstrong.com Git - lilypond.git/blob - lily/breathing-sign.cc
*** empty log message ***
[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:
28  * stafflinethickness) rather than hardwired to (staff_space / 6).
29  */
30
31 /*
32   WTF: what does Breathing_sign have to do with text?!
33
34   --hwn
35  */
36 MAKE_SCHEME_CALLBACK (Breathing_sign,brew_molecule,1);
37 SCM 
38 Breathing_sign::brew_molecule (SCM smob)
39 {
40   Grob *me = unsmob_grob (smob);
41   SCM text = me->get_grob_property ("text");
42   if (text == SCM_EOL)
43     return divisio_minima (smob);
44   SCM properties = Font_interface::font_alist_chain (me);
45   Molecule out = Text_item::interpret_new_markup (smob, properties, text);
46   SCM space_scm = me->get_grob_property ("word-space");
47   if (gh_number_p (space_scm))
48     {
49       Molecule mol;
50       mol.set_empty (false);
51       out.add_at_edge (X_AXIS, RIGHT, mol, gh_scm2double (space_scm) *
52                        Staff_symbol_referencer::staff_space (me), 0);
53     }
54   return out.smobbed_copy ();
55 }
56
57 /*
58   Simplistic caesura.
59  */
60 MAKE_SCHEME_CALLBACK (Breathing_sign,railtracks,1);
61 SCM 
62 Breathing_sign::railtracks (SCM smob)
63 {
64   Grob * me = unsmob_grob (smob);
65   Real space = Staff_symbol_referencer::staff_space (me);
66   Real th = me->get_paper ()->get_realvar (ly_symbol2scm ("linethickness"));
67   SCM lt =  me->get_grob_property ("thickness");
68   if (gh_number_p (lt))
69     th *= gh_scm2double (lt);
70   
71   Offset x1 (0, -space);
72   Offset x2 (space / 3, space);
73   Molecule l1 (Lookup::line (th, x1, x2));
74   Molecule l2 (l1);
75   l2.translate_axis (space *0.6 , X_AXIS);
76   l1.add_molecule (l2);
77   return l1.smobbed_copy();
78 }
79
80 /*
81   Gregorian chant divisio minima.  (Actually, this was the original
82   breathing sign by Michael. -- jr)
83  */
84 MAKE_SCHEME_CALLBACK (Breathing_sign,divisio_minima,1);
85 SCM 
86 Breathing_sign::divisio_minima (SCM smob)
87 {
88   Grob *me = unsmob_grob (smob);
89   Real staff_space = Staff_symbol_referencer::staff_space (me);
90   Real staff_size;
91   Real thickness = me->get_paper ()->get_realvar (ly_symbol2scm ("linethickness"));
92   SCM lt =  me->get_grob_property ("thickness");
93   if (gh_number_p (lt))
94     thickness *= gh_scm2double (lt);
95   if (Staff_symbol_referencer::get_staff_symbol (me))
96     {
97       staff_size = (Staff_symbol_referencer::line_count (me) - 1) * staff_space;
98     }
99   else
100     staff_size = 0.0;
101
102   Real blotdiameter = me->get_paper ()->get_realvar (ly_symbol2scm ("blotdiameter"));
103
104   /*
105    * Draw a small vertical line through the uppermost (or, depending
106    * on direction, lowermost) staff line.
107    */
108   Interval xdim (0, thickness);
109   Interval ydim (-0.5 * staff_space, +0.5 * staff_space);
110   Box b (xdim, ydim);
111   Molecule out = Lookup::roundfilledbox (b, blotdiameter);
112   return out.smobbed_copy ();
113 }
114
115 /*
116   Gregorian chant divisio maior.
117  */
118 MAKE_SCHEME_CALLBACK (Breathing_sign,divisio_maior,1);
119 SCM 
120 Breathing_sign::divisio_maior (SCM smob)
121 {
122   Grob *me = unsmob_grob (smob);
123   Real staff_space = Staff_symbol_referencer::staff_space (me);
124   Real staff_size;
125   Real thickness = me->get_paper ()->get_realvar (ly_symbol2scm ("linethickness"));
126   SCM lt =  me->get_grob_property ("thickness");
127   if (gh_number_p (lt))
128     thickness *= gh_scm2double (lt);
129   if (Staff_symbol_referencer::get_staff_symbol (me))
130     {
131       staff_size = (Staff_symbol_referencer::line_count (me) - 1) * staff_space;
132     }
133   else
134     staff_size = 0.0;
135
136   Real blotdiameter = me->get_paper ()->get_realvar (ly_symbol2scm ("blotdiameter"));
137
138   /*
139    * Draw a vertical line that is vertically centered in the staff
140    * (just like a bar).  The height of this line should be a little
141    * more than half the size of the staff, such that the endings of
142    * the line are in the middle of a staff space.
143    */
144   int lines = Staff_symbol_referencer::line_count (me);
145   int height = lines / 2; // little more than half of staff size
146   if ((lines & 1) != (height & 1))
147     height++; // ensure endings are centered in staff space
148
149   Interval xdim (0, thickness);
150   Interval ydim (-0.5 * height, +0.5 * height);
151   Box b (xdim, ydim);
152   Molecule out = Lookup::roundfilledbox (b, blotdiameter);
153   return out.smobbed_copy ();
154 }
155
156 /*
157   Gregorian chant divisio maxima.
158  */
159 MAKE_SCHEME_CALLBACK (Breathing_sign,divisio_maxima,1);
160 SCM 
161 Breathing_sign::divisio_maxima (SCM smob)
162 {
163   Grob *me = unsmob_grob (smob);
164   Real staff_space = Staff_symbol_referencer::staff_space (me);
165   Real staff_size;
166   Real thickness = me->get_paper ()->get_realvar (ly_symbol2scm ("linethickness"));
167   SCM lt =  me->get_grob_property ("thickness");
168   if (gh_number_p (lt))
169     thickness *= gh_scm2double (lt);
170   if (Staff_symbol_referencer::get_staff_symbol (me))
171     {
172       staff_size = (Staff_symbol_referencer::line_count (me) - 1) * staff_space;
173     }
174   else
175     staff_size = 0.0;
176
177   Real blotdiameter = me->get_paper ()->get_realvar (ly_symbol2scm ("blotdiameter"));
178
179   // like a "|" type bar
180   Interval xdim (0, thickness);
181   Interval ydim (-0.5 * staff_size, +0.5 * staff_size);
182   Box b (xdim, ydim);
183   Molecule out = Lookup::roundfilledbox (b, blotdiameter);
184   return out.smobbed_copy ();
185 }
186
187 /*
188   Gregorian chant finalis.
189  */
190 MAKE_SCHEME_CALLBACK (Breathing_sign,finalis,1);
191 SCM 
192 Breathing_sign::finalis (SCM smob)
193 {
194   Grob *me = unsmob_grob (smob);
195   Real staff_space = Staff_symbol_referencer::staff_space (me);
196   Real staff_size;
197   Real thickness = me->get_paper ()->get_realvar (ly_symbol2scm ("linethickness"));
198   SCM lt =  me->get_grob_property ("thickness");
199   if (gh_number_p (lt))
200     thickness *= gh_scm2double (lt);
201   if (Staff_symbol_referencer::get_staff_symbol (me))
202     {
203       staff_size = (Staff_symbol_referencer::line_count (me) - 1) * staff_space;
204     }
205   else
206     staff_size = 0.0;
207
208   Real blotdiameter = me->get_paper ()->get_realvar (ly_symbol2scm ("blotdiameter"));
209
210   // like a "||" type bar
211   Interval xdim (0, thickness);
212   Interval ydim (-0.5 * staff_size, +0.5 * staff_size);
213   Box b (xdim, ydim);
214   Molecule line1 = Lookup::roundfilledbox (b, blotdiameter);
215   Molecule line2 (line1);
216   line2.translate_axis (0.5 * staff_space, X_AXIS);
217   line1.add_molecule (line2);
218
219   return line1.smobbed_copy ();
220 }
221
222 MAKE_SCHEME_CALLBACK (Breathing_sign,offset_callback,2);
223 SCM
224 Breathing_sign::offset_callback (SCM element_smob, SCM)
225 {
226   Grob *me = unsmob_grob (element_smob);
227   
228   Direction d = Directional_element_interface::get (me);
229   if (!d)
230     {
231       d = UP;
232       Directional_element_interface::set (me, d);
233     }
234
235   Real inter_f = Staff_symbol_referencer::staff_space (me)/2;
236   int sz = Staff_symbol_referencer::line_count (me)-1;
237   return gh_double2scm (inter_f * sz * d);
238 }
239
240 ADD_INTERFACE(Breathing_sign, "breathing-sign-interface",
241               "A breathing sign.",
242               "direction");