Fixes Issue 1504, allowing feather beam line breaking.
[lilypond/patrick.git] / lily / rest.cc
blob9b85523f80ae2840ad273f8b1626891ef8f7493c
1 /*
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/>.
20 #include "rest.hh"
22 #include "directional-element-interface.hh"
23 #include "dots.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 "stencil.hh"
30 #include "grob.hh"
32 // -> offset callback
33 MAKE_SCHEME_CALLBACK (Rest, y_offset_callback, 1);
34 SCM
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)
44 * 0.5 * ss;
46 if (line_count % 2)
48 if (duration_log == 0 && line_count > 1)
49 amount += ss;
51 else
52 amount += ss / 2;
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);
64 SCM
65 Rest::calc_cross_staff (SCM smob)
67 Grob *me = unsmob_grob (smob);
68 Grob *stem = unsmob_grob (me->get_object ("stem"));
70 if (!stem)
71 return SCM_BOOL_F;
73 return stem->get_property ("cross-staff");
77 make this function easily usable in C++
79 string
80 Rest::glyph_name (Grob *me, int balltype, string style, bool try_ledgers)
82 bool is_ledgered = false;
83 if (try_ledgers && (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
91 dinner.
93 is_ledgered |= (balltype == 0) && (pos >= +rad + 2 || pos < -rad);
94 is_ledgered |= (balltype == 1) && (pos <= -rad - 2 || pos > +rad);
97 string actual_style (style.c_str ());
99 if ((style == "mensural") || (style == "neomensural"))
103 FIXME: Currently, ancient font does not provide ledgered rests;
104 hence the "o" suffix in the glyph name is bogus. But do we need
105 ledgered rests at all now that we can draw ledger lines with
106 variable width, length and blotdiameter? -- jr
108 is_ledgered = 0;
111 There are no 32th/64th/128th mensural/neomensural rests. In
112 these cases, revert back to default style.
114 if (balltype > 4)
115 actual_style = "";
118 if ((style == "classical") && (balltype != 2))
121 classical style: revert back to default style for any rest other
122 than quarter rest
124 actual_style = "";
127 if (style == "default")
130 Some parts of lily still prefer style "default" over "".
131 Correct this here. -- jr
133 actual_style = "";
136 return ("rests." + to_string (balltype) + (is_ledgered ? "o" : "")
137 + actual_style);
140 MAKE_SCHEME_CALLBACK (Rest, print, 1);
142 Rest::brew_internal_stencil (Grob *me, bool ledgered)
144 SCM balltype_scm = me->get_property ("duration-log");
145 if (!scm_is_number (balltype_scm))
146 return Stencil ().smobbed_copy ();
148 int balltype = scm_to_int (balltype_scm);
150 string style;
151 SCM style_scm = me->get_property ("style");
152 if (scm_is_symbol (style_scm))
153 style = ly_scm2string (scm_symbol_to_string (style_scm));
155 Font_metric *fm = Font_interface::get_default_font (me);
156 string font_char = glyph_name (me, balltype, style, ledgered);
157 Stencil out = fm->find_by_name (font_char);
158 if (out.is_empty ())
159 me->warning (_f ("rest `%s' not found", font_char.c_str ()));
161 return out.smobbed_copy ();
165 translate the rest vertically by amount DY, but only if
166 it doesn't have staff-position set.
168 void
169 Rest::translate (Grob *me, int dy)
171 if (!scm_is_number (me->get_property ("staff-position")))
173 me->translate_axis (dy * Staff_symbol_referencer::staff_space (me) / 2.0, Y_AXIS);
174 Grob *p = me->get_parent (Y_AXIS);
175 p->flush_extent_cache (Y_AXIS);
180 Rest::print (SCM smob)
182 return brew_internal_stencil (unsmob_grob (smob), true);
185 MAKE_SCHEME_CALLBACK (Rest, width, 1);
187 We need the callback. The real stencil has ledgers depending on
188 Y-position. The Y-position is known only after line breaking. */
190 Rest::width (SCM smob)
192 return generic_extent_callback (unsmob_grob (smob), X_AXIS);
195 MAKE_SCHEME_CALLBACK (Rest, height, 1);
197 Rest::height (SCM smob)
199 return generic_extent_callback (unsmob_grob (smob), Y_AXIS);
203 We need the callback. The real stencil has ledgers depending on
204 Y-position. The Y-position is known only after line breaking. */
206 Rest::generic_extent_callback (Grob *me, Axis a)
209 Don't want ledgers: ledgers depend on Y position, which depends on
210 rest collision, which depends on stem size which depends on beam
211 slop of opposite note column.
213 consequence: we get too small extents and potential collisions
214 with ledgered rests.
216 SCM m = brew_internal_stencil (me, a != X_AXIS);
217 return ly_interval2scm (unsmob_stencil (m)->extent (a));
220 MAKE_SCHEME_CALLBACK (Rest, pure_height, 3);
222 Rest::pure_height (SCM smob,
223 SCM /* start */,
224 SCM /* end */)
226 Grob *me = unsmob_grob (smob);
227 SCM m = brew_internal_stencil (me, false);
228 return ly_interval2scm (unsmob_stencil (m)->extent (Y_AXIS));
231 ADD_INTERFACE (Rest,
232 "A rest symbol. The property @code{style} can be"
233 " @code{default}, @code{mensural}, @code{neomensural} or"
234 " @code{classical}.",
236 /* properties */
237 "direction "
238 "minimum-distance "
239 "style "