Add FiguredBass to ChoirStaff's accepts list.
[lilypond/mpolesky.git] / lily / arpeggio.cc
blobfe5ed02dcd48d5b66b41a3023470fe6d760bb271
1 /*
2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 2000--2009 Jan Nieuwenhuizen <janneke@gnu.org>
6 LilyPond is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 LilyPond is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
20 #include "arpeggio.hh"
22 #include "bezier.hh"
23 #include "font-interface.hh"
24 #include "grob.hh"
25 #include "lookup.hh"
26 #include "output-def.hh"
27 #include "pointer-group-interface.hh"
28 #include "staff-symbol-referencer.hh"
29 #include "staff-symbol.hh"
30 #include "stem.hh"
31 #include "warn.hh"
33 Grob *
34 Arpeggio::get_common_y (Grob *me)
36 Grob *common = me;
38 extract_grob_set (me, "stems", stems);
39 for (vsize i = 0; i < stems.size (); i++)
41 Grob *stem = stems[i];
42 common = common->common_refpoint (Staff_symbol_referencer::get_staff_symbol (stem),
43 Y_AXIS);
46 return common;
49 MAKE_SCHEME_CALLBACK(Arpeggio, calc_positions, 1);
50 SCM
51 Arpeggio::calc_positions (SCM grob)
53 Grob *me = unsmob_grob (grob);
54 Grob *common = get_common_y (me);
57 TODO:
59 Using stems here is not very convenient; should store noteheads
60 instead, and also put them into the support. Now we will mess up
61 in vicinity of a collision.
63 Interval heads;
64 Real my_y = me->relative_coordinate (common, Y_AXIS);
66 extract_grob_set (me, "stems", stems);
67 for (vsize i = 0; i < stems.size (); i++)
69 Grob *stem = stems[i];
70 Grob *ss = Staff_symbol_referencer::get_staff_symbol (stem);
71 Interval iv = Stem::head_positions (stem);
72 iv *= Staff_symbol::staff_space (ss) / 2.0;
74 heads.unite (iv + ss->relative_coordinate (common, Y_AXIS)
75 - my_y);
78 heads *= 1/Staff_symbol_referencer::staff_space(me);
80 return ly_interval2scm (heads);
83 MAKE_SCHEME_CALLBACK (Arpeggio, print, 1);
84 SCM
85 Arpeggio::print (SCM smob)
87 Grob *me = unsmob_grob (smob);
88 Interval heads = robust_scm2interval (me->get_property ("positions"),
89 Interval())
90 * Staff_symbol_referencer::staff_space (me);
92 if (heads.is_empty () || heads.length () < 0.5)
94 if (!to_boolean (me->get_property ("transparent")))
96 me->warning ("no heads for arpeggio found?");
97 me->suicide ();
99 return SCM_EOL;
102 SCM ad = me->get_property ("arpeggio-direction");
103 Direction dir = CENTER;
104 if (is_direction (ad))
105 dir = to_dir (ad);
107 Stencil mol;
108 Font_metric *fm = Font_interface::get_default_font (me);
109 Stencil squiggle = fm->find_by_name ("scripts.arpeggio");
112 Compensate for rounding error which may occur when a chord
113 reaches the center line, resulting in an extra squiggle
114 being added to the arpeggio stencil. This value is appreciably
115 larger than the rounding error, which is in the region of 1e-16
116 for a global-staff-size of 20, but small enough that it does not
117 interfere with smaller staff sizes.
119 const Real epsilon = 1e-3;
121 Stencil arrow;
122 if (dir)
124 arrow = fm->find_by_name ("scripts.arpeggio.arrow." + to_string (dir));
125 heads[dir] -= dir * arrow.extent (Y_AXIS).length ();
128 while (mol.extent (Y_AXIS).length () + epsilon < heads.length ())
130 mol.add_at_edge (Y_AXIS, UP, squiggle, 0.0);
133 mol.translate_axis (heads[LEFT], Y_AXIS);
134 if (dir)
135 mol.add_at_edge (Y_AXIS, dir, arrow, 0);
137 return mol.smobbed_copy ();
140 /* Draws a vertical bracket to the left of a chord
141 Chris Jackson <chris@fluffhouse.org.uk> */
143 MAKE_SCHEME_CALLBACK (Arpeggio, brew_chord_bracket, 1);
145 Arpeggio::brew_chord_bracket (SCM smob)
147 Grob *me = unsmob_grob (smob);
148 Interval heads = robust_scm2interval (me->get_property ("positions"),
149 Interval())
150 * Staff_symbol_referencer::staff_space (me);
152 Real lt = me->layout ()->get_dimension (ly_symbol2scm ("line-thickness"));
153 Real sp = 1.5 * Staff_symbol_referencer::staff_space (me);
154 Real dy = heads.length () + sp;
155 Real x = 0.7;
157 Stencil mol (Lookup::bracket (Y_AXIS, Interval (0, dy), lt, x, lt));
158 mol.translate_axis (heads[LEFT] - sp / 2.0, Y_AXIS);
159 return mol.smobbed_copy ();
162 MAKE_SCHEME_CALLBACK (Arpeggio, brew_chord_slur, 1);
164 Arpeggio::brew_chord_slur (SCM smob)
166 Grob *me = unsmob_grob (smob);
167 SCM dash_definition = me->get_property ("dash-definition");
168 Interval heads = robust_scm2interval (me->get_property ("positions"),
169 Interval())
170 * Staff_symbol_referencer::staff_space (me);
172 Real lt = me->layout ()->get_dimension (ly_symbol2scm ("line-thickness"));
173 Real dy = heads.length ();
175 Real height_limit = 1.5;
176 Real ratio = .33;
177 Bezier curve = slur_shape (dy, height_limit, ratio);
178 curve.rotate (M_PI / 2);
180 Stencil mol (Lookup::slur (curve, lt, lt, dash_definition));
181 mol.translate_axis (heads[LEFT], Y_AXIS);
182 return mol.smobbed_copy ();
186 We have to do a callback, because print () triggers a
187 vertical alignment if it is cross-staff.
189 MAKE_SCHEME_CALLBACK (Arpeggio, width, 1);
191 Arpeggio::width (SCM smob)
193 Grob *me = unsmob_grob (smob);
194 Stencil arpeggio = Font_interface::get_default_font (me)->find_by_name ("scripts.arpeggio");
196 return ly_interval2scm (arpeggio.extent (X_AXIS));
199 MAKE_SCHEME_CALLBACK (Arpeggio, height, 1);
201 Arpeggio::height (SCM smob)
203 return Grob::stencil_height (smob);
206 MAKE_SCHEME_CALLBACK (Arpeggio, pure_height, 3);
208 Arpeggio::pure_height (SCM smob, SCM, SCM)
210 Grob *me = unsmob_grob (smob);
211 if (to_boolean (me->get_property ("cross-staff")))
212 return ly_interval2scm (Interval ());
214 return height (smob);
217 ADD_INTERFACE (Arpeggio,
218 "Functions and settings for drawing an arpeggio symbol.",
220 /* properties */
221 "arpeggio-direction "
222 "positions "
223 "script-priority " // TODO: make around-note-interface
224 "stems "
225 "dash-definition " // TODO: make apply to non-slur arpeggios