]> git.donarmstrong.com Git - lilypond.git/blob - lily/breathing-sign.cc
* flower
[lilypond.git] / lily / breathing-sign.cc
1 /*
2   breathing_sign.cc -- implement Breathing_sign
3
4   (c) 1999--2005 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--2005 by Juergen Reuter
11 */
12
13 #include "breathing-sign.hh"
14
15 #include "staff-symbol-referencer.hh"
16 #include "directional-element-interface.hh"
17 #include "output-def.hh"
18 #include "lookup.hh"
19 #include "dimensions.hh"
20 #include "direction.hh"
21 #include "text-item.hh"
22 #include "font-interface.hh"
23
24 /*
25   TODO: thickness should be a grob property (unit: linethickness)
26   rather than hardwired to (staff_space / 6).
27 */
28
29 /*
30   UGH : this is full of C&P code. Consolidate!  --hwn
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
45   Real thickness = Staff_symbol_referencer::line_thickness (me);
46   thickness *= robust_scm2double (me->get_property ("thickness"), 1.0);
47   if (Staff_symbol_referencer::get_staff_symbol (me))
48     {
49       staff_size = (Staff_symbol_referencer::line_count (me) - 1) * staff_space;
50     }
51   else
52     staff_size = 0.0;
53
54   Real blotdiameter = me->get_layout ()->get_dimension (ly_symbol2scm ("blotdiameter"));
55
56   /*
57    * Draw a small vertical line through the uppermost (or, depending
58    * on direction, lowermost) staff line.
59    */
60   Interval xdim (0, thickness);
61   Interval ydim (-0.5 * staff_space, +0.5 * staff_space);
62   Box b (xdim, ydim);
63   Stencil out = Lookup::round_filled_box (b, blotdiameter);
64   return out.smobbed_copy ();
65 }
66
67 /*
68   Gregorian chant divisio maior.
69 */
70 MAKE_SCHEME_CALLBACK (Breathing_sign, divisio_maior, 1);
71 SCM
72 Breathing_sign::divisio_maior (SCM smob)
73 {
74   Grob *me = unsmob_grob (smob);
75   Real staff_space = Staff_symbol_referencer::staff_space (me);
76   Real staff_size;
77   Real thickness = Staff_symbol_referencer::line_thickness (me);
78   thickness *= robust_scm2double (me->get_property ("thickness"), 1.0);
79
80   if (Staff_symbol_referencer::get_staff_symbol (me))
81     {
82       staff_size = (Staff_symbol_referencer::line_count (me) - 1) * staff_space;
83     }
84   else
85     staff_size = 0.0;
86
87   Real blotdiameter = me->get_layout ()->get_dimension (ly_symbol2scm ("blotdiameter"));
88
89   /*
90    * Draw a vertical line that is vertically centered in the staff
91    * (just like a bar).  The height of this line should be a little
92    * more than half the size of the staff, such that the endings of
93    * the line are in the middle of a staff space.
94    */
95   int lines = Staff_symbol_referencer::line_count (me);
96   int height = lines / 2; // little more than half of staff size
97   if ((lines & 1) != (height & 1))
98     height++; // ensure endings are centered in staff space
99
100   Interval xdim (0, thickness);
101   Interval ydim (-0.5 * height, +0.5 * height);
102   Box b (xdim, ydim);
103   Stencil out = Lookup::round_filled_box (b, blotdiameter);
104   return out.smobbed_copy ();
105 }
106
107 /*
108   Gregorian chant divisio maxima.
109 */
110 MAKE_SCHEME_CALLBACK (Breathing_sign, divisio_maxima, 1);
111 SCM
112 Breathing_sign::divisio_maxima (SCM smob)
113 {
114   Grob *me = unsmob_grob (smob);
115   Real staff_space = Staff_symbol_referencer::staff_space (me);
116   Real staff_size;
117   Real thickness = Staff_symbol_referencer::line_thickness (me);
118   thickness *= robust_scm2double (me->get_property ("thickness"), 1.0);
119
120   if (Staff_symbol_referencer::get_staff_symbol (me))
121     {
122       staff_size = (Staff_symbol_referencer::line_count (me) - 1) * staff_space;
123     }
124   else
125     staff_size = 0.0;
126
127   Real blotdiameter = me->get_layout ()->get_dimension (ly_symbol2scm ("blotdiameter"));
128
129   // like a "|" type bar
130   Interval xdim (0, thickness);
131   Interval ydim (-0.5 * staff_size, +0.5 * staff_size);
132   Box b (xdim, ydim);
133   Stencil out = Lookup::round_filled_box (b, blotdiameter);
134   return out.smobbed_copy ();
135 }
136
137 /*
138   Gregorian chant finalis.
139 */
140 MAKE_SCHEME_CALLBACK (Breathing_sign, finalis, 1);
141 SCM
142 Breathing_sign::finalis (SCM smob)
143 {
144   Grob *me = unsmob_grob (smob);
145   Real staff_space = Staff_symbol_referencer::staff_space (me);
146   Real staff_size;
147   Real thickness = Staff_symbol_referencer::line_thickness (me);
148   thickness *= robust_scm2double (me->get_property ("thickness"), 1.0);
149
150   if (Staff_symbol_referencer::get_staff_symbol (me))
151     {
152       staff_size = (Staff_symbol_referencer::line_count (me) - 1) * staff_space;
153     }
154   else
155     staff_size = 0.0;
156
157   Real blotdiameter = me->get_layout ()->get_dimension (ly_symbol2scm ("blotdiameter"));
158
159   // like a "||" type bar
160   Interval xdim (0, thickness);
161   Interval ydim (-0.5 * staff_size, +0.5 * staff_size);
162   Box b (xdim, ydim);
163   Stencil line1 = Lookup::round_filled_box (b, blotdiameter);
164   Stencil line2 (line1);
165   line2.translate_axis (0.5 * staff_space, X_AXIS);
166   line1.add_stencil (line2);
167
168   return line1.smobbed_copy ();
169 }
170
171 MAKE_SCHEME_CALLBACK (Breathing_sign, offset_callback, 2);
172 SCM
173 Breathing_sign::offset_callback (SCM element_smob, SCM)
174 {
175   Grob *me = unsmob_grob (element_smob);
176
177   Direction d = get_grob_direction (me);
178   if (!d)
179     {
180       d = UP;
181       set_grob_direction (me, d);
182     }
183
184   Real inter_f = Staff_symbol_referencer::staff_space (me) / 2;
185   int sz = Staff_symbol_referencer::line_count (me) - 1;
186   return scm_make_real (inter_f * sz * d);
187 }
188
189 ADD_INTERFACE (Breathing_sign, "breathing-sign-interface",
190                "A breathing sign.",
191                "direction");