2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 1999--2014 Michael Krause
5 Extensions for ancient notation (c) 2003--2014 by Juergen Reuter
7 LilyPond is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 LilyPond is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
21 #include "breathing-sign.hh"
23 #include "dimensions.hh"
24 #include "direction.hh"
25 #include "directional-element-interface.hh"
26 #include "font-interface.hh"
29 #include "output-def.hh"
30 #include "staff-symbol.hh"
31 #include "staff-symbol-referencer.hh"
32 #include "text-interface.hh"
35 UGH : this is full of C&P code. Consolidate! --hwn
39 Gregorian chant divisio minima. (Actually, this was the original
40 breathing sign by Michael. -- jr)
42 MAKE_SCHEME_CALLBACK (Breathing_sign, divisio_minima, 1);
44 Breathing_sign::divisio_minima (SCM smob)
46 Grob *me = unsmob_grob (smob);
47 Real staff_space = Staff_symbol_referencer::staff_space (me);
49 Real thickness = Staff_symbol_referencer::line_thickness (me);
50 thickness *= robust_scm2double (me->get_property ("thickness"), 1.0);
52 Real blotdiameter = me->layout ()->get_dimension (ly_symbol2scm ("blot-diameter"));
55 * Draw a small vertical line through the uppermost (or, depending
56 * on direction, lowermost) staff line.
58 Interval xdim (0, thickness);
59 Interval ydim (-0.5 * staff_space, +0.5 * staff_space);
61 Stencil out = Lookup::round_filled_box (b, blotdiameter);
62 return out.smobbed_copy ();
66 Gregorian chant divisio maior.
68 MAKE_SCHEME_CALLBACK (Breathing_sign, divisio_maior, 1);
70 Breathing_sign::divisio_maior (SCM smob)
72 Grob *me = unsmob_grob (smob);
73 Real thickness = Staff_symbol_referencer::line_thickness (me);
74 thickness *= robust_scm2double (me->get_property ("thickness"), 1.0);
76 Real blotdiameter = me->layout ()->get_dimension (ly_symbol2scm ("blot-diameter"));
79 Draw a vertical line that is roughly centered vertically in
80 the staff (just like a bar) with the following requirements:
81 1. length should be at least half the size of the staff
82 2. both ends should be in the middle of a staff space.
84 These two requirements contradict if the first or last space is
85 larger than half of the whole staff (e.g. the staff consists of
86 two lines only); in such cases the first prescription wins.
88 Interval ydim (0.0, 0.0);
89 if (Grob *staff = Staff_symbol_referencer::get_staff_symbol (me))
91 std::vector<Real> line_pos = Staff_symbol::line_positions (staff);
92 if (!line_pos.empty ())
94 std::sort (line_pos.begin (), line_pos.end ());
95 ydim[DOWN] = line_pos.front ();
96 ydim[UP] = line_pos.back ();
97 if (Real const height = ydim.length ())
99 ydim.widen (-0.25 * height);
102 ydim has now the required height; to satisfy req. 2
103 find the staff spaces containing current endpoints.
105 standard algorithms are suitable to find the upper
106 line of these spaces; we must choose between
107 upper_bound and lower_bound considering that if
108 there's a line exactly at quarter of the staff (the
109 lower end) then we need the space below it, while if
110 there's a line exactly at three quarters of the staff
111 (upper end) then we need the space above it.
113 if the middle of the space found is not low/high
114 enough, take the next space (if there are no more
115 spaces, ydim won't be enlarged further).
117 std::vector<Real>::const_iterator it
118 = std::lower_bound (line_pos.begin (), line_pos.end (),
120 assert (line_pos.begin () < it);
121 double val = (it[-1] + it[0]) / 2;
122 if (ydim[DOWN] < val && line_pos.begin () < it + 1)
123 val = (it[-2] + it[-1]) / 2;
124 ydim.add_point (val);
126 it = std::upper_bound (line_pos.begin (), line_pos.end (),
128 assert (it < line_pos.end ());
129 val = (it[-1] + it[0]) / 2;
130 if (val < ydim[UP] && it + 1 < line_pos.end ())
131 val = (it[0] + it[1]) / 2;
132 ydim.add_point (val);
137 ydim *= Staff_symbol_referencer::staff_space (me) / 2;
139 Interval xdim (0, thickness);
141 Stencil out = Lookup::round_filled_box (b, blotdiameter);
142 return out.smobbed_copy ();
146 Gregorian chant divisio maxima.
148 MAKE_SCHEME_CALLBACK (Breathing_sign, divisio_maxima, 1);
150 Breathing_sign::divisio_maxima (SCM smob)
152 Grob *me = unsmob_grob (smob);
153 Real staff_space = Staff_symbol_referencer::staff_space (me);
154 Real thickness = Staff_symbol_referencer::line_thickness (me);
155 thickness *= robust_scm2double (me->get_property ("thickness"), 1.0);
157 Real blotdiameter = me->layout ()->get_dimension (ly_symbol2scm ("blot-diameter"));
159 // like a "|" type bar
160 Interval xdim (0, thickness);
161 Interval ydim = Staff_symbol_referencer::staff_span (me);
162 ydim *= staff_space / 2;
164 Stencil out = Lookup::round_filled_box (b, blotdiameter);
165 return out.smobbed_copy ();
169 Gregorian chant finalis.
171 MAKE_SCHEME_CALLBACK (Breathing_sign, finalis, 1);
173 Breathing_sign::finalis (SCM smob)
175 Grob *me = unsmob_grob (smob);
176 Real staff_space = Staff_symbol_referencer::staff_space (me);
177 Real thickness = Staff_symbol_referencer::line_thickness (me);
178 thickness *= robust_scm2double (me->get_property ("thickness"), 1.0);
180 Real blotdiameter = me->layout ()->get_dimension (ly_symbol2scm ("blot-diameter"));
182 // like a "||" type bar
183 Interval xdim (0, thickness);
184 Interval ydim = Staff_symbol_referencer::staff_span (me);
185 ydim *= staff_space / 2;
187 Stencil line1 = Lookup::round_filled_box (b, blotdiameter);
188 Stencil line2 (line1);
189 line2.translate_axis (0.5 * staff_space, X_AXIS);
190 line1.add_stencil (line2);
192 return line1.smobbed_copy ();
195 MAKE_SCHEME_CALLBACK (Breathing_sign, offset_callback, 1);
197 Breathing_sign::offset_callback (SCM smob)
199 Grob *me = unsmob_grob (smob);
201 Direction d = get_grob_direction (me);
205 set_grob_direction (me, d);
208 Grob *staff = Staff_symbol_referencer::get_staff_symbol (me);
211 Interval iv = Staff_symbol::line_span (staff);
212 Real inter = Staff_symbol::staff_space (staff) / 2;
213 return scm_from_double (inter * iv[d]);
216 return scm_from_double (0.0);
219 ADD_INTERFACE (Breathing_sign,