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);
57 return scm_from_double (amount);
60 /* A rest might lie under a beam, in which case it should be cross-staff if
61 the beam is cross-staff because the rest's position depends on the
62 formatting of the beam. */
63 MAKE_SCHEME_CALLBACK (Rest, calc_cross_staff, 1);
65 Rest::calc_cross_staff (SCM smob)
67 Grob *me = unsmob_grob (smob);
68 Grob *stem = unsmob_grob (me->get_object ("stem"));
73 return stem->get_property ("cross-staff");
77 make this function easily usable in C++
80 Rest::glyph_name (Grob *me, int balltype, string style, bool try_ledgers)
82 bool is_ledgered = false;
83 if (try_ledgers && (balltype == -1 || balltype == 0 || balltype == 1))
85 Real rad = Staff_symbol_referencer::staff_radius (me) * 2.0;
86 Real pos = Staff_symbol_referencer::get_position (me);
89 Figure out when the rest is far enough outside the staff. This
90 could bemore generic, but hey, we understand this even after
93 is_ledgered |= (balltype == -1) && (pos <= -rad - 3 || pos >= +rad + 1);
94 is_ledgered |= (balltype == 0) && (pos >= +rad + 2 || pos < -rad);
95 is_ledgered |= (balltype == 1) && (pos <= -rad - 2 || pos > +rad);
98 string actual_style (style.c_str ());
100 if ((style == "mensural") || (style == "neomensural"))
104 FIXME: Currently, ancient font does not provide ledgered rests;
105 hence the "o" suffix in the glyph name is bogus. But do we need
106 ledgered rests at all now that we can draw ledger lines with
107 variable width, length and blotdiameter? -- jr
112 There are no 32th/64th/128th mensural/neomensural rests. In
113 these cases, revert back to default style.
119 if ((style == "classical") && (balltype != 2))
122 classical style: revert back to default style for any rest other
128 if (style == "default")
131 Some parts of lily still prefer style "default" over "".
132 Correct this here. -- jr
137 return ("rests." + to_string (balltype) + (is_ledgered ? "o" : "")
141 MAKE_SCHEME_CALLBACK (Rest, print, 1);
143 Rest::brew_internal_stencil (Grob *me, bool ledgered)
145 SCM balltype_scm = me->get_property ("duration-log");
146 if (!scm_is_number (balltype_scm))
147 return Stencil ().smobbed_copy ();
149 int balltype = scm_to_int (balltype_scm);
151 string style = robust_symbol2string (me->get_property ("style"), "default");
153 Font_metric *fm = Font_interface::get_default_font (me);
154 string font_char = glyph_name (me, balltype, style, ledgered);
155 Stencil out = fm->find_by_name (font_char);
157 me->warning (_f ("rest `%s' not found", font_char.c_str ()));
159 return out.smobbed_copy ();
163 translate the rest vertically by amount DY, but only if
164 it doesn't have staff-position set.
167 Rest::translate (Grob *me, int dy)
169 if (!scm_is_number (me->get_property ("staff-position")))
171 me->translate_axis (dy * Staff_symbol_referencer::staff_space (me) / 2.0, Y_AXIS);
172 Grob *p = me->get_parent (Y_AXIS);
173 p->flush_extent_cache (Y_AXIS);
178 Rest::print (SCM smob)
180 return brew_internal_stencil (unsmob_grob (smob), true);
183 MAKE_SCHEME_CALLBACK (Rest, width, 1);
185 We need the callback. The real stencil has ledgers depending on
186 Y-position. The Y-position is known only after line breaking. */
188 Rest::width (SCM smob)
190 return generic_extent_callback (unsmob_grob (smob), X_AXIS);
193 MAKE_SCHEME_CALLBACK (Rest, height, 1);
195 Rest::height (SCM smob)
197 return generic_extent_callback (unsmob_grob (smob), Y_AXIS);
201 We need the callback. The real stencil has ledgers depending on
202 Y-position. The Y-position is known only after line breaking. */
204 Rest::generic_extent_callback (Grob *me, Axis a)
207 Don't want ledgers: ledgers depend on Y position, which depends on
208 rest collision, which depends on stem size which depends on beam
209 slop of opposite note column.
211 consequence: we get too small extents and potential collisions
214 SCM m = brew_internal_stencil (me, a != X_AXIS);
215 return ly_interval2scm (unsmob_stencil (m)->extent (a));
218 MAKE_SCHEME_CALLBACK (Rest, pure_height, 3);
220 Rest::pure_height (SCM smob,
224 Grob *me = unsmob_grob (smob);
225 SCM m = brew_internal_stencil (me, false);
226 return ly_interval2scm (unsmob_stencil (m)->extent (Y_AXIS));
230 "A rest symbol. The property @code{style} can be"
231 " @code{default}, @code{mensural}, @code{neomensural} or"
232 " @code{classical}.",