]> git.donarmstrong.com Git - lilypond.git/blob - lily/mensural-ligature.cc
Update.
[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--2005 Juergen Reuter <reuter@ipd.uka.de>,
7   Pal Benko <benkop@freestart.hu>
8 */
9
10 #include <math.h>
11
12 #include "mensural-ligature.hh"
13 #include "item.hh"
14 #include "font-interface.hh"
15 #include "lookup.hh"
16 #include "staff-symbol-referencer.hh"
17 #include "note-head.hh"
18 #include "output-def.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 thickness)
32 {
33   Real staff_space = Staff_symbol_referencer::staff_space (me);
34   Real height = 0.6 * staff_space;
35   Stencil stencil;
36
37   Real slope = (interval / 2.0 * staff_space) / width;
38
39   // Compensate optical illusion regarding vertical position of left
40   // and right endings due to slope.
41   Real ypos_correction = -0.1 * staff_space * sign (slope);
42   Real slope_correction = 0.2 * staff_space * sign (slope);
43   Real corrected_slope = slope + slope_correction / width;
44
45   if (solid) // this will come handy for colorated flexae
46     {
47       Stencil solid_head
48         = Lookup::beam (corrected_slope, width, height, 0.0);
49       stencil.add_stencil (solid_head);
50     }
51   else // outline
52     {
53       Stencil left_edge
54         = Lookup::beam (corrected_slope, thickness, height, 0.0);
55       stencil.add_stencil (left_edge);
56
57       Stencil right_edge
58         = Lookup::beam (corrected_slope, thickness, height, 0.0);
59       right_edge.translate_axis (width - thickness, X_AXIS);
60       right_edge.translate_axis (corrected_slope * (width - thickness), Y_AXIS);
61       stencil.add_stencil (right_edge);
62
63       Stencil bottom_edge
64         = Lookup::beam (corrected_slope, width, thickness, 0.0);
65       bottom_edge.translate_axis (-0.5 * height, Y_AXIS);
66       stencil.add_stencil (bottom_edge);
67
68       Stencil top_edge
69         = Lookup::beam (corrected_slope, width, thickness, 0.0);
70       top_edge.translate_axis (+0.5 * height, Y_AXIS);
71       stencil.add_stencil (top_edge);
72     }
73   stencil.translate_axis (ypos_correction, Y_AXIS);
74   return stencil;
75 }
76
77 Stencil
78 internal_brew_primitive (Grob *me)
79 {
80   SCM primitive_scm = me->get_property ("primitive");
81   if (primitive_scm == SCM_EOL)
82     {
83       programming_error ("Mensural_ligature: "
84                          "undefined primitive -> ignoring grob");
85       return Stencil ();
86     }
87   int primitive = scm_to_int (primitive_scm);
88
89   Stencil out;
90   int delta_pitch = 0;
91   Real thickness = 0.0;
92   Real width = 0.0;
93   Real staff_space = Staff_symbol_referencer::staff_space (me);
94   if (primitive & MLP_ANY)
95     {
96       thickness = robust_scm2double (me->get_property ("thickness"), .14);
97     }
98
99   if (primitive & MLP_FLEXA)
100     {
101       delta_pitch = robust_scm2int (me->get_property ("delta-pitch"),
102                                     0);
103       width
104         = robust_scm2double (me->get_property ("flexa-width"), 2.0 * staff_space);
105     }
106   if (primitive & MLP_SINGLE_HEAD)
107     {
108       width = robust_scm2double (me->get_property ("head-width"), staff_space);
109     }
110
111   switch (primitive & MLP_ANY)
112     {
113     case MLP_NONE:
114       return Stencil ();
115     case MLP_LONGA: // mensural brevis head with right cauda
116       out = Font_interface::get_default_font (me)->find_by_name
117         ("noteheads.s-2mensural");
118       break;
119     case MLP_BREVIS: // mensural brevis head
120       out = Font_interface::get_default_font (me)->find_by_name
121         ("noteheads.s-1mensural");
122       break;
123     case MLP_MAXIMA: // should be mensural maxima head without stem
124       out = Font_interface::get_default_font (me)->find_by_name
125         ("noteheads.s-1neomensural");
126       break;
127     case MLP_FLEXA:
128       out = brew_flexa (me, delta_pitch, false, width, thickness);
129       break;
130     default:
131       programming_error (_f ("Mensural_ligature: "
132                              "unexpected case fall-through"));
133       return Stencil ();
134     }
135
136   Real blotdiameter
137     = (me->get_layout ()->get_dimension (ly_symbol2scm ("blotdiameter")));
138
139   if (primitive & MLP_STEM)
140     {
141       // assume MLP_UP
142       Real y_bottom = 0.0, y_top = 3.0 * staff_space;
143
144       if (primitive & MLP_DOWN)
145         {
146           y_bottom = -y_top;
147           y_top = 0.0;
148         }
149
150       Interval x_extent (0, thickness);
151       Interval y_extent (y_bottom, y_top);
152       Box join_box (x_extent, y_extent);
153
154       Stencil join = Lookup::round_filled_box (join_box, blotdiameter);
155       out.add_stencil (join);
156     }
157
158   SCM join_right_scm = me->get_property ("join-right-amount");
159
160   if (join_right_scm != SCM_EOL)
161     {
162       int join_right = scm_to_int (join_right_scm);
163       if (join_right)
164         {
165           Real y_top = join_right * 0.5 * staff_space;
166           Real y_bottom = 0.0;
167
168           if (y_top < 0.0)
169             {
170               y_bottom = y_top;
171               y_top = 0.0;
172             }
173
174           Interval x_extent (width - thickness, width);
175           Interval y_extent (y_bottom, y_top);
176           Box join_box (x_extent, y_extent);
177           Stencil join = Lookup::round_filled_box (join_box, blotdiameter);
178
179           out.add_stencil (join);
180         }
181       else
182         {
183           programming_error (_f ("Mensural_ligature: (join_right == 0)"));
184         }
185     }
186
187 #if 0 // what happend with the ledger lines?
188   int pos = Staff_symbol_referencer::get_rounded_position (me);
189   if (primitive & MLP_FLEXA)
190     {
191       pos += delta_pitch;
192       add_ledger_lines (me, &out, pos, 0.5 * delta_pitch, ledger_take_space);
193     }
194 #endif
195
196   return out;
197 }
198
199 MAKE_SCHEME_CALLBACK (Mensural_ligature, brew_ligature_primitive, 1);
200 SCM
201 Mensural_ligature::brew_ligature_primitive (SCM smob)
202 {
203   Grob *me = unsmob_grob (smob);
204   return internal_brew_primitive (me).smobbed_copy ();
205 }
206
207 MAKE_SCHEME_CALLBACK (Mensural_ligature, print, 1);
208 SCM
209 Mensural_ligature::print (SCM)
210 {
211   return SCM_EOL;
212 }
213
214 ADD_INTERFACE (Mensural_ligature, "mensural-ligature-interface",
215                "A mensural ligature",
216                "delta-pitch flexa-width head-width join-right-amount " // "add-join "
217                "ligature-primitive-callback primitive thickness");