]> git.donarmstrong.com Git - lilypond.git/blob - lily/rest.cc
* lily/score-engraver.cc (initialize): abort if ecrm10.pfa not
[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--2004 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 */
8
9 #include "stencil.hh"
10 #include "output-def.hh"
11 #include "font-interface.hh"
12 #include "rest.hh"
13 #include "dots.hh"
14 #include "paper-score.hh"
15 #include "staff-symbol-referencer.hh"
16 #include "directional-element-interface.hh"
17
18 // -> offset callback
19 MAKE_SCHEME_CALLBACK (Rest,after_line_breaking,1);
20 SCM
21 Rest::after_line_breaking (SCM smob)
22 {
23   Grob *me = unsmob_grob (smob);
24   int bt = ly_scm2int (me->get_property ("duration-log"));
25   int lc = Staff_symbol_referencer::line_count (me);
26   Real ss = Staff_symbol_referencer::staff_space (me);
27   if (lc % 2)
28     {
29       if (bt == 0 && lc > 1)
30         {
31           me->translate_axis (ss , Y_AXIS);
32         }
33     }
34   else
35     {
36       me->translate_axis (ss/2 , Y_AXIS);
37     }
38
39   Grob * d = unsmob_grob (me->get_property ("dot"));
40   if (d && bt > 4) // UGH.
41     {
42       d->set_property ("staff-position",
43                             scm_int2num ((bt == 7) ? 4 : 3));
44     }
45   if (d && bt >= -1 && bt <= 1) // UGH again.
46     {
47       d->set_property ("staff-position",
48                             scm_int2num ((bt == 0) ? -1 : 1));
49     }
50   return SCM_UNSPECIFIED;
51 }
52
53 /*
54   make this function easily usable in C++
55  */
56 String
57 Rest::glyph_name (Grob *me, int balltype, String style, bool try_ledgers)
58 {
59   bool ledgered_b = false;
60   if (try_ledgers && (balltype == 0 || balltype == 1))
61     {
62       Real rad = Staff_symbol_referencer::staff_radius (me) * 2.0;
63       Real pos = Staff_symbol_referencer::get_position (me);
64
65       /*
66         Figure out when the rest is far enough outside the staff. This
67         could bemore generic, but hey, we understand this even after
68         dinner.
69        */
70       ledgered_b |= (balltype == 0) && (pos >= +rad + 2 || pos < -rad);
71       ledgered_b |= (balltype == 1) && (pos <= -rad - 2 || pos > +rad);
72     }
73
74   String actual_style (style.to_str0 ());
75
76   if ((style == "mensural") || (style == "neo_mensural")) {
77
78     /*
79       FIXME: Currently, ancient font does not provide ledgered rests;
80       hence the "o" suffix in the glyph name is bogus.  But do we need
81       ledgered rests at all now that we can draw ledger lines with
82       variable width, length and blotdiameter? -- jr
83     */
84     ledgered_b = 0;
85
86     /*
87       There are no 32th/64th/128th mensural/neo_mensural rests.  In
88       these cases, revert back to default style.
89     */
90     if (balltype > 4)
91       actual_style = "";
92   }
93
94   if ((style == "classical") && (balltype != 2)) {
95     /*
96       classical style: revert back to default style for any rest other
97       than quarter rest
98     */
99     actual_style = "";
100   }
101
102   if (style == "default") {
103     /*
104       Some parts of lily still prefer style "default" over "".
105       Correct this here. -- jr
106     */
107     actual_style = "";
108   }
109
110   return ("rests-") + to_string (balltype) + (ledgered_b ? "o" : "") + actual_style;
111 }
112
113
114 MAKE_SCHEME_CALLBACK (Rest,print,1);
115
116 SCM
117 Rest::brew_internal_stencil (SCM smob, bool ledgered)
118 {
119   Grob* me = unsmob_grob (smob);
120
121   SCM balltype_scm = me->get_property ("duration-log");
122   if (!ly_c_number_p (balltype_scm))
123     return Stencil ().smobbed_copy ();
124
125   int balltype = ly_scm2int (balltype_scm);
126   
127   String style; 
128   SCM style_scm = me->get_property ("style");
129   if (ly_c_symbol_p (style_scm))
130     style = ly_scm2string (scm_symbol_to_string (style_scm));
131
132   Font_metric *fm = Font_interface::get_default_font (me);
133   String font_char = glyph_name (me, balltype, style, ledgered);
134   Stencil out = fm->find_by_name (font_char);
135   if (out.is_empty ())
136     me->warning (_f ("rest `%s' not found", font_char.to_str0 ()));
137
138   return out.smobbed_copy ();
139 }
140
141 SCM 
142 Rest::print (SCM smob) 
143 {
144   return brew_internal_stencil (smob, true);
145 }
146 MAKE_SCHEME_CALLBACK (Rest,extent_callback,2);
147 /*
148   We need the callback. The real stencil has ledgers depending on
149   Y-position. The Y-position is known only after line breaking.  */
150 SCM
151 Rest::extent_callback (SCM smob, SCM ax)
152 {
153   Axis a = (Axis) ly_scm2int (ax);
154
155   /*
156     Don't want ledgers: ledgers depend on Y position, which depends on
157     rest collision, which depends on stem size which depends on beam
158     slop of opposite note column.
159
160     consequence: we get too small extents and potential collisions
161     with ledgered rests.
162    */
163   SCM m = brew_internal_stencil (smob, a != X_AXIS);
164   return ly_interval2scm (unsmob_stencil (m)->extent (a));
165 }
166
167 MAKE_SCHEME_CALLBACK (Rest,polyphonic_offset_callback,2);
168 SCM
169 Rest::polyphonic_offset_callback (SCM smob, SCM)
170 {
171   Grob* me = unsmob_grob (smob);
172   if (ly_c_number_p (me->get_property ("staff-position")))
173     return scm_make_real (0);
174
175   Direction d = get_grob_direction (me);
176   Real off = 2* d ;
177   if (off)
178     off *= Staff_symbol_referencer::staff_space (me);
179   return scm_make_real (off);
180 }
181
182 ADD_INTERFACE (Rest,"rest-interface",
183   "A rest symbol.",
184   "style direction minimum-distance");
185