2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 1997--2012 Han-Wen Nienhuys <hanwen@xs4all.nl>
6 LilyPond is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 LilyPond is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
22 #include "directional-element-interface.hh"
24 #include "font-interface.hh"
25 #include "international.hh"
26 #include "output-def.hh"
27 #include "paper-score.hh"
28 #include "staff-symbol-referencer.hh"
29 #include "staff-symbol.hh"
34 MAKE_SCHEME_CALLBACK (Rest, y_offset_callback, 1);
36 Rest::y_offset_callback (SCM smob)
38 Grob *me = unsmob_grob (smob);
39 int duration_log = scm_to_int (me->get_property ("duration-log"));
40 int line_count = Staff_symbol_referencer::line_count (me);
41 Real ss = Staff_symbol_referencer::staff_space (me);
43 bool position_override = scm_is_number (me->get_property ("staff-position"));
46 if (position_override)
49 robust_scm2double (me->get_property ("staff-position"), 0) * 0.5 * ss;
52 semibreve rests are positioned one staff line off
54 if (duration_log == 0)
58 trust the client on good positioning;
59 would be tempting to adjust position of rests longer than a quarter
60 to be properly aligned to staff lines,
61 but custom rest shapes may not need that sort of care.
66 int pos = 4 * get_grob_direction (me);
69 make a semibreve rest hang from the next line,
70 except for a single line staff
72 if (duration_log == 0 && line_count > 1)
76 make sure rest is aligned to a staff line
78 if (Grob *staff = Staff_symbol_referencer::get_staff_symbol(me))
80 std::vector<Real> linepos = Staff_symbol::line_positions (staff);
81 std::sort(linepos.begin(), linepos.end());
82 std::vector<Real>::const_iterator it
83 = std::lower_bound(linepos.begin(), linepos.end(), pos);
84 if (it != linepos.end())
90 amount = ss * 0.5 * pos;
93 return scm_from_double (amount);
96 /* A rest might lie under a beam, in which case it should be cross-staff if
97 the beam is cross-staff because the rest's position depends on the
98 formatting of the beam. */
99 MAKE_SCHEME_CALLBACK (Rest, calc_cross_staff, 1);
101 Rest::calc_cross_staff (SCM smob)
103 Grob *me = unsmob_grob (smob);
104 Grob *stem = unsmob_grob (me->get_object ("stem"));
109 return stem->get_property ("cross-staff");
113 make this function easily usable in C++
116 Rest::glyph_name (Grob *me, int durlog, string style, bool try_ledgers)
118 bool is_ledgered = false;
119 if (try_ledgers && (durlog == -1 || durlog == 0 || durlog == 1))
121 int const pos = int (Staff_symbol_referencer::get_position (me));
124 half rests need ledger if not lying on a staff line,
125 whole rests need ledger if not hanging from a staff line,
126 breve rests need ledger if neither lying on nor hanging from a staff line
128 if (-1 <= durlog && durlog <= 1)
129 is_ledgered = !Staff_symbol_referencer::on_staff_line (me, pos)
131 && Staff_symbol_referencer::on_staff_line (me, pos + 2));
134 string actual_style (style.c_str ());
136 if ((style == "mensural") || (style == "neomensural"))
140 FIXME: Currently, ancient font does not provide ledgered rests;
141 hence the "o" suffix in the glyph name is bogus. But do we need
142 ledgered rests at all now that we can draw ledger lines with
143 variable width, length and blotdiameter? -- jr
148 There are no 32th/64th/128th mensural/neomensural rests. In
149 these cases, revert back to default style.
155 if ((style == "classical") && (durlog != 2))
158 classical style: revert back to default style for any rest other
164 if (style == "default")
167 Some parts of lily still prefer style "default" over "".
168 Correct this here. -- jr
173 return ("rests." + to_string (durlog) + (is_ledgered ? "o" : "")
177 MAKE_SCHEME_CALLBACK (Rest, print, 1);
179 Rest::brew_internal_stencil (Grob *me, bool ledgered)
181 SCM durlog_scm = me->get_property ("duration-log");
182 if (!scm_is_number (durlog_scm))
183 return Stencil ().smobbed_copy ();
185 int durlog = scm_to_int (durlog_scm);
187 string style = robust_symbol2string (me->get_property ("style"), "default");
189 Font_metric *fm = Font_interface::get_default_font (me);
190 string font_char = glyph_name (me, durlog, style, ledgered);
191 Stencil out = fm->find_by_name (font_char);
193 me->warning (_f ("rest `%s' not found", font_char.c_str ()));
195 return out.smobbed_copy ();
199 translate the rest vertically by amount DY, but only if
200 it doesn't have staff-position set.
203 Rest::translate (Grob *me, int dy)
205 if (!scm_is_number (me->get_property ("staff-position")))
207 me->translate_axis (dy * Staff_symbol_referencer::staff_space (me) / 2.0, Y_AXIS);
208 Grob *p = me->get_parent (Y_AXIS);
209 p->flush_extent_cache (Y_AXIS);
214 Rest::print (SCM smob)
216 return brew_internal_stencil (unsmob_grob (smob), true);
219 MAKE_SCHEME_CALLBACK (Rest, width, 1);
221 We need the callback. The real stencil has ledgers depending on
222 Y-position. The Y-position is known only after line breaking. */
224 Rest::width (SCM smob)
226 return generic_extent_callback (unsmob_grob (smob), X_AXIS);
229 MAKE_SCHEME_CALLBACK (Rest, height, 1);
231 Rest::height (SCM smob)
233 return generic_extent_callback (unsmob_grob (smob), Y_AXIS);
237 We need the callback. The real stencil has ledgers depending on
238 Y-position. The Y-position is known only after line breaking. */
240 Rest::generic_extent_callback (Grob *me, Axis a)
243 Don't want ledgers: ledgers depend on Y position, which depends on
244 rest collision, which depends on stem size which depends on beam
245 slop of opposite note column.
247 consequence: we get too small extents and potential collisions
250 SCM m = brew_internal_stencil (me, a != X_AXIS);
251 return ly_interval2scm (unsmob_stencil (m)->extent (a));
254 MAKE_SCHEME_CALLBACK (Rest, pure_height, 3);
256 Rest::pure_height (SCM smob,
260 Grob *me = unsmob_grob (smob);
261 SCM m = brew_internal_stencil (me, false);
262 return ly_interval2scm (unsmob_stencil (m)->extent (Y_AXIS));
266 "A rest symbol. The property @code{style} can be"
267 " @code{default}, @code{mensural}, @code{neomensural} or"
268 " @code{classical}.",