]> git.donarmstrong.com Git - lilypond.git/blob - lily/rest.cc
Run grand-replace for 2012
[lilypond.git] / lily / rest.cc
1 /*
2   This file is part of LilyPond, the GNU music typesetter.
3
4   Copyright (C) 1997--2012 Han-Wen Nienhuys <hanwen@xs4all.nl>
5
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.
10
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.
15
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/>.
18 */
19
20 #include "rest.hh"
21
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"
31
32 // -> offset callback
33 MAKE_SCHEME_CALLBACK (Rest, y_offset_callback, 1);
34 SCM
35 Rest::y_offset_callback (SCM smob)
36 {
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);
41
42   bool position_override = scm_is_number (me->get_property ("staff-position"));
43   Real amount;
44
45   if (position_override)
46     {
47       amount =
48         robust_scm2double (me->get_property ("staff-position"), 0) * 0.5 * ss;
49       /*
50         trust the client on good positioning;
51         would be tempting to adjust position of rests longer than a quarter
52         to be properly aligned to staff lines,
53         but custom rest shapes may not need that sort of care.
54       */
55     }
56   else
57     {
58       amount = 2 * ss * get_grob_direction (me);
59
60       if (line_count % 2 == 0)
61         amount += ss / 2;
62     }
63
64   /*
65     make a semibreve rest hang from the next line,
66     except for a single line staff
67   */
68   if (duration_log == 0 && line_count > 1)
69     amount += ss;
70
71   return scm_from_double (amount);
72 }
73
74 /* A rest might lie under a beam, in which case it should be cross-staff if
75    the beam is cross-staff because the rest's position depends on the
76    formatting of the beam. */
77 MAKE_SCHEME_CALLBACK (Rest, calc_cross_staff, 1);
78 SCM
79 Rest::calc_cross_staff (SCM smob)
80 {
81   Grob *me = unsmob_grob (smob);
82   Grob *stem = unsmob_grob (me->get_object ("stem"));
83
84   if (!stem)
85     return SCM_BOOL_F;
86
87   return stem->get_property ("cross-staff");
88 }
89
90 /*
91   make this function easily usable in C++
92 */
93 string
94 Rest::glyph_name (Grob *me, int balltype, string style, bool try_ledgers)
95 {
96   bool is_ledgered = false;
97   if (try_ledgers && (balltype == -1 || balltype == 0 || balltype == 1))
98     {
99       Real rad = Staff_symbol_referencer::staff_radius (me) * 2.0;
100       Real pos = Staff_symbol_referencer::get_position (me);
101
102       /*
103         Figure out when the rest is far enough outside the staff. This
104         could bemore generic, but hey, we understand this even after
105         dinner.
106       */
107       is_ledgered |= (balltype == -1) && (pos <= -rad - 3 || pos >= +rad + 1);
108       is_ledgered |= (balltype == 0) && (pos >= +rad + 2 || pos < -rad);
109       is_ledgered |= (balltype == 1) && (pos <= -rad - 2 || pos > +rad);
110     }
111
112   string actual_style (style.c_str ());
113
114   if ((style == "mensural") || (style == "neomensural"))
115     {
116
117       /*
118         FIXME: Currently, ancient font does not provide ledgered rests;
119         hence the "o" suffix in the glyph name is bogus.  But do we need
120         ledgered rests at all now that we can draw ledger lines with
121         variable width, length and blotdiameter? -- jr
122       */
123       is_ledgered = 0;
124
125       /*
126         There are no 32th/64th/128th mensural/neomensural rests.  In
127         these cases, revert back to default style.
128       */
129       if (balltype > 4)
130         actual_style = "";
131     }
132
133   if ((style == "classical") && (balltype != 2))
134     {
135       /*
136         classical style: revert back to default style for any rest other
137         than quarter rest
138       */
139       actual_style = "";
140     }
141
142   if (style == "default")
143     {
144       /*
145         Some parts of lily still prefer style "default" over "".
146         Correct this here. -- jr
147       */
148       actual_style = "";
149     }
150
151   return ("rests." + to_string (balltype) + (is_ledgered ? "o" : "")
152           + actual_style);
153 }
154
155 MAKE_SCHEME_CALLBACK (Rest, print, 1);
156 SCM
157 Rest::brew_internal_stencil (Grob *me, bool ledgered)
158 {
159   SCM balltype_scm = me->get_property ("duration-log");
160   if (!scm_is_number (balltype_scm))
161     return Stencil ().smobbed_copy ();
162
163   int balltype = scm_to_int (balltype_scm);
164
165   string style = robust_symbol2string (me->get_property ("style"), "default");
166
167   Font_metric *fm = Font_interface::get_default_font (me);
168   string font_char = glyph_name (me, balltype, style, ledgered);
169   Stencil out = fm->find_by_name (font_char);
170   if (out.is_empty ())
171     me->warning (_f ("rest `%s' not found", font_char.c_str ()));
172
173   return out.smobbed_copy ();
174 }
175
176 /**
177    translate the rest vertically by amount DY, but only if
178    it doesn't have staff-position set.
179 */
180 void
181 Rest::translate (Grob *me, int dy)
182 {
183   if (!scm_is_number (me->get_property ("staff-position")))
184     {
185       me->translate_axis (dy * Staff_symbol_referencer::staff_space (me) / 2.0, Y_AXIS);
186       Grob *p = me->get_parent (Y_AXIS);
187       p->flush_extent_cache (Y_AXIS);
188     }
189 }
190
191 SCM
192 Rest::print (SCM smob)
193 {
194   return brew_internal_stencil (unsmob_grob (smob), true);
195 }
196
197 MAKE_SCHEME_CALLBACK (Rest, width, 1);
198 /*
199   We need the callback. The real stencil has ledgers depending on
200   Y-position. The Y-position is known only after line breaking.  */
201 SCM
202 Rest::width (SCM smob)
203 {
204   return generic_extent_callback (unsmob_grob (smob), X_AXIS);
205 }
206
207 MAKE_SCHEME_CALLBACK (Rest, height, 1);
208 SCM
209 Rest::height (SCM smob)
210 {
211   return generic_extent_callback (unsmob_grob (smob), Y_AXIS);
212 }
213
214 /*
215   We need the callback. The real stencil has ledgers depending on
216   Y-position. The Y-position is known only after line breaking.  */
217 SCM
218 Rest::generic_extent_callback (Grob *me, Axis a)
219 {
220   /*
221     Don't want ledgers: ledgers depend on Y position, which depends on
222     rest collision, which depends on stem size which depends on beam
223     slop of opposite note column.
224
225     consequence: we get too small extents and potential collisions
226     with ledgered rests.
227   */
228   SCM m = brew_internal_stencil (me, a != X_AXIS);
229   return ly_interval2scm (unsmob_stencil (m)->extent (a));
230 }
231
232 MAKE_SCHEME_CALLBACK (Rest, pure_height, 3);
233 SCM
234 Rest::pure_height (SCM smob,
235                    SCM /* start */,
236                    SCM /* end */)
237 {
238   Grob *me = unsmob_grob (smob);
239   SCM m = brew_internal_stencil (me, false);
240   return ly_interval2scm (unsmob_stencil (m)->extent (Y_AXIS));
241 }
242
243 ADD_INTERFACE (Rest,
244                "A rest symbol.  The property @code{style} can be"
245                " @code{default}, @code{mensural}, @code{neomensural} or"
246                " @code{classical}.",
247
248                /* properties */
249                "direction "
250                "minimum-distance "
251                "style "
252               );
253