2 arpeggio.cc -- implement Arpeggio
4 source file of the GNU LilyPond music typesetter
6 (c) 2000--2007 Jan Nieuwenhuizen <janneke@gnu.org>
12 #include "output-def.hh"
14 #include "staff-symbol-referencer.hh"
15 #include "staff-symbol.hh"
17 #include "font-interface.hh"
19 #include "pointer-group-interface.hh"
22 Arpeggio::get_common_y (Grob *me)
26 extract_grob_set (me, "stems", stems);
27 for (vsize i = 0; i < stems.size (); i++)
29 Grob *stem = stems[i];
30 common = common->common_refpoint (Staff_symbol_referencer::get_staff_symbol (stem),
37 MAKE_SCHEME_CALLBACK(Arpeggio, calc_positions, 1);
39 Arpeggio::calc_positions (SCM grob)
41 Grob *me = unsmob_grob (grob);
42 Grob *common = get_common_y (me);
47 Using stems here is not very convenient; should store noteheads
48 instead, and also put them into the support. Now we will mess up
49 in vicinity of a collision.
52 Real my_y = me->relative_coordinate (common, Y_AXIS);
54 extract_grob_set (me, "stems", stems);
55 for (vsize i = 0; i < stems.size (); i++)
57 Grob *stem = stems[i];
58 Grob *ss = Staff_symbol_referencer::get_staff_symbol (stem);
59 Interval iv = Stem::head_positions (stem);
60 iv *= Staff_symbol::staff_space (ss) / 2.0;
62 heads.unite (iv + ss->relative_coordinate (common, Y_AXIS)
66 heads *= 1/Staff_symbol_referencer::staff_space(me);
68 return ly_interval2scm (heads);
71 MAKE_SCHEME_CALLBACK (Arpeggio, print, 1);
73 Arpeggio::print (SCM smob)
75 Grob *me = unsmob_grob (smob);
76 Interval heads = robust_scm2interval (me->get_property ("positions"),
78 * Staff_symbol_referencer::staff_space (me);
80 if (heads.is_empty () || heads.length () < 0.5)
82 if (!to_boolean (me->get_property ("transparent")))
84 me->warning ("no heads for arpeggio found?");
90 SCM ad = me->get_property ("arpeggio-direction");
91 Direction dir = CENTER;
92 if (is_direction (ad))
96 Font_metric *fm = Font_interface::get_default_font (me);
97 Stencil squiggle = fm->find_by_name ("scripts.arpeggio");
102 arrow = fm->find_by_name ("scripts.arpeggio.arrow." + to_string (dir));
103 heads[dir] -= dir * arrow.extent (Y_AXIS).length ();
106 for (Real y = heads[LEFT]; y < heads[RIGHT];
107 y += squiggle.extent (Y_AXIS).length ())
108 mol.add_at_edge (Y_AXIS, UP, squiggle, 0.0);
110 mol.translate_axis (heads[LEFT], Y_AXIS);
112 mol.add_at_edge (Y_AXIS, dir, arrow, 0);
114 return mol.smobbed_copy ();
117 /* Draws a vertical bracket to the left of a chord
118 Chris Jackson <chris@fluffhouse.org.uk> */
120 MAKE_SCHEME_CALLBACK (Arpeggio, brew_chord_bracket, 1);
122 Arpeggio::brew_chord_bracket (SCM smob)
124 Grob *me = unsmob_grob (smob);
125 Interval heads = robust_scm2interval (me->get_property ("positions"),
127 * Staff_symbol_referencer::staff_space (me);
129 Real lt = me->layout ()->get_dimension (ly_symbol2scm ("line-thickness"));
130 Real sp = 1.5 * Staff_symbol_referencer::staff_space (me);
131 Real dy = heads.length () + sp;
134 Stencil mol (Lookup::bracket (Y_AXIS, Interval (0, dy), lt, x, lt));
135 mol.translate_axis (heads[LEFT] - sp / 2.0, Y_AXIS);
136 return mol.smobbed_copy ();
140 We have to do a callback, because print () triggers a
141 vertical alignment if it is cross-staff.
143 MAKE_SCHEME_CALLBACK (Arpeggio, width, 1);
145 Arpeggio::width (SCM smob)
147 Grob *me = unsmob_grob (smob);
148 Stencil arpeggio = Font_interface::get_default_font (me)->find_by_name ("scripts.arpeggio");
150 return ly_interval2scm (arpeggio.extent (X_AXIS));
153 MAKE_SCHEME_CALLBACK (Arpeggio, height, 1);
155 Arpeggio::height (SCM smob)
157 return Grob::stencil_height (smob);
160 MAKE_SCHEME_CALLBACK (Arpeggio, pure_height, 3);
162 Arpeggio::pure_height (SCM smob, SCM, SCM)
164 Grob *me = unsmob_grob (smob);
165 if (to_boolean (me->get_property ("cross-staff")))
166 return ly_interval2scm (Interval ());
168 return height (smob);
171 ADD_INTERFACE (Arpeggio,
172 "Functions and settings for drawing an arpeggio symbol (a"
173 " wavy line left to noteheads.",
176 "arpeggio-direction "
178 "script-priority " // TODO: make around-note-interface