2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 1997--2011 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"
33 MAKE_SCHEME_CALLBACK (Rest, y_offset_callback, 1);
35 Rest::y_offset_callback (SCM smob)
37 Grob *me = unsmob_grob (smob);
38 int duration_log = scm_to_int (me->get_property ("duration-log"));
39 int line_count = Staff_symbol_referencer::line_count (me);
40 Real ss = Staff_symbol_referencer::staff_space (me);
42 bool position_override = scm_is_number (me->get_property ("staff-position"));
43 Real amount = robust_scm2double (me->get_property ("staff-position"), 0)
48 if (duration_log == 0 && line_count > 1)
54 if (!position_override)
55 amount += 2 * ss * get_grob_direction (me);
58 return scm_from_double (amount);
61 /* A rest might lie under a beam, in which case it should be cross-staff if
62 the beam is cross-staff because the rest's position depends on the
63 formatting of the beam. */
64 MAKE_SCHEME_CALLBACK (Rest, calc_cross_staff, 1);
66 Rest::calc_cross_staff (SCM smob)
68 Grob *me = unsmob_grob (smob);
69 Grob *stem = unsmob_grob (me->get_object ("stem"));
74 return stem->get_property ("cross-staff");
78 make this function easily usable in C++
81 Rest::glyph_name (Grob *me, int balltype, string style, bool try_ledgers)
83 bool is_ledgered = false;
84 if (try_ledgers && (balltype == -1 || balltype == 0 || balltype == 1))
86 Real rad = Staff_symbol_referencer::staff_radius (me) * 2.0;
87 Real pos = Staff_symbol_referencer::get_position (me);
90 Figure out when the rest is far enough outside the staff. This
91 could bemore generic, but hey, we understand this even after
94 is_ledgered |= (balltype == -1) && (pos <= -rad - 3 || pos >= +rad + 1);
95 is_ledgered |= (balltype == 0) && (pos >= +rad + 2 || pos < -rad);
96 is_ledgered |= (balltype == 1) && (pos <= -rad - 2 || pos > +rad);
99 string actual_style (style.c_str ());
101 if ((style == "mensural") || (style == "neomensural"))
105 FIXME: Currently, ancient font does not provide ledgered rests;
106 hence the "o" suffix in the glyph name is bogus. But do we need
107 ledgered rests at all now that we can draw ledger lines with
108 variable width, length and blotdiameter? -- jr
113 There are no 32th/64th/128th mensural/neomensural rests. In
114 these cases, revert back to default style.
120 if ((style == "classical") && (balltype != 2))
123 classical style: revert back to default style for any rest other
129 if (style == "default")
132 Some parts of lily still prefer style "default" over "".
133 Correct this here. -- jr
138 return ("rests." + to_string (balltype) + (is_ledgered ? "o" : "")
142 MAKE_SCHEME_CALLBACK (Rest, print, 1);
144 Rest::brew_internal_stencil (Grob *me, bool ledgered)
146 SCM balltype_scm = me->get_property ("duration-log");
147 if (!scm_is_number (balltype_scm))
148 return Stencil ().smobbed_copy ();
150 int balltype = scm_to_int (balltype_scm);
153 SCM style_scm = me->get_property ("style");
154 if (scm_is_symbol (style_scm))
155 style = ly_scm2string (scm_symbol_to_string (style_scm));
157 Font_metric *fm = Font_interface::get_default_font (me);
158 string font_char = glyph_name (me, balltype, style, ledgered);
159 Stencil out = fm->find_by_name (font_char);
161 me->warning (_f ("rest `%s' not found", font_char.c_str ()));
163 return out.smobbed_copy ();
167 translate the rest vertically by amount DY, but only if
168 it doesn't have staff-position set.
171 Rest::translate (Grob *me, int dy)
173 if (!scm_is_number (me->get_property ("staff-position")))
175 me->translate_axis (dy * Staff_symbol_referencer::staff_space (me) / 2.0, Y_AXIS);
176 Grob *p = me->get_parent (Y_AXIS);
177 p->flush_extent_cache (Y_AXIS);
182 Rest::print (SCM smob)
184 return brew_internal_stencil (unsmob_grob (smob), true);
187 MAKE_SCHEME_CALLBACK (Rest, width, 1);
189 We need the callback. The real stencil has ledgers depending on
190 Y-position. The Y-position is known only after line breaking. */
192 Rest::width (SCM smob)
194 return generic_extent_callback (unsmob_grob (smob), X_AXIS);
197 MAKE_SCHEME_CALLBACK (Rest, height, 1);
199 Rest::height (SCM smob)
201 return generic_extent_callback (unsmob_grob (smob), Y_AXIS);
205 We need the callback. The real stencil has ledgers depending on
206 Y-position. The Y-position is known only after line breaking. */
208 Rest::generic_extent_callback (Grob *me, Axis a)
211 Don't want ledgers: ledgers depend on Y position, which depends on
212 rest collision, which depends on stem size which depends on beam
213 slop of opposite note column.
215 consequence: we get too small extents and potential collisions
218 SCM m = brew_internal_stencil (me, a != X_AXIS);
219 return ly_interval2scm (unsmob_stencil (m)->extent (a));
222 MAKE_SCHEME_CALLBACK (Rest, pure_height, 3);
224 Rest::pure_height (SCM smob,
228 Grob *me = unsmob_grob (smob);
229 SCM m = brew_internal_stencil (me, false);
230 return ly_interval2scm (unsmob_stencil (m)->extent (Y_AXIS));
234 "A rest symbol. The property @code{style} can be"
235 " @code{default}, @code{mensural}, @code{neomensural} or"
236 " @code{classical}.",