]> git.donarmstrong.com Git - lilypond.git/blob - lily/rest.cc
*** empty log message ***
[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
119 MAKE_SCHEME_CALLBACK (Rest, print, 1);
120
121 SCM
122 Rest::brew_internal_stencil (SCM smob, bool ledgered)
123 {
124   Grob* me = unsmob_grob (smob);
125
126   SCM balltype_scm = me->get_property ("duration-log");
127   if (!scm_is_number (balltype_scm))
128     return Stencil ().smobbed_copy ();
129
130   int balltype = scm_to_int (balltype_scm);
131   
132   String style; 
133   SCM style_scm = me->get_property ("style");
134   if (scm_is_symbol (style_scm))
135     style = ly_scm2string (scm_symbol_to_string (style_scm));
136
137   Font_metric *fm = Font_interface::get_default_font (me);
138   String font_char = glyph_name (me, balltype, style, ledgered);
139   Stencil out = fm->find_by_name (font_char);
140   if (out.is_empty ())
141     me->warning (_f ("rest `%s' not found", font_char.to_str0 ()));
142
143   return out.smobbed_copy ();
144 }
145
146 SCM 
147 Rest::print (SCM smob) 
148 {
149   return brew_internal_stencil (smob, true);
150 }
151
152 MAKE_SCHEME_CALLBACK (Rest, extent_callback, 2);
153 /*
154   We need the callback. The real stencil has ledgers depending on
155   Y-position. The Y-position is known only after line breaking.  */
156 SCM
157 Rest::extent_callback (SCM smob, SCM ax)
158 {
159   Axis a = (Axis) scm_to_int (ax);
160
161   /*
162     Don't want ledgers: ledgers depend on Y position, which depends on
163     rest collision, which depends on stem size which depends on beam
164     slop of opposite note column.
165
166     consequence: we get too small extents and potential collisions
167     with ledgered rests.
168    */
169   SCM m = brew_internal_stencil (smob, a != X_AXIS);
170   return ly_interval2scm (unsmob_stencil (m)->extent (a));
171 }
172
173 MAKE_SCHEME_CALLBACK (Rest, polyphonic_offset_callback, 2);
174 SCM
175 Rest::polyphonic_offset_callback (SCM smob, SCM)
176 {
177   Grob* me = unsmob_grob (smob);
178   if (scm_is_number (me->get_property ("staff-position")))
179     return scm_make_real (0);
180
181   Direction d = get_grob_direction (me);
182   Real off = 2 * d ;
183   if (off)
184     off *= Staff_symbol_referencer::staff_space (me);
185
186   return scm_make_real (off);
187 }
188
189 ADD_INTERFACE (Rest, "rest-interface",
190   "A rest symbol.",
191   "style direction minimum-distance");
192