Consider accidentals in optical spacing correction.
[lilypond.git] / lily / mensural-ligature.cc
blob4f9e64c96193291a4cd724e23c5d842e70b7d477
1 /*
2 mensural-ligature.cc -- implement Mensural_ligature
4 source file of the GNU LilyPond music typesetter
6 (c) 2002--2009 Juergen Reuter <reuter@ipd.uka.de>,
7 Pal Benko <benkop@freestart.hu>
8 */
10 #include "mensural-ligature.hh"
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"
22 * TODO: divide this function into mensural and neo-mensural style.
24 * TODO: move this function to class Lookup?
26 Stencil
27 brew_flexa (Grob *me,
28 Real interval,
29 bool solid,
30 Real width,
31 Real vertical_line_thickness)
33 Real staff_space = Staff_symbol_referencer::staff_space (me);
34 Real slope = (interval / 2.0 * staff_space) / width;
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;
42 Stencil stencil;
43 if (solid) // colorated flexae
45 Stencil solid_head
46 = Lookup::beam (corrected_slope, width, staff_space, 0.0);
47 stencil.add_stencil (solid_head);
49 else // outline
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).
56 Real const horizontal_line_thickness = staff_space * 0.35;
58 // URGH! vertical_line_thickness is adjustable (via thickness
59 // property), while horizontal_line_thickness is constant.
60 // Maybe both should be adjustable independently?
62 Real height = staff_space - horizontal_line_thickness;
64 Stencil left_edge
65 = Lookup::beam (corrected_slope, vertical_line_thickness, height, 0.0);
66 stencil.add_stencil (left_edge);
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);
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);
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);
87 stencil.translate_axis (ypos_correction, Y_AXIS);
88 return stencil;
91 Stencil
92 internal_brew_primitive (Grob *me)
94 SCM primitive_scm = me->get_property ("primitive");
95 if (primitive_scm == SCM_EOL)
97 programming_error ("Mensural_ligature: "
98 "undefined primitive -> ignoring grob");
99 return Lookup::blank (Box (Interval (0, 0), Interval (0, 0)));
101 int primitive = scm_to_int (primitive_scm);
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);
111 if (primitive & MLP_FLEXA)
113 delta_pitch = robust_scm2int (me->get_property ("delta-position"),
115 width
116 = robust_scm2double (me->get_property ("flexa-width"), 2.0 * staff_space);
118 if (primitive & MLP_SINGLE_HEAD)
119 width = robust_scm2double (me->get_property ("head-width"), staff_space);
121 switch (primitive & MLP_ANY)
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)));
146 Real blotdiameter
147 = (me->layout ()->get_dimension (ly_symbol2scm ("blot-diameter")));
149 if (primitive & MLP_STEM)
151 // assume MLP_UP
152 Real y_bottom = 0.0, y_top = 3.0 * staff_space;
154 if (primitive & MLP_DOWN)
156 y_bottom = -y_top;
157 y_top = 0.0;
160 Interval x_extent (0, thickness);
161 Interval y_extent (y_bottom, y_top);
162 Box join_box (x_extent, y_extent);
164 Stencil join = Lookup::round_filled_box (join_box, blotdiameter);
165 out.add_stencil (join);
168 SCM join_right_scm = me->get_property ("join-right-amount");
170 if (scm_is_number (join_right_scm))
172 int join_right = scm_to_int (join_right_scm);
173 if (join_right)
175 Real y_top = join_right * 0.5 * staff_space;
176 Real y_bottom = 0.0;
178 if (y_top < 0.0)
180 y_bottom = y_top;
181 y_top = 0.0;
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);
189 out.add_stencil (join);
191 else
192 programming_error (_ ("Mensural_ligature: (join_right == 0)"));
195 #if 0 /* what happend with the ledger lines? */
196 int pos = Staff_symbol_referencer::get_rounded_position (me);
197 if (primitive & MLP_FLEXA)
199 pos += delta_pitch;
200 add_ledger_lines (me, &out, pos, 0.5 * delta_pitch, ledger_take_space);
202 #endif
204 return out;
207 MAKE_SCHEME_CALLBACK (Mensural_ligature, brew_ligature_primitive, 1);
209 Mensural_ligature::brew_ligature_primitive (SCM smob)
211 Grob *me = unsmob_grob (smob);
212 return internal_brew_primitive (me).smobbed_copy ();
215 MAKE_SCHEME_CALLBACK (Mensural_ligature, print, 1);
217 Mensural_ligature::print (SCM)
219 return SCM_EOL;
222 ADD_INTERFACE (Mensural_ligature,
223 "A mensural ligature.",
225 /* properties */
226 "delta-position "
227 "flexa-width "
228 "head-width "
229 "join-right-amount "
230 "primitive "
231 "thickness "