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