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