]> 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       FIXME: Currently, ancient font does not provide ledgered rests;
81       hence the "o" suffix in the glyph name is bogus.  But do we need
82       ledgered rests at all now that we can draw ledger lines with
83       variable width, length and blotdiameter? -- jr
84     */
85     ledgered_b = 0;
86
87     /*
88       There are no 32th/64th/128th mensural/neomensural rests.  In
89       these cases, revert back to default style.
90     */
91     if (balltype > 4)
92       actual_style = "";
93   }
94
95   if ((style == "classical") && (balltype != 2)) {
96     /*
97       classical style: revert back to default style for any rest other
98       than quarter rest
99     */
100     actual_style = "";
101   }
102
103   if (style == "default") {
104     /*
105       Some parts of lily still prefer style "default" over "".
106       Correct this here. -- jr
107     */
108     actual_style = "";
109   }
110
111   return ("rests." + to_string (balltype) + (ledgered_b ? "o" : "")
112           + actual_style);
113 }
114
115
116 MAKE_SCHEME_CALLBACK (Rest,print,1);
117
118 SCM
119 Rest::brew_internal_stencil (SCM smob, bool ledgered)
120 {
121   Grob* me = unsmob_grob (smob);
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 (smob, true);
147 }
148 MAKE_SCHEME_CALLBACK (Rest,extent_callback,2);
149 /*
150   We need the callback. The real stencil has ledgers depending on
151   Y-position. The Y-position is known only after line breaking.  */
152 SCM
153 Rest::extent_callback (SCM smob, SCM ax)
154 {
155   Axis a = (Axis) scm_to_int (ax);
156
157   /*
158     Don't want ledgers: ledgers depend on Y position, which depends on
159     rest collision, which depends on stem size which depends on beam
160     slop of opposite note column.
161
162     consequence: we get too small extents and potential collisions
163     with ledgered rests.
164    */
165   SCM m = brew_internal_stencil (smob, a != X_AXIS);
166   return ly_interval2scm (unsmob_stencil (m)->extent (a));
167 }
168
169 MAKE_SCHEME_CALLBACK (Rest,polyphonic_offset_callback,2);
170 SCM
171 Rest::polyphonic_offset_callback (SCM smob, SCM)
172 {
173   Grob* me = unsmob_grob (smob);
174   if (scm_is_number (me->get_property ("staff-position")))
175     return scm_make_real (0);
176
177   Direction d = get_grob_direction (me);
178   Real off = 2* d ;
179   if (off)
180     off *= Staff_symbol_referencer::staff_space (me);
181   return scm_make_real (off);
182 }
183
184 ADD_INTERFACE (Rest,"rest-interface",
185   "A rest symbol.",
186   "style direction minimum-distance");
187