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