]> git.donarmstrong.com Git - lilypond.git/blob - lily/mensural-ligature.cc
Use `_f' consequently only for strings with arguments.
[lilypond.git] / lily / mensural-ligature.cc
1 /*
2   mensural-ligature.cc -- implement Mensural_ligature
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 2002--2007 Juergen Reuter <reuter@ipd.uka.de>,
7   Pal Benko <benkop@freestart.hu>
8 */
9
10 #include "mensural-ligature.hh"
11
12 #include "font-interface.hh"
13 #include "international.hh"
14 #include "item.hh"
15 #include "lookup.hh"
16 #include "note-head.hh"
17 #include "output-def.hh"
18 #include "staff-symbol-referencer.hh"
19 #include "warn.hh"
20
21 /*
22  * TODO: divide this function into mensural and neo-mensural style.
23  *
24  * TODO: move this function to class Lookup?
25  */
26 Stencil
27 brew_flexa (Grob *me,
28             Real interval,
29             bool solid,
30             Real width,
31             Real vertical_line_thickness)
32 {
33   Real staff_space = Staff_symbol_referencer::staff_space (me);
34   Real slope = (interval / 2.0 * staff_space) / width;
35
36   // Compensate optical illusion regarding vertical position of left
37   // and right endings due to slope.
38   Real ypos_correction = -0.1 * staff_space * sign (slope);
39   Real slope_correction = 0.2 * staff_space * sign (slope);
40   Real corrected_slope = slope + slope_correction / width;
41
42   Stencil stencil;
43   if (solid) // colorated flexae
44     {
45       Stencil solid_head
46         = Lookup::beam (corrected_slope, width, staff_space, 0.0);
47       stencil.add_stencil (solid_head);
48     }
49   else // outline
50     {
51       /*
52         The thickness of the horizontal lines of the flexa shape
53         should be equal to that of the horizontal lines of the
54         neomensural brevis note head (see mf/parmesan-heads.mf).
55       */
56       Real const horizontal_line_thickness = staff_space * 0.35;
57
58       // URGH!  vertical_line_thickness is adjustable (via thickness
59       // property), while horizontal_line_thickness is constant.
60       // Maybe both should be adjustable independently?
61
62       Real height = staff_space - horizontal_line_thickness;
63
64       Stencil left_edge
65         = Lookup::beam (corrected_slope, vertical_line_thickness, height, 0.0);
66       stencil.add_stencil (left_edge);
67
68       Stencil right_edge
69         = Lookup::beam (corrected_slope, vertical_line_thickness, height, 0.0);
70       right_edge.translate_axis (width - vertical_line_thickness, X_AXIS);
71       right_edge.translate_axis ((width - vertical_line_thickness) *
72                                  corrected_slope, Y_AXIS);
73       stencil.add_stencil (right_edge);
74
75       Stencil bottom_edge
76         = Lookup::beam (corrected_slope, width,
77                         horizontal_line_thickness, 0.0);
78       bottom_edge.translate_axis (-0.5 * height, Y_AXIS);
79       stencil.add_stencil (bottom_edge);
80
81       Stencil top_edge
82         = Lookup::beam (corrected_slope, width,
83                         horizontal_line_thickness, 0.0);
84       top_edge.translate_axis (+0.5 * height, Y_AXIS);
85       stencil.add_stencil (top_edge);
86     }
87   stencil.translate_axis (ypos_correction, Y_AXIS);
88   return stencil;
89 }
90
91 Stencil
92 internal_brew_primitive (Grob *me)
93 {
94   SCM primitive_scm = me->get_property ("primitive");
95   if (primitive_scm == SCM_EOL)
96     {
97       programming_error ("Mensural_ligature: "
98                          "undefined primitive -> ignoring grob");
99       return Lookup::blank (Box (Interval (0, 0), Interval (0, 0)));
100     }
101   int primitive = scm_to_int (primitive_scm);
102
103   Stencil out;
104   int delta_pitch = 0;
105   Real thickness = 0.0;
106   Real width = 0.0;
107   Real staff_space = Staff_symbol_referencer::staff_space (me);
108   if (primitive & MLP_ANY)
109     thickness = robust_scm2double (me->get_property ("thickness"), .14);
110
111   if (primitive & MLP_FLEXA)
112     {
113       delta_pitch = robust_scm2int (me->get_property ("delta-position"),
114                                     0);
115       width
116         = robust_scm2double (me->get_property ("flexa-width"), 2.0 * staff_space);
117     }
118   if (primitive & MLP_SINGLE_HEAD)
119     width = robust_scm2double (me->get_property ("head-width"), staff_space);
120
121   switch (primitive & MLP_ANY)
122     {
123     case MLP_NONE:
124       return Lookup::blank (Box (Interval (0, 0), Interval (0, 0)));
125     case MLP_LONGA: // mensural brevis head with right cauda
126       out = Font_interface::get_default_font (me)->find_by_name
127         ("noteheads.sM2mensural");
128       break;
129     case MLP_BREVIS: // mensural brevis head
130       out = Font_interface::get_default_font (me)->find_by_name
131         ("noteheads.sM1mensural");
132       break;
133     case MLP_MAXIMA: // should be mensural maxima head without stem
134       out = Font_interface::get_default_font (me)->find_by_name
135         ("noteheads.sM1neomensural");
136       break;
137     case MLP_FLEXA:
138       out = brew_flexa (me, delta_pitch, false, width, thickness);
139       break;
140     default:
141       programming_error (_ ("Mensural_ligature: "
142                             "unexpected case fall-through"));
143       return Lookup::blank (Box (Interval (0, 0), Interval (0, 0)));
144     }
145
146   Real blotdiameter
147     = (me->layout ()->get_dimension (ly_symbol2scm ("blot-diameter")));
148
149   if (primitive & MLP_STEM)
150     {
151       // assume MLP_UP
152       Real y_bottom = 0.0, y_top = 3.0 * staff_space;
153
154       if (primitive & MLP_DOWN)
155         {
156           y_bottom = -y_top;
157           y_top = 0.0;
158         }
159
160       Interval x_extent (0, thickness);
161       Interval y_extent (y_bottom, y_top);
162       Box join_box (x_extent, y_extent);
163
164       Stencil join = Lookup::round_filled_box (join_box, blotdiameter);
165       out.add_stencil (join);
166     }
167
168   SCM join_right_scm = me->get_property ("join-right-amount");
169
170   if (scm_is_number (join_right_scm))
171     {
172       int join_right = scm_to_int (join_right_scm);
173       if (join_right)
174         {
175           Real y_top = join_right * 0.5 * staff_space;
176           Real y_bottom = 0.0;
177
178           if (y_top < 0.0)
179             {
180               y_bottom = y_top;
181               y_top = 0.0;
182             }
183
184           Interval x_extent (width - thickness, width);
185           Interval y_extent (y_bottom, y_top);
186           Box join_box (x_extent, y_extent);
187           Stencil join = Lookup::round_filled_box (join_box, blotdiameter);
188
189           out.add_stencil (join);
190         }
191       else
192         programming_error (_ ("Mensural_ligature: (join_right == 0)"));
193     }
194
195 #if 0 /* what happend with the ledger lines? */
196   int pos = Staff_symbol_referencer::get_rounded_position (me);
197   if (primitive & MLP_FLEXA)
198     {
199       pos += delta_pitch;
200       add_ledger_lines (me, &out, pos, 0.5 * delta_pitch, ledger_take_space);
201     }
202 #endif
203
204   return out;
205 }
206
207 MAKE_SCHEME_CALLBACK (Mensural_ligature, brew_ligature_primitive, 1);
208 SCM
209 Mensural_ligature::brew_ligature_primitive (SCM smob)
210 {
211   Grob *me = unsmob_grob (smob);
212   return internal_brew_primitive (me).smobbed_copy ();
213 }
214
215 MAKE_SCHEME_CALLBACK (Mensural_ligature, print, 1);
216 SCM
217 Mensural_ligature::print (SCM)
218 {
219   return SCM_EOL;
220 }
221
222 ADD_INTERFACE (Mensural_ligature,
223                "A mensural ligature.",
224
225                /* properties */
226                "delta-position "
227                "flexa-width "
228                "head-width "
229                "join-right-amount "
230                "primitive "
231                "thickness "
232                );
233