Update from Andrew: tweaks for cross-staff chords snippet.
[lilypond.git] / lily / rest.cc
blob22420f54f4def9528dbccb739288d5ca8ade0727
1 /*
2 rest.cc -- implement Rest
4 source file of the GNU LilyPond music typesetter
6 (c) 1997--2007 Han-Wen Nienhuys <hanwen@xs4all.nl>
7 */
9 #include "rest.hh"
11 #include "directional-element-interface.hh"
12 #include "dots.hh"
13 #include "font-interface.hh"
14 #include "international.hh"
15 #include "output-def.hh"
16 #include "paper-score.hh"
17 #include "staff-symbol-referencer.hh"
18 #include "stencil.hh"
19 #include "grob.hh"
21 // -> offset callback
22 MAKE_SCHEME_CALLBACK (Rest, y_offset_callback, 1);
23 SCM
24 Rest::y_offset_callback (SCM smob)
26 Grob *me = unsmob_grob (smob);
27 int duration_log = scm_to_int (me->get_property ("duration-log"));
28 int line_count = Staff_symbol_referencer::line_count (me);
29 Real ss = Staff_symbol_referencer::staff_space (me);
31 bool position_override = scm_is_number (me->get_property ("staff-position"));
32 Real amount = robust_scm2double (me->get_property ("staff-position"), 0)
33 * 0.5 * ss;
35 if (line_count % 2)
37 if (duration_log == 0 && line_count > 1)
38 amount += ss;
40 else
41 amount += ss / 2;
43 if (!position_override)
44 amount += 2 * ss * get_grob_direction (me);;
46 return scm_from_double (amount);
49 /* A rest might lie under a beam, in which case it should be cross-staff if
50 the beam is cross-staff because the rest's position depends on the
51 formatting of the beam. */
52 MAKE_SCHEME_CALLBACK (Rest, calc_cross_staff, 1);
53 SCM
54 Rest::calc_cross_staff (SCM smob)
56 Grob *me = unsmob_grob (smob);
57 Grob *stem = unsmob_grob (me->get_object ("stem"));
59 if (!stem)
60 return SCM_BOOL_F;
62 return stem->get_property ("cross-staff");
66 make this function easily usable in C++
68 string
69 Rest::glyph_name (Grob *me, int balltype, string style, bool try_ledgers)
71 bool is_ledgered = false;
72 if (try_ledgers && (balltype == 0 || balltype == 1))
74 Real rad = Staff_symbol_referencer::staff_radius (me) * 2.0;
75 Real pos = Staff_symbol_referencer::get_position (me);
78 Figure out when the rest is far enough outside the staff. This
79 could bemore generic, but hey, we understand this even after
80 dinner.
82 is_ledgered |= (balltype == 0) && (pos >= +rad + 2 || pos < -rad);
83 is_ledgered |= (balltype == 1) && (pos <= -rad - 2 || pos > +rad);
86 string actual_style (style.c_str ());
88 if ((style == "mensural") || (style == "neomensural"))
92 FIXME: Currently, ancient font does not provide ledgered rests;
93 hence the "o" suffix in the glyph name is bogus. But do we need
94 ledgered rests at all now that we can draw ledger lines with
95 variable width, length and blotdiameter? -- jr
97 is_ledgered = 0;
100 There are no 32th/64th/128th mensural/neomensural rests. In
101 these cases, revert back to default style.
103 if (balltype > 4)
104 actual_style = "";
107 if ((style == "classical") && (balltype != 2))
110 classical style: revert back to default style for any rest other
111 than quarter rest
113 actual_style = "";
116 if (style == "default")
119 Some parts of lily still prefer style "default" over "".
120 Correct this here. -- jr
122 actual_style = "";
125 return ("rests." + to_string (balltype) + (is_ledgered ? "o" : "")
126 + actual_style);
129 MAKE_SCHEME_CALLBACK (Rest, print, 1);
131 Rest::brew_internal_stencil (Grob *me, bool ledgered)
133 SCM balltype_scm = me->get_property ("duration-log");
134 if (!scm_is_number (balltype_scm))
135 return Stencil ().smobbed_copy ();
137 int balltype = scm_to_int (balltype_scm);
139 string style;
140 SCM style_scm = me->get_property ("style");
141 if (scm_is_symbol (style_scm))
142 style = ly_scm2string (scm_symbol_to_string (style_scm));
144 Font_metric *fm = Font_interface::get_default_font (me);
145 string font_char = glyph_name (me, balltype, style, ledgered);
146 Stencil out = fm->find_by_name (font_char);
147 if (out.is_empty ())
148 me->warning (_f ("rest `%s' not found", font_char.c_str ()));
150 return out.smobbed_copy ();
154 Rest::print (SCM smob)
156 return brew_internal_stencil (unsmob_grob (smob), true);
159 MAKE_SCHEME_CALLBACK (Rest, width, 1);
161 We need the callback. The real stencil has ledgers depending on
162 Y-position. The Y-position is known only after line breaking. */
164 Rest::width (SCM smob)
166 return generic_extent_callback (unsmob_grob (smob), X_AXIS);
169 MAKE_SCHEME_CALLBACK (Rest, height, 1);
171 Rest::height (SCM smob)
173 return generic_extent_callback (unsmob_grob (smob), Y_AXIS);
177 We need the callback. The real stencil has ledgers depending on
178 Y-position. The Y-position is known only after line breaking. */
180 Rest::generic_extent_callback (Grob *me, Axis a)
183 Don't want ledgers: ledgers depend on Y position, which depends on
184 rest collision, which depends on stem size which depends on beam
185 slop of opposite note column.
187 consequence: we get too small extents and potential collisions
188 with ledgered rests.
190 SCM m = brew_internal_stencil (me, a != X_AXIS);
191 return ly_interval2scm (unsmob_stencil (m)->extent (a));
194 MAKE_SCHEME_CALLBACK (Rest, pure_height, 3);
196 Rest::pure_height (SCM smob, SCM start, SCM end)
198 (void) start;
199 (void) end;
201 Grob *me = unsmob_grob (smob);
202 SCM m = brew_internal_stencil (me, false);
203 return ly_interval2scm (unsmob_stencil (m)->extent (Y_AXIS));
206 ADD_INTERFACE (Rest,
207 "A rest symbol. The property @code{style} can be"
208 " @code{default}, @code{mensural}, @code{neomensural} or"
209 " @code{classical}.",
211 /* properties */
212 "direction "
213 "minimum-distance "
214 "style "