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