]> git.donarmstrong.com Git - lilypond.git/blob - lily/breathing-sign.cc
* lily/lily-guile.cc (robust_scm2double): new function. Use throughout.
[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   UGH : this is full of C&P code. Consolidate!  --hwn
35 */
36
37 /*
38   Gregorian chant divisio minima.  (Actually, this was the original
39   breathing sign by Michael. -- jr)
40  */
41 MAKE_SCHEME_CALLBACK (Breathing_sign,divisio_minima,1);
42 SCM 
43 Breathing_sign::divisio_minima (SCM smob)
44 {
45   Grob *me = unsmob_grob (smob);
46   Real staff_space = Staff_symbol_referencer::staff_space (me);
47   Real staff_size;
48   Real thickness = me->get_paper ()->get_realvar (ly_symbol2scm ("linethickness"));
49   SCM lt =  me->get_grob_property ("thickness");
50   if (gh_number_p (lt))
51     thickness *= gh_scm2double (lt);
52   if (Staff_symbol_referencer::get_staff_symbol (me))
53     {
54       staff_size = (Staff_symbol_referencer::line_count (me) - 1) * staff_space;
55     }
56   else
57     staff_size = 0.0;
58
59   Real blotdiameter = me->get_paper ()->get_realvar (ly_symbol2scm ("blotdiameter"));
60
61   /*
62    * Draw a small vertical line through the uppermost (or, depending
63    * on direction, lowermost) staff line.
64    */
65   Interval xdim (0, thickness);
66   Interval ydim (-0.5 * staff_space, +0.5 * staff_space);
67   Box b (xdim, ydim);
68   Molecule out = Lookup::round_filled_box (b, blotdiameter);
69   return out.smobbed_copy ();
70 }
71
72 /*
73   Gregorian chant divisio maior.
74  */
75 MAKE_SCHEME_CALLBACK (Breathing_sign,divisio_maior,1);
76 SCM 
77 Breathing_sign::divisio_maior (SCM smob)
78 {
79   Grob *me = unsmob_grob (smob);
80   Real staff_space = Staff_symbol_referencer::staff_space (me);
81   Real staff_size;
82   Real thickness = me->get_paper ()->get_realvar (ly_symbol2scm ("linethickness"));
83   SCM lt =  me->get_grob_property ("thickness");
84   if (gh_number_p (lt))
85     thickness *= gh_scm2double (lt);
86   if (Staff_symbol_referencer::get_staff_symbol (me))
87     {
88       staff_size = (Staff_symbol_referencer::line_count (me) - 1) * staff_space;
89     }
90   else
91     staff_size = 0.0;
92
93   Real blotdiameter = me->get_paper ()->get_realvar (ly_symbol2scm ("blotdiameter"));
94
95   /*
96    * Draw a vertical line that is vertically centered in the staff
97    * (just like a bar).  The height of this line should be a little
98    * more than half the size of the staff, such that the endings of
99    * the line are in the middle of a staff space.
100    */
101   int lines = Staff_symbol_referencer::line_count (me);
102   int height = lines / 2; // little more than half of staff size
103   if ((lines & 1) != (height & 1))
104     height++; // ensure endings are centered in staff space
105
106   Interval xdim (0, thickness);
107   Interval ydim (-0.5 * height, +0.5 * height);
108   Box b (xdim, ydim);
109   Molecule out = Lookup::round_filled_box (b, blotdiameter);
110   return out.smobbed_copy ();
111 }
112
113 /*
114   Gregorian chant divisio maxima.
115  */
116 MAKE_SCHEME_CALLBACK (Breathing_sign,divisio_maxima,1);
117 SCM 
118 Breathing_sign::divisio_maxima (SCM smob)
119 {
120   Grob *me = unsmob_grob (smob);
121   Real staff_space = Staff_symbol_referencer::staff_space (me);
122   Real staff_size;
123   Real thickness = me->get_paper ()->get_realvar (ly_symbol2scm ("linethickness"));
124   SCM lt =  me->get_grob_property ("thickness");
125   if (gh_number_p (lt))
126     thickness *= gh_scm2double (lt);
127   if (Staff_symbol_referencer::get_staff_symbol (me))
128     {
129       staff_size = (Staff_symbol_referencer::line_count (me) - 1) * staff_space;
130     }
131   else
132     staff_size = 0.0;
133
134   Real blotdiameter = me->get_paper ()->get_realvar (ly_symbol2scm ("blotdiameter"));
135
136   // like a "|" type bar
137   Interval xdim (0, thickness);
138   Interval ydim (-0.5 * staff_size, +0.5 * staff_size);
139   Box b (xdim, ydim);
140   Molecule out = Lookup::round_filled_box (b, blotdiameter);
141   return out.smobbed_copy ();
142 }
143
144 /*
145   Gregorian chant finalis.
146  */
147 MAKE_SCHEME_CALLBACK (Breathing_sign,finalis,1);
148 SCM 
149 Breathing_sign::finalis (SCM smob)
150 {
151   Grob *me = unsmob_grob (smob);
152   Real staff_space = Staff_symbol_referencer::staff_space (me);
153   Real staff_size;
154   Real thickness = me->get_paper ()->get_realvar (ly_symbol2scm ("linethickness"));
155   SCM lt =  me->get_grob_property ("thickness");
156   if (gh_number_p (lt))
157     thickness *= gh_scm2double (lt);
158   if (Staff_symbol_referencer::get_staff_symbol (me))
159     {
160       staff_size = (Staff_symbol_referencer::line_count (me) - 1) * staff_space;
161     }
162   else
163     staff_size = 0.0;
164
165   Real blotdiameter = me->get_paper ()->get_realvar (ly_symbol2scm ("blotdiameter"));
166
167   // like a "||" type bar
168   Interval xdim (0, thickness);
169   Interval ydim (-0.5 * staff_size, +0.5 * staff_size);
170   Box b (xdim, ydim);
171   Molecule line1 = Lookup::round_filled_box (b, blotdiameter);
172   Molecule line2 (line1);
173   line2.translate_axis (0.5 * staff_space, X_AXIS);
174   line1.add_molecule (line2);
175
176   return line1.smobbed_copy ();
177 }
178
179 MAKE_SCHEME_CALLBACK (Breathing_sign,offset_callback,2);
180 SCM
181 Breathing_sign::offset_callback (SCM element_smob, SCM)
182 {
183   Grob *me = unsmob_grob (element_smob);
184   
185   Direction d = get_grob_direction (me);
186   if (!d)
187     {
188       d = UP;
189       set_grob_direction (me, d);
190     }
191
192   Real inter_f = Staff_symbol_referencer::staff_space (me)/2;
193   int sz = Staff_symbol_referencer::line_count (me)-1;
194   return gh_double2scm (inter_f * sz * d);
195 }
196
197 ADD_INTERFACE(Breathing_sign, "breathing-sign-interface",
198               "A breathing sign.",
199               "direction");