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