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