]> git.donarmstrong.com Git - lilypond.git/blob - lily/rest.cc
Run `make grand-replace'.
[lilypond.git] / lily / rest.cc
1 /*
2   rest.cc -- implement Rest
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 1997--2008 Han-Wen Nienhuys <hanwen@xs4all.nl>
7 */
8
9 #include "rest.hh"
10
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"
20
21 // -> offset callback
22 MAKE_SCHEME_CALLBACK (Rest, y_offset_callback, 1);
23 SCM
24 Rest::y_offset_callback (SCM smob)
25 {
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);
30
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;
34   
35   if (line_count % 2)
36     {
37       if (duration_log == 0 && line_count > 1)
38         amount += ss;
39     }
40   else
41     amount += ss / 2;
42
43   if (!position_override)
44     amount += 2 * ss * get_grob_direction (me);; 
45   
46   return scm_from_double (amount);
47 }
48
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)
55 {
56   Grob *me = unsmob_grob (smob);
57   Grob *stem = unsmob_grob (me->get_object ("stem"));
58
59   if (!stem)
60     return SCM_BOOL_F;
61
62   return stem->get_property ("cross-staff");
63 }
64
65 /*
66   make this function easily usable in C++
67 */
68 string
69 Rest::glyph_name (Grob *me, int balltype, string style, bool try_ledgers)
70 {
71   bool is_ledgered = false;
72   if (try_ledgers && (balltype == 0 || balltype == 1))
73     {
74       Real rad = Staff_symbol_referencer::staff_radius (me) * 2.0;
75       Real pos = Staff_symbol_referencer::get_position (me);
76
77       /*
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.
81       */
82       is_ledgered |= (balltype == 0) && (pos >= +rad + 2 || pos < -rad);
83       is_ledgered |= (balltype == 1) && (pos <= -rad - 2 || pos > +rad);
84     }
85
86   string actual_style (style.c_str ());
87
88   if ((style == "mensural") || (style == "neomensural"))
89     {
90
91       /*
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
96       */
97       is_ledgered = 0;
98
99       /*
100         There are no 32th/64th/128th mensural/neomensural rests.  In
101         these cases, revert back to default style.
102       */
103       if (balltype > 4)
104         actual_style = "";
105     }
106
107   if ((style == "classical") && (balltype != 2))
108     {
109       /*
110         classical style: revert back to default style for any rest other
111         than quarter rest
112       */
113       actual_style = "";
114     }
115
116   if (style == "default")
117     {
118       /*
119         Some parts of lily still prefer style "default" over "".
120         Correct this here. -- jr
121       */
122       actual_style = "";
123     }
124
125   return ("rests." + to_string (balltype) + (is_ledgered ? "o" : "")
126           + actual_style);
127 }
128
129 MAKE_SCHEME_CALLBACK (Rest, print, 1);
130 SCM
131 Rest::brew_internal_stencil (Grob *me, bool ledgered)
132 {
133   SCM balltype_scm = me->get_property ("duration-log");
134   if (!scm_is_number (balltype_scm))
135     return Stencil ().smobbed_copy ();
136
137   int balltype = scm_to_int (balltype_scm);
138
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));
143
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 ()));
149
150   return out.smobbed_copy ();
151 }
152
153 SCM
154 Rest::print (SCM smob)
155 {
156   return brew_internal_stencil (unsmob_grob (smob), true);
157 }
158
159 MAKE_SCHEME_CALLBACK (Rest, width, 1);
160 /*
161   We need the callback. The real stencil has ledgers depending on
162   Y-position. The Y-position is known only after line breaking.  */
163 SCM
164 Rest::width (SCM smob)
165 {
166   return generic_extent_callback (unsmob_grob (smob), X_AXIS);
167 }
168
169 MAKE_SCHEME_CALLBACK (Rest, height, 1);
170 SCM
171 Rest::height (SCM smob)
172 {
173   return generic_extent_callback (unsmob_grob (smob), Y_AXIS);
174 }
175
176 /*
177   We need the callback. The real stencil has ledgers depending on
178   Y-position. The Y-position is known only after line breaking.  */
179 SCM
180 Rest::generic_extent_callback (Grob *me, Axis a)
181 {
182   /*
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.
186
187     consequence: we get too small extents and potential collisions
188     with ledgered rests.
189   */
190   SCM m = brew_internal_stencil (me, a != X_AXIS);
191   return ly_interval2scm (unsmob_stencil (m)->extent (a));
192 }
193
194 MAKE_SCHEME_CALLBACK (Rest, pure_height, 3);
195 SCM
196 Rest::pure_height (SCM smob, SCM start, SCM end)
197 {
198   (void) start;
199   (void) end;
200   
201   Grob *me = unsmob_grob (smob);
202   SCM m = brew_internal_stencil (me, false);
203   return ly_interval2scm (unsmob_stencil (m)->extent (Y_AXIS));
204 }
205
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}.",
210
211                /* properties */
212                "direction "
213                "minimum-distance "
214                "style "
215                );
216