source file of the GNU LilyPond music typesetter
- (c) 1997--2007 Jan Nieuwenhuizen <janneke@gnu.org>
+ (c) 1997--2009 Jan Nieuwenhuizen <janneke@gnu.org>
Han-Wen Nienhuys <hanwen@xs4all.nl>
*/
/*
Return beam that encompasses the span of the tuplet bracket.
*/
-
Grob *
Tuplet_bracket::parallel_beam (Grob *me_grob, vector<Grob*> const &cols,
bool *equally_long)
Drul_array<Grob*> stems (Note_column::get_stem (cols[0]),
Note_column::get_stem (cols.back ()));
- if (dynamic_cast<Item*> (stems[RIGHT])->get_column ()
- != me->get_bound (RIGHT)->get_column ())
+ if (!stems[RIGHT]
+ || !stems[LEFT]
+ || (dynamic_cast<Item*> (stems[RIGHT])->get_column ()
+ != me->get_bound (RIGHT)->get_column ()))
return 0;
Drul_array<Grob*> beams;
do
{
Direction break_dir = bounds[d]->break_status_dir ();
-
Spanner *orig_spanner = dynamic_cast<Spanner*> (me->original ());
-
vsize neighbor_idx = me->get_break_index () - break_dir;
if (break_dir
&& d == RIGHT
/*
We're connecting to a column, for the last bit of a broken
fullLength bracket.
-
- TODO: make padding tunable?
*/
- Real padding = 1.0;
+ Real padding =
+ robust_scm2double(me->get_property("full-length-padding"), 1.0);
if (bounds[d]->break_status_dir ())
padding = 0.0;
-
- x_span[d]
- = robust_relative_extent (bounds[d], commonx, X_AXIS) [LEFT]
- - padding;
+
+ Real coord = bounds[d]->relative_coordinate(commonx, X_AXIS);
+ if (to_boolean (me->get_property ("full-length-to-extent")))
+ coord = robust_relative_extent(bounds[d], commonx, X_AXIS)[LEFT];
+
+ coord = max (coord, x_span[LEFT]);
+
+ x_span[d] = coord - padding;
}
}
while (flip (&d) != LEFT);
bracket_visibility = ly_scm2bool (bracket);
else if (bracket == ly_symbol2scm ("if-no-beam"))
bracket_visibility = !par_beam;
-
+ /* Don't print a tuplet bracket and number if no control-points were calculated */
SCM cpoints = me->get_property ("control-points");
if (scm_ilength (cpoints) < 2)
{
me->suicide ();
return SCM_EOL;
}
+ /* if the tuplet does not span any time, i.e. a single-note tuplet, hide
+ the bracket, but still let the number be displayed */
+ if (robust_scm2moment (me->get_bound (LEFT)->get_column ()->get_property ("when"), Moment (0))
+ == robust_scm2moment (me->get_bound (RIGHT)->get_column ()->get_property ("when"), Moment (0)))
+ {
+ bracket_visibility = false;
+ }
Drul_array<Offset> points;
points[LEFT] = ly_scm2offset (scm_car (cpoints));
Interval x_span (points[LEFT][X_AXIS], points[RIGHT][X_AXIS]);
Drul_array<Real> positions (points[LEFT][Y_AXIS], points[RIGHT][Y_AXIS]);
-
-
Output_def *pap = me->layout ();
Grob *number_grob = unsmob_grob (me->get_object ("tuplet-number"));
commony = common_refpoint_of_array (tuplets, commony, Y_AXIS);
if (Grob *st = Staff_symbol_referencer::get_staff_symbol (me))
commony = st->common_refpoint (commony, Y_AXIS);
+ Real my_offset = me->relative_coordinate (commony, Y_AXIS);
Grob *commonx = get_common_x (me);
commonx = common_refpoint_of_array (tuplets, commonx, Y_AXIS);
Interval staff;
- if (Grob *st = Staff_symbol_referencer::get_staff_symbol (me))
+ Grob *st = Staff_symbol_referencer::get_staff_symbol (me);
+
+ /* staff-padding doesn't work correctly on cross-staff tuplets
+ because it only considers one staff symbol. Until this works,
+ disable it. */
+ if (st && !to_boolean (me->get_property ("cross-staff")))
{
Real pad = robust_scm2double (me->get_property ("staff-padding"), -1.0);
if (pad >= 0.0)
{
- staff = st->extent (commony, Y_AXIS);
+ staff = st->extent (commony, Y_AXIS) - my_offset;
staff.widen (pad);
}
}
bool equally_long = false;
Grob *par_beam = parallel_beam (me, columns, &equally_long);
-
-
Item *lgr = get_x_bound_item (me, LEFT, dir);
Item *rgr = get_x_bound_item (me, RIGHT, dir);
Real x0 = robust_relative_extent (lgr, commonx, X_AXIS)[LEFT];
Real x1 = robust_relative_extent (rgr, commonx, X_AXIS)[RIGHT];
+ bool follow_beam = par_beam
+ && get_grob_direction (par_beam) == dir
+ && ! to_boolean (par_beam->get_property ("knee"));
vector<Offset> points;
-
if (columns.size ()
- && par_beam
- && get_grob_direction (par_beam) == dir
+ && follow_beam
&& Note_column::get_stem (columns[0])
&& Note_column::get_stem (columns.back ()))
{
*/
(void) par_beam->get_property ("quantized-positions");
-
Drul_array<Grob *> stems (Note_column::get_stem (columns[0]),
Note_column::get_stem (columns.back ()));
-
-
-
Real ss = 0.5 * Staff_symbol_referencer::staff_space (me);
- Real lp = ss * robust_scm2double (stems[LEFT]->get_property ("stem-end-position"), 0.0);
- Real rp = ss * robust_scm2double (stems[RIGHT]->get_property ("stem-end-position"), 0.0);
+ Real lp = ss * robust_scm2double (stems[LEFT]->get_property ("stem-end-position"), 0.0)
+ + stems[LEFT]->get_parent (Y_AXIS)->relative_coordinate (commony, Y_AXIS);
+ Real rp = ss * robust_scm2double (stems[RIGHT]->get_property ("stem-end-position"), 0.0)
+ + stems[RIGHT]->get_parent (Y_AXIS)->relative_coordinate (commony, Y_AXIS);
*dy = rp - lp;
points.push_back (Offset (stems[LEFT]->relative_coordinate (commonx, X_AXIS) - x0, lp));
get_bounds (me, &left_col, &right_col);
if (left_col && right_col)
{
- Interval rv = right_col->extent (commony, Y_AXIS);
- Interval lv = left_col->extent (commony, Y_AXIS);
+ Interval rv = Note_column::cross_staff_extent (right_col, commony);
+ Interval lv = Note_column::cross_staff_extent (left_col, commony);
rv.unite (staff);
lv.unite (staff);
+
Real graphical_dy = rv[dir] - lv[dir];
Slice ls = Note_column::head_positions_interval (left_col);
else
*dy = 0;
- *offset = -dir * infinity_f;
for (vsize i = 0; i < columns.size (); i++)
{
- Interval note_ext = columns[i]->extent (commony, Y_AXIS);
- Real notey = note_ext[dir] - me->relative_coordinate (commony, Y_AXIS);
-
+ Interval note_ext = Note_column::cross_staff_extent (columns[i], commony);
Real x = columns[i]->relative_coordinate (commonx, X_AXIS) - x0;
- points.push_back (Offset (x, notey));
+
+ points.push_back (Offset (x, note_ext[dir]));
}
}
- if (!(par_beam && get_grob_direction (par_beam) == dir))
+ if (!follow_beam)
{
points.push_back (Offset (x0 - x0, staff[dir]));
points.push_back (Offset (x1 - x0, staff[dir]));
while (flip (&d) != LEFT);
}
+ *offset = -dir * infinity_f;
Real factor = (columns.size () > 1) ? 1 / (x1 - x0) : 1.0;
for (vsize i = 0; i < points.size (); i++)
{
Real x = points[i][X_AXIS];
- Real tuplety = (*dy) * x * factor;
+ Real tuplety = (*dy) * x * factor + my_offset;
if (points[i][Y_AXIS] * dir > (*offset + tuplety) * dir)
*offset = points[i][Y_AXIS] - tuplety;
Kind of pointless since we put them outside the staff anyway, but
let's leave code for the future when possibly allow them to move
into the staff once again.
+
+ This doesn't seem to support cross-staff tuplets atm.
*/
if (*dy == 0
&& fabs (*offset) < ss * Staff_symbol_referencer::staff_radius (me))
{
Spanner *me = unsmob_spanner (smob);
- /*
- Don't print if it doesn't span time.
- */
- if (robust_scm2moment (me->get_bound (LEFT)->get_column ()->get_property ("when"), Moment (0))
- == robust_scm2moment (me->get_bound (RIGHT)->get_column ()->get_property ("when"), Moment (0)))
- {
- me->suicide ();
- return SCM_EOL;
- }
-
Real dy = 0.0;
Real offset = 0.0;
calc_position_and_height (me, &offset, &dy);
Pointer_group_interface::add_grob (me, ly_symbol2scm ("tuplets"), bracket);
}
-ADD_INTERFACE (Tuplet_bracket,
- "A bracket with a number in the middle, used for tuplets. "
- "When the bracket spans a line break, the value of "
- "@code{break-overshoot} determines how far it extends "
- "beyond the staff. "
- "At a line break, the markups in the @code{edge-text} are printed "
- "at the edges. ",
+MAKE_SCHEME_CALLBACK (Tuplet_bracket, calc_cross_staff, 1);
+SCM
+Tuplet_bracket::calc_cross_staff (SCM smob)
+{
+ Grob *me = unsmob_grob (smob);
+ Grob *staff_symbol = 0;
+ extract_grob_set (me, "note-columns", cols);
+ bool equally_long = false;
+ Grob *par_beam = parallel_beam (me, cols, &equally_long);
+
+ if (par_beam)
+ return par_beam->get_property ("cross-staff");
+ for (vsize i = 0; i < cols.size (); i++)
+ {
+ Grob *stem = unsmob_grob (cols[i]->get_object ("stem"));
+ if (!stem)
+ continue;
+
+ if (to_boolean (stem->get_property ("cross-staff")))
+ return SCM_BOOL_T;
+
+ Grob *stem_staff = Staff_symbol_referencer::get_staff_symbol (stem);
+ if (staff_symbol && (stem_staff != staff_symbol))
+ return SCM_BOOL_T;
+ staff_symbol = stem_staff;
+ }
+ return SCM_BOOL_F;
+}
+
+ADD_INTERFACE (Tuplet_bracket,
+ "A bracket with a number in the middle, used for tuplets."
+ " When the bracket spans a line break, the value of"
+ " @code{break-overshoot} determines how far it extends"
+ " beyond the staff. At a line break, the markups in the"
+ " @code{edge-text} are printed at the edges.",
/* properties */
"bracket-flare "
"direction "
"edge-height "
"edge-text "
+ "full-length-padding "
+ "full-length-to-extent "
"gap "
"positions "
"note-columns "
"shorten-pair "
"staff-padding "
"thickness "
- "tuplets ");
+ "tuplets "
+ );