2 plet-spanner.cc -- implement Tuplet_bracket
4 source file of the GNU LilyPond music typesetter
6 (c) 1997--2001 Jan Nieuwenhuizen <janneke@gnu.org>
13 #include "font-interface.hh"
14 #include "molecule.hh"
15 #include "paper-column.hh"
16 #include "paper-def.hh"
17 #include "text-item.hh"
18 #include "tuplet-spanner.hh"
20 #include "note-column.hh"
21 #include "dimensions.hh"
22 #include "group-interface.hh"
23 #include "directional-element-interface.hh"
27 Tuplet_bracket::set_interface (Grob*me)
29 me->set_interface (ly_symbol2scm ("tuplet-bracket"));
33 TODO: use stem->beam fields to find Beams. Autobeams aren't found
34 through the engraver mechanism. */
35 MAKE_SCHEME_CALLBACK(Tuplet_bracket,brew_molecule,1);
37 Tuplet_bracket::brew_molecule (SCM smob)
39 Grob *me= unsmob_grob (smob);
42 // Default behaviour: number always, bracket when no beam!
43 bool par_beam = to_boolean (me->get_grob_property ("parallel-beam"));
44 bool bracket_visibility = !par_beam;
45 bool number_visibility = true;
47 SCM bracket = me->get_grob_property ("tuplet-bracket-visibility");
48 if (gh_boolean_p (bracket))
50 bracket_visibility = gh_scm2bool (bracket);
52 else if (bracket == ly_symbol2scm ("if-no-beam"))
53 bracket_visibility = !par_beam;
55 SCM numb = me->get_grob_property ("tuplet-number-visibility");
56 if (gh_boolean_p (numb))
58 number_visibility = gh_scm2bool (numb);
60 else if (bracket == ly_symbol2scm ("if-no-beam"))
61 number_visibility = !par_beam;
63 if (gh_pair_p (me->get_grob_property ("columns")))
65 Link_array<Grob> column_arr=
66 Pointer_group_interface__extract_elements (me, (Grob*)0, "columns");
68 Real ncw = column_arr.top ()->extent(column_arr.top (), X_AXIS).length ();
69 Real w = dynamic_cast<Spanner*>(me)->spanner_length () + ncw;
71 Real staff_space = 1.0;
72 Direction dir = Directional_element_interface::get (me);
73 Real dy = gh_scm2double (me->get_grob_property ("delta-y"));
74 SCM number = me->get_grob_property ("text");
75 if (gh_string_p (number) && number_visibility)
77 SCM properties = Font_interface::font_alist_chain (me);
78 Molecule num = Text_item::text2molecule (me, number, properties);
79 num.align_to (X_AXIS, CENTER);
80 num.translate_axis (w/2, X_AXIS);
81 num.align_to (Y_AXIS, CENTER);
82 num.translate_axis (dir * staff_space, Y_AXIS);
84 num.translate_axis (dy/2, Y_AXIS);
86 mol.add_molecule (num);
89 if (bracket_visibility)
91 Real lt = me->paper_l ()->get_var ("stafflinethickness");
93 SCM thick = me->get_grob_property ("thick");
94 SCM gap = me->get_grob_property ("number-gap");
96 SCM at =gh_list(ly_symbol2scm ("tuplet"),
101 gh_double2scm (gh_scm2double (thick)* lt),
106 mol.add_molecule (Molecule (b, at));
109 return mol.smobbed_copy ();
116 use first -> last note for slope, and then correct for disturbing
119 Tuplet_bracket::calc_position_and_height (Grob*me,Real *offset, Real * dy)
121 Link_array<Grob> column_arr=
122 Pointer_group_interface__extract_elements (me, (Grob*)0, "columns");
125 Grob * commony = me->common_refpoint (me->get_grob_property ("columns"), Y_AXIS);
126 Grob * commonx = me->common_refpoint (me->get_grob_property ("columns"), X_AXIS);
128 Direction d = Directional_element_interface::get (me);
131 Use outer non-rest columns to determine slope
134 while (l <column_arr.size() && Note_column::rest_b(column_arr[l]))
137 int r = column_arr.size ()- 1;
138 while (r >= l && Note_column::rest_b(column_arr[r]))
143 *dy = column_arr[r]->extent (commony, Y_AXIS) [d]
144 - column_arr[l]->extent (commony, Y_AXIS) [d] ;
150 *offset = - d * infinity_f;
152 if (!column_arr.size ())
155 Real x0 = column_arr[0]->relative_coordinate (commonx, X_AXIS);
156 Real x1 = column_arr.top ()->relative_coordinate (commonx, X_AXIS);
158 Real factor = column_arr.size () > 1 ? 1/(x1 - x0) : 1.0;
160 for (int i = 0; i < column_arr.size (); i++)
162 Real notey = column_arr[i]->extent (commony, Y_AXIS)[d]
163 - me->relative_coordinate (commony, Y_AXIS);
165 Real x = column_arr[i]->relative_coordinate (commonx, X_AXIS) - x0;
166 Real tuplety = *dy * x * factor;
168 if (notey * d > (*offset + tuplety) * d)
169 *offset = notey - tuplety;
174 use first -> last note for slope,
177 Tuplet_bracket::calc_dy (Grob*me,Real * dy)
179 Link_array<Grob> column_arr=
180 Pointer_group_interface__extract_elements (me, (Grob*)0, "columns");
185 Direction d = Directional_element_interface::get (me);
186 *dy = column_arr.top ()->extent (column_arr.top (), Y_AXIS) [d]
187 - column_arr[0]->extent (column_arr[0], Y_AXIS) [d];
189 MAKE_SCHEME_CALLBACK(Tuplet_bracket,after_line_breaking,1);
192 Tuplet_bracket::after_line_breaking (SCM smob)
194 Grob * me = unsmob_grob (smob);
195 Link_array<Note_column> column_arr=
196 Pointer_group_interface__extract_elements (me, (Note_column*)0, "columns");
197 Spanner *sp = dynamic_cast<Spanner*> (me);
200 if (!column_arr.size ())
203 return SCM_UNSPECIFIED;
206 Direction d = Directional_element_interface::get (me);
209 d = Tuplet_bracket::get_default_dir (me);
210 Directional_element_interface::set (me, d);
215 calc_position_and_height (me,&offset,&dy);
217 me->set_grob_property ("delta-y", gh_double2scm (dy));
219 me->translate_axis (offset, Y_AXIS);
221 if (scm_ilength (me->get_grob_property ("beams")) == 1)
223 SCM bs = me->get_grob_property ("beams");
224 Grob *b = unsmob_grob (gh_car (bs));
225 Spanner * beam_l = dynamic_cast<Spanner *> (b);
227 && sp->get_bound (LEFT)->column_l () == beam_l->get_bound (LEFT)->column_l ()
228 && sp->get_bound (RIGHT)->column_l () == beam_l->get_bound (RIGHT)->column_l ())
229 me->set_grob_property ("parallel-beam", SCM_BOOL_T);
231 return SCM_UNSPECIFIED;
236 Tuplet_bracket::get_default_dir (Grob*me)
239 SCM dir_sym =me->get_grob_property ("dir-forced");
240 if (isdir_b (dir_sym))
248 for (SCM s = me->get_grob_property ("columns"); gh_pair_p (s); s = gh_cdr (s))
250 Grob * nc = unsmob_grob (gh_car (s));
251 if (Note_column::dir (nc) < 0)
262 Tuplet_bracket::add_beam (Grob*me, Grob *b)
264 me->add_dependency (b);
265 Pointer_group_interface::add_element (me, "beams",b);
269 Tuplet_bracket::add_column (Grob*me, Item*n)
271 Pointer_group_interface::add_element (me, "columns",n);
272 me->add_dependency (n);
274 add_bound_item (dynamic_cast<Spanner*> (me), n);