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