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 "font-interface.hh"
15 #include "output-def.hh"
16 #include "pointer-group-interface.hh"
17 #include "staff-symbol-referencer.hh"
18 #include "staff-symbol.hh"
23 Arpeggio::get_common_y (Grob
*me
)
27 extract_grob_set (me
, "stems", stems
);
28 for (vsize i
= 0; i
< stems
.size (); i
++)
30 Grob
*stem
= stems
[i
];
31 common
= common
->common_refpoint (Staff_symbol_referencer::get_staff_symbol (stem
),
38 MAKE_SCHEME_CALLBACK(Arpeggio
, calc_positions
, 1);
40 Arpeggio::calc_positions (SCM grob
)
42 Grob
*me
= unsmob_grob (grob
);
43 Grob
*common
= get_common_y (me
);
48 Using stems here is not very convenient; should store noteheads
49 instead, and also put them into the support. Now we will mess up
50 in vicinity of a collision.
53 Real my_y
= me
->relative_coordinate (common
, Y_AXIS
);
55 extract_grob_set (me
, "stems", stems
);
56 for (vsize i
= 0; i
< stems
.size (); i
++)
58 Grob
*stem
= stems
[i
];
59 Grob
*ss
= Staff_symbol_referencer::get_staff_symbol (stem
);
60 Interval iv
= Stem::head_positions (stem
);
61 iv
*= Staff_symbol::staff_space (ss
) / 2.0;
63 heads
.unite (iv
+ ss
->relative_coordinate (common
, Y_AXIS
)
67 heads
*= 1/Staff_symbol_referencer::staff_space(me
);
69 return ly_interval2scm (heads
);
72 MAKE_SCHEME_CALLBACK (Arpeggio
, print
, 1);
74 Arpeggio::print (SCM smob
)
76 Grob
*me
= unsmob_grob (smob
);
77 Interval heads
= robust_scm2interval (me
->get_property ("positions"),
79 * Staff_symbol_referencer::staff_space (me
);
81 if (heads
.is_empty () || heads
.length () < 0.5)
83 if (!to_boolean (me
->get_property ("transparent")))
85 me
->warning ("no heads for arpeggio found?");
91 SCM ad
= me
->get_property ("arpeggio-direction");
92 Direction dir
= CENTER
;
93 if (is_direction (ad
))
97 Font_metric
*fm
= Font_interface::get_default_font (me
);
98 Stencil squiggle
= fm
->find_by_name ("scripts.arpeggio");
103 arrow
= fm
->find_by_name ("scripts.arpeggio.arrow." + to_string (dir
));
104 heads
[dir
] -= dir
* arrow
.extent (Y_AXIS
).length ();
107 for (Real y
= heads
[LEFT
]; y
< heads
[RIGHT
];
108 y
+= squiggle
.extent (Y_AXIS
).length ())
109 mol
.add_at_edge (Y_AXIS
, UP
, squiggle
, 0.0);
111 mol
.translate_axis (heads
[LEFT
], Y_AXIS
);
113 mol
.add_at_edge (Y_AXIS
, dir
, arrow
, 0);
115 return mol
.smobbed_copy ();
118 /* Draws a vertical bracket to the left of a chord
119 Chris Jackson <chris@fluffhouse.org.uk> */
121 MAKE_SCHEME_CALLBACK (Arpeggio
, brew_chord_bracket
, 1);
123 Arpeggio::brew_chord_bracket (SCM smob
)
125 Grob
*me
= unsmob_grob (smob
);
126 Interval heads
= robust_scm2interval (me
->get_property ("positions"),
128 * Staff_symbol_referencer::staff_space (me
);
130 Real lt
= me
->layout ()->get_dimension (ly_symbol2scm ("line-thickness"));
131 Real sp
= 1.5 * Staff_symbol_referencer::staff_space (me
);
132 Real dy
= heads
.length () + sp
;
135 Stencil
mol (Lookup::bracket (Y_AXIS
, Interval (0, dy
), lt
, x
, lt
));
136 mol
.translate_axis (heads
[LEFT
] - sp
/ 2.0, Y_AXIS
);
137 return mol
.smobbed_copy ();
140 MAKE_SCHEME_CALLBACK (Arpeggio
, brew_chord_slur
, 1);
142 Arpeggio::brew_chord_slur (SCM smob
)
144 Grob
*me
= unsmob_grob (smob
);
145 Interval heads
= robust_scm2interval (me
->get_property ("positions"),
147 * Staff_symbol_referencer::staff_space (me
);
149 Real lt
= me
->layout ()->get_dimension (ly_symbol2scm ("line-thickness"));
150 Real dy
= heads
.length ();
152 Real height_limit
= 1.5;
154 Bezier curve
= slur_shape (dy
, height_limit
, ratio
);
155 curve
.rotate (M_PI
/ 2);
157 Stencil
mol (Lookup::slur (curve
, lt
, lt
));
158 mol
.translate_axis (heads
[LEFT
], Y_AXIS
);
159 return mol
.smobbed_copy ();
163 We have to do a callback, because print () triggers a
164 vertical alignment if it is cross-staff.
166 MAKE_SCHEME_CALLBACK (Arpeggio
, width
, 1);
168 Arpeggio::width (SCM smob
)
170 Grob
*me
= unsmob_grob (smob
);
171 Stencil arpeggio
= Font_interface::get_default_font (me
)->find_by_name ("scripts.arpeggio");
173 return ly_interval2scm (arpeggio
.extent (X_AXIS
));
176 MAKE_SCHEME_CALLBACK (Arpeggio
, height
, 1);
178 Arpeggio::height (SCM smob
)
180 return Grob::stencil_height (smob
);
183 MAKE_SCHEME_CALLBACK (Arpeggio
, pure_height
, 3);
185 Arpeggio::pure_height (SCM smob
, SCM
, SCM
)
187 Grob
*me
= unsmob_grob (smob
);
188 if (to_boolean (me
->get_property ("cross-staff")))
189 return ly_interval2scm (Interval ());
191 return height (smob
);
194 ADD_INTERFACE (Arpeggio
,
195 "Functions and settings for drawing an arpeggio symbol (a"
196 " wavy line left to noteheads.",
199 "arpeggio-direction "
201 "script-priority " // TODO: make around-note-interface