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