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