2 plet-spanner.cc -- implement Tuplet_spanner
4 source file of the GNU LilyPond music typesetter
6 (c) 1997--2000 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_spanner::set_interface (Grob
*me
)
29 me
->set_interface (ly_symbol2scm ("tuplet-bracket"));
36 MAKE_SCHEME_CALLBACK(Tuplet_spanner
,brew_molecule
,1);
39 Tuplet_spanner::brew_molecule (SCM smob
)
41 Grob
*me
= unsmob_grob (smob
);
44 // Default behaviour: number always, bracket when no beam!
45 bool par_beam
= to_boolean (me
->get_grob_property ("parallel-beam"));
46 bool bracket_visibility
= !par_beam
;
47 bool number_visibility
= true;
49 SCM bracket
= me
->get_grob_property ("tuplet-bracket-visibility");
50 if (gh_boolean_p (bracket
))
52 bracket_visibility
= gh_scm2bool (bracket
);
54 else if (bracket
== ly_symbol2scm ("if-no-beam"))
55 bracket_visibility
= !par_beam
;
57 SCM numb
= me
->get_grob_property ("tuplet-number-visibility");
58 if (gh_boolean_p (numb
))
60 number_visibility
= gh_scm2bool (numb
);
62 else if (bracket
== ly_symbol2scm ("if-no-beam"))
63 number_visibility
= !par_beam
;
65 if (gh_pair_p (me
->get_grob_property ("columns")))
67 Link_array
<Grob
> column_arr
=
68 Pointer_group_interface__extract_elements (me
, (Grob
*)0, "columns");
70 Real ncw
= column_arr
.top ()->extent(column_arr
.top (), X_AXIS
).length ();
71 Real w
= dynamic_cast<Spanner
*>(me
)->spanner_length () + ncw
;
73 Real staff_space
= 1.0;
74 Direction dir
= Directional_element_interface::get (me
);
75 Real dy
= gh_scm2double (me
->get_grob_property ("delta-y"));
76 SCM number
= me
->get_grob_property ("text");
77 if (gh_string_p (number
) && number_visibility
)
79 SCM properties
= Font_interface::font_alist_chain (me
);
80 Molecule num
= Text_item::text2molecule (me
, number
, properties
);
81 num
.align_to (X_AXIS
, CENTER
);
82 num
.translate_axis (w
/2, X_AXIS
);
83 num
.align_to (Y_AXIS
, CENTER
);
84 num
.translate_axis (dir
* staff_space
, Y_AXIS
);
86 num
.translate_axis (dy
/2, Y_AXIS
);
88 mol
.add_molecule (num
);
91 if (bracket_visibility
)
93 Real lt
= me
->paper_l ()->get_var ("stafflinethickness");
95 SCM thick
= me
->get_grob_property ("thick");
96 SCM gap
= me
->get_grob_property ("number-gap");
98 SCM at
=gh_list(ly_symbol2scm ("tuplet"),
103 gh_double2scm (gh_scm2double (thick
)* lt
),
108 mol
.add_molecule (Molecule (b
, at
));
111 return mol
.smobbed_copy ();
118 use first -> last note for slope, and then correct for disturbing
121 Tuplet_spanner::calc_position_and_height (Grob
*me
,Real
*offset
, Real
* dy
)
123 Link_array
<Grob
> column_arr
=
124 Pointer_group_interface__extract_elements (me
, (Grob
*)0, "columns");
127 Grob
* commony
= me
->common_refpoint (me
->get_grob_property ("columns"), Y_AXIS
);
128 Grob
* commonx
= me
->common_refpoint (me
->get_grob_property ("columns"), X_AXIS
);
130 Direction d
= Directional_element_interface::get (me
);
133 Use outer non-rest columns to determine slope
136 while (l
<column_arr
.size() && Note_column::rest_b(column_arr
[l
]))
139 int r
= column_arr
.size ()- 1;
140 while (r
>= l
&& Note_column::rest_b(column_arr
[r
]))
145 *dy
= column_arr
[r
]->extent (commony
, Y_AXIS
) [d
]
146 - column_arr
[l
]->extent (commony
, Y_AXIS
) [d
] ;
152 *offset
= - d
* infinity_f
;
154 if (!column_arr
.size ())
157 Real x0
= column_arr
[0]->relative_coordinate (commonx
, X_AXIS
);
158 Real x1
= column_arr
.top ()->relative_coordinate (commonx
, X_AXIS
);
160 Real factor
= column_arr
.size () > 1 ? 1/(x1
- x0
) : 1.0;
162 for (int i
= 0; i
< column_arr
.size (); i
++)
164 Real notey
= column_arr
[i
]->extent (commony
, Y_AXIS
)[d
]
165 - me
->relative_coordinate (commony
, Y_AXIS
);
167 Real x
= column_arr
[i
]->relative_coordinate (commonx
, X_AXIS
) - x0
;
168 Real tuplety
= *dy
* x
* factor
;
170 if (notey
* d
> (*offset
+ tuplety
) * d
)
171 *offset
= notey
- tuplety
;
176 use first -> last note for slope,
179 Tuplet_spanner::calc_dy (Grob
*me
,Real
* dy
)
181 Link_array
<Grob
> column_arr
=
182 Pointer_group_interface__extract_elements (me
, (Grob
*)0, "columns");
187 Direction d
= Directional_element_interface::get (me
);
188 *dy
= column_arr
.top ()->extent (column_arr
.top (), Y_AXIS
) [d
]
189 - column_arr
[0]->extent (column_arr
[0], Y_AXIS
) [d
];
191 MAKE_SCHEME_CALLBACK(Tuplet_spanner
,after_line_breaking
,1);
194 Tuplet_spanner::after_line_breaking (SCM smob
)
196 Grob
* me
= unsmob_grob (smob
);
197 Link_array
<Note_column
> column_arr
=
198 Pointer_group_interface__extract_elements (me
, (Note_column
*)0, "columns");
199 Spanner
*sp
= dynamic_cast<Spanner
*> (me
);
202 if (!column_arr
.size ())
205 return SCM_UNSPECIFIED
;
208 Direction d
= Directional_element_interface::get (me
);
211 d
= Tuplet_spanner::get_default_dir (me
);
212 Directional_element_interface::set (me
, d
);
217 calc_position_and_height (me
,&offset
,&dy
);
219 me
->set_grob_property ("delta-y", gh_double2scm (dy
));
221 me
->translate_axis (offset
, Y_AXIS
);
223 if (scm_ilength (me
->get_grob_property ("beams")) == 1)
225 SCM bs
= me
->get_grob_property ("beams");
226 Grob
*b
= unsmob_grob (gh_car (bs
));
227 Spanner
* beam_l
= dynamic_cast<Spanner
*> (b
);
229 && sp
->get_bound (LEFT
)->column_l () == beam_l
->get_bound (LEFT
)->column_l ()
230 && sp
->get_bound (RIGHT
)->column_l () == beam_l
->get_bound (RIGHT
)->column_l ())
231 me
->set_grob_property ("parallel-beam", SCM_BOOL_T
);
233 return SCM_UNSPECIFIED
;
238 Tuplet_spanner::get_default_dir (Grob
*me
)
241 SCM dir_sym
=me
->get_grob_property ("dir-forced");
242 if (isdir_b (dir_sym
))
250 for (SCM s
= me
->get_grob_property ("columns"); gh_pair_p (s
); s
= gh_cdr (s
))
252 Grob
* nc
= unsmob_grob (gh_car (s
));
253 if (Note_column::dir (nc
) < 0)
264 Tuplet_spanner::add_beam (Grob
*me
, Grob
*b
)
266 me
->add_dependency (b
);
267 Pointer_group_interface::add_element (me
, "beams",b
);
271 Tuplet_spanner::add_column (Grob
*me
, Item
*n
)
273 Pointer_group_interface::add_element (me
, "columns",n
);
274 me
->add_dependency (n
);
276 add_bound_item (dynamic_cast<Spanner
*> (me
), n
);