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