]> git.donarmstrong.com Git - lilypond.git/blob - lily/rest.cc
(parse_symbol_list): Bugfix.
[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--2005 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 */
8
9 #include "rest.hh"
10
11 #include "stencil.hh"
12 #include "output-def.hh"
13 #include "font-interface.hh"
14 #include "dots.hh"
15 #include "paper-score.hh"
16 #include "staff-symbol-referencer.hh"
17 #include "directional-element-interface.hh"
18
19 // -> offset callback
20 MAKE_SCHEME_CALLBACK (Rest, after_line_breaking, 1);
21 SCM
22 Rest::after_line_breaking (SCM smob)
23 {
24   Grob *me = unsmob_grob (smob);
25   int bt = scm_to_int (me->get_property ("duration-log"));
26   int lc = Staff_symbol_referencer::line_count (me);
27   Real ss = Staff_symbol_referencer::staff_space (me);
28   if (lc % 2)
29     {
30       if (bt == 0 && lc > 1)
31         me->translate_axis (ss, Y_AXIS);
32     }
33   else
34     {
35       me->translate_axis (ss / 2, Y_AXIS);
36     }
37
38   Grob *d = unsmob_grob (me->get_object ("dot"));
39   if (d && bt > 4) // UGH.
40     {
41       d->set_property ("staff-position",
42                        scm_from_int ((bt == 7) ? 4 : 3));
43     }
44   if (d && bt >= -1 && bt <= 1) // UGH again.
45     {
46       d->set_property ("staff-position",
47                        scm_from_int ((bt == 0) ? -1 : 1));
48     }
49   return SCM_UNSPECIFIED;
50 }
51
52 /*
53   make this function easily usable in C++
54 */
55 String
56 Rest::glyph_name (Grob *me, int balltype, String style, bool try_ledgers)
57 {
58   bool ledgered_b = false;
59   if (try_ledgers && (balltype == 0 || balltype == 1))
60     {
61       Real rad = Staff_symbol_referencer::staff_radius (me) * 2.0;
62       Real pos = Staff_symbol_referencer::get_position (me);
63
64       /*
65         Figure out when the rest is far enough outside the staff. This
66         could bemore generic, but hey, we understand this even after
67         dinner.
68       */
69       ledgered_b |= (balltype == 0) && (pos >= +rad + 2 || pos < -rad);
70       ledgered_b |= (balltype == 1) && (pos <= -rad - 2 || pos > +rad);
71     }
72
73   String actual_style (style.to_str0 ());
74
75   if ((style == "mensural") || (style == "neomensural"))
76     {
77
78       /*
79         FIXME: Currently, ancient font does not provide ledgered rests;
80         hence the "o" suffix in the glyph name is bogus.  But do we need
81         ledgered rests at all now that we can draw ledger lines with
82         variable width, length and blotdiameter? -- jr
83       */
84       ledgered_b = 0;
85
86       /*
87         There are no 32th/64th/128th mensural/neomensural rests.  In
88         these cases, revert back to default style.
89       */
90       if (balltype > 4)
91         actual_style = "";
92     }
93
94   if ((style == "classical") && (balltype != 2))
95     {
96       /*
97         classical style: revert back to default style for any rest other
98         than quarter rest
99       */
100       actual_style = "";
101     }
102
103   if (style == "default")
104     {
105       /*
106         Some parts of lily still prefer style "default" over "".
107         Correct this here. -- jr
108       */
109       actual_style = "";
110     }
111
112   return ("rests." + to_string (balltype) + (ledgered_b ? "o" : "")
113           + actual_style);
114 }
115
116 MAKE_SCHEME_CALLBACK (Rest, print, 1);
117
118 SCM
119 Rest::brew_internal_stencil (SCM smob, bool ledgered)
120 {
121   Grob *me = unsmob_grob (smob);
122
123   SCM balltype_scm = me->get_property ("duration-log");
124   if (!scm_is_number (balltype_scm))
125     return Stencil ().smobbed_copy ();
126
127   int balltype = scm_to_int (balltype_scm);
128
129   String style;
130   SCM style_scm = me->get_property ("style");
131   if (scm_is_symbol (style_scm))
132     style = ly_scm2string (scm_symbol_to_string (style_scm));
133
134   Font_metric *fm = Font_interface::get_default_font (me);
135   String font_char = glyph_name (me, balltype, style, ledgered);
136   Stencil out = fm->find_by_name (font_char);
137   if (out.is_empty ())
138     me->warning (_f ("rest `%s' not found", font_char.to_str0 ()));
139
140   return out.smobbed_copy ();
141 }
142
143 SCM
144 Rest::print (SCM smob)
145 {
146   return brew_internal_stencil (smob, true);
147 }
148
149 MAKE_SCHEME_CALLBACK (Rest, extent_callback, 2);
150 /*
151   We need the callback. The real stencil has ledgers depending on
152   Y-position. The Y-position is known only after line breaking.  */
153 SCM
154 Rest::extent_callback (SCM smob, SCM ax)
155 {
156   Axis a = (Axis) scm_to_int (ax);
157
158   /*
159     Don't want ledgers: ledgers depend on Y position, which depends on
160     rest collision, which depends on stem size which depends on beam
161     slop of opposite note column.
162
163     consequence: we get too small extents and potential collisions
164     with ledgered rests.
165   */
166   SCM m = brew_internal_stencil (smob, a != X_AXIS);
167   return ly_interval2scm (unsmob_stencil (m)->extent (a));
168 }
169
170 MAKE_SCHEME_CALLBACK (Rest, polyphonic_offset_callback, 2);
171 SCM
172 Rest::polyphonic_offset_callback (SCM smob, SCM)
173 {
174   Grob *me = unsmob_grob (smob);
175   if (scm_is_number (me->get_property ("staff-position")))
176     return scm_from_double (0);
177
178   Direction d = get_grob_direction (me);
179   Real off = 2 * d;
180   if (off)
181     off *= Staff_symbol_referencer::staff_space (me);
182
183   return scm_from_double (off);
184 }
185
186 ADD_INTERFACE (Rest, "rest-interface",
187                "A rest symbol.",
188                "style direction minimum-distance");
189