todo: handle breaking elegantly.
*/
-#include <math.h>
#include "tuplet-bracket.hh"
#include "line-interface.hh"
|| me->get_bound (RIGHT)->break_status_dir ())
return 0;
- Grob *s1 = Note_column::get_stem (cols[0]);
- Grob *s2 = Note_column::get_stem (cols.top ());
+ Drul_array<Grob*> stems (Note_column::get_stem (cols[0]),
+ Note_column::get_stem (cols.top ()));
- if (s2 != me->get_bound (RIGHT))
+ if (dynamic_cast<Item*> (stems[RIGHT])->get_column ()
+ != me->get_bound (RIGHT)->get_column())
return 0;
- Grob *b1 = s1 ? Stem::get_beam (s1) : 0;
- Grob *b2 = s2 ? Stem::get_beam (s2) : 0;
-
+ Drul_array<Grob*> beams;
+ Direction d = LEFT;
+ do {
+ beams[d] = stems[d] ? Stem::get_beam (stems[d]) : 0;
+ } while (flip (&d) != LEFT);
+
*equally_long = false;
- if (! (b1 && (b1 == b2) && !me->is_broken ()))
+ if (! (beams[LEFT] && (beams[LEFT] == beams[RIGHT]) && !me->is_broken ()))
return 0;
- extract_grob_set (b1, "stems", beam_stems);
+ extract_grob_set (beams[LEFT], "stems", beam_stems);
if (beam_stems.size () == 0)
{
programming_error ("beam under tuplet bracket has no stems");
return 0;
}
- *equally_long = (beam_stems[0] == s1 && beam_stems.top () == s2);
- return b1;
+ *equally_long = (beam_stems[0] == stems[LEFT] && beam_stems.top () == stems[RIGHT]);
+ return beams[LEFT];
}
/*
Stencil mol;
extract_grob_set (me, "note-columns", columns);
- {
- SCM lp = me->get_property ("left-position");
- SCM rp = me->get_property ("right-position");
-
- if (!scm_is_number (rp) || !scm_is_number (lp))
- {
- /*
- UGH. dependency tracking!
- */
- extract_grob_set (me, "tuplets", tuplets);
- for (int i = 0; i < tuplets.size (); i++)
- Tuplet_bracket::print (tuplets[i]->self_scm ());
-
- after_line_breaking (smob);
- }
- }
-
- Real ly = robust_scm2double (me->get_property ("left-position"), 0);
- Real ry = robust_scm2double (me->get_property ("right-position"), 0);
-
+ Drul_array<Real> positions = ly_scm2realdrul (me->get_property ("positions"));
+ Real dy = positions[RIGHT] - positions[LEFT];
bool equally_long = false;
Grob *par_beam = parallel_beam (me, columns, &equally_long);
-
Spanner *sp = dynamic_cast<Spanner *> (me);
bool bracket_visibility = !(par_beam && equally_long);
x_span[d] = robust_relative_extent (bounds[d], commonx, X_AXIS)[d];
Direction break_dir = bounds[d]->break_status_dir ();
Spanner *orig_spanner = dynamic_cast<Spanner *> (me->original_);
+
+ int neighbor_idx = me->get_break_index () - break_dir;
+
+ if (break_dir
+ && d == RIGHT
+ && neighbor_idx < orig_spanner->broken_intos_.size ())
+ {
+ Grob *neighbor = orig_spanner->broken_intos_[neighbor_idx];
+
+ /* trigger possible suicide*/
+ (void) neighbor->get_property ("positions");
+ }
+
connect_to_other[d]
= (break_dir
- && (me->get_break_index () - break_dir < orig_spanner->broken_intos_.size ()));
+ && (neighbor_idx < orig_spanner->broken_intos_.size ()
+ && neighbor_idx >= 0)
+ && orig_spanner->broken_intos_[neighbor_idx]->is_live ());
+
if (connect_to_other[d])
{
/*
TODO: make padding tunable?
*/
- x_span[d] = robust_relative_extent (bounds[d], commonx, X_AXIS) [LEFT] - 1.0;
+ Real 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;
}
}
while (flip (&d) != LEFT);
num.translate_axis (w / 2, X_AXIS);
num.align_to (Y_AXIS, CENTER);
- num.translate_axis ((ry - ly) / 2, Y_AXIS);
+ num.translate_axis (dy / 2, Y_AXIS);
mol.add_stencil (num);
}
SCM text = index_get_cell (edge_text, d);
if (Text_interface::is_markup (text))
{
- SCM t = Text_interface::interpret_markup (pap->self_scm (), properties, text);
+ SCM t = Text_interface::interpret_markup (pap->self_scm (),
+ properties, text);
Stencil *edge_text = unsmob_stencil (t);
edge_text->translate_axis (x_span[d] - x_span[LEFT], X_AXIS);
while (flip (&d) != LEFT);
Stencil brack = make_bracket (me, Y_AXIS,
- Offset (w, ry - ly),
+ Offset (w, dy),
height,
/*
0.1 = more space at right due to italics
mol.add_stencil (brack);
}
- mol.translate_axis (ly, Y_AXIS);
+ mol.translate_axis (positions[LEFT], Y_AXIS);
mol.translate_axis (x_span[LEFT]
- sp->get_bound (LEFT)->relative_coordinate (commonx, X_AXIS), X_AXIS);
return mol.smobbed_copy ();
Interval staff;
if (Grob *st = Staff_symbol_referencer::get_staff_symbol (me))
- staff = st->extent (commony, Y_AXIS);
-
+ {
+ staff = st->extent (commony, Y_AXIS);
+ Real pad = robust_scm2double (me->get_property ("staff-padding"), 0.5);
+ staff.widen (pad);
+ }
+
Direction dir = get_grob_direction (me);
/*
Real x0 = robust_relative_extent (lgr, commonx, X_AXIS)[LEFT];
Real x1 = robust_relative_extent (rgr, commonx, X_AXIS)[RIGHT];
- /*
- offset
- */
- Real factor = columns.size () > 1 ? 1 / (x1 - x0) : 1.0;
-
Array<Offset> points;
- points.push (Offset (x0, staff[dir]));
- points.push (Offset (x1, staff[dir]));
+ points.push (Offset (x0 - x0, staff[dir]));
+ points.push (Offset (x1 - x0, staff[dir]));
for (int i = 0; i < columns.size (); i++)
{
Interval tuplet_y (tuplets[i]->extent (commony, Y_AXIS));
Direction d = LEFT;
- Real lp = scm_to_double (tuplets[i]->get_property ("left-position"));
- Real rp = scm_to_double (tuplets[i]->get_property ("right-position"));
- Real other_dy = rp - lp;
+ Drul_array<Real> positions = ly_scm2realdrul (tuplets[i]->get_property ("positions"));
+
+
+ Real other_dy = positions[RIGHT] - positions[LEFT];
do
{
while (flip (&d) != LEFT);
}
+ Real factor = (columns.size () > 1) ? 1 / (x1 - x0) : 1.0;
for (int i = 0; i < points.size (); i++)
{
Real x = points[i][X_AXIS];
- Real tuplety = *dy * x * factor;
+ Real tuplety = (*dy) * x * factor;
if (points[i][Y_AXIS] * dir > (*offset + tuplety) * dir)
- *offset = points[i][Y_AXIS] - tuplety * sign (*dy) * dir;
+ *offset = points[i][Y_AXIS] - tuplety;
}
*offset += scm_to_double (me->get_property ("padding")) * dir;
}
}
-/*
- We depend on the beams if there are any.
-*/
-MAKE_SCHEME_CALLBACK (Tuplet_bracket, before_line_breaking, 1);
+
+MAKE_SCHEME_CALLBACK (Tuplet_bracket, calc_direction, 1);
SCM
-Tuplet_bracket::before_line_breaking (SCM smob)
+Tuplet_bracket::calc_direction (SCM smob)
{
Grob *me = unsmob_grob (smob);
- extract_grob_set (me, "note-columns", columns);
-
- for (int i = columns.size (); i--;)
- {
- Grob *s = Note_column::get_stem (columns[i]);
- Grob *b = s ? Stem::get_beam (s) : 0;
- if (b)
- me->add_dependency (b);
- }
- return SCM_UNSPECIFIED;
+ Direction dir = Tuplet_bracket::get_default_dir (me);
+ return scm_from_int (dir);
}
-MAKE_SCHEME_CALLBACK (Tuplet_bracket, after_line_breaking, 1);
-
+MAKE_SCHEME_CALLBACK (Tuplet_bracket, calc_positions, 1);
SCM
-Tuplet_bracket::after_line_breaking (SCM smob)
+Tuplet_bracket::calc_positions (SCM smob)
{
Grob *me = unsmob_grob (smob);
extract_grob_set (me, "note-columns", columns);
- Direction dir = get_grob_direction (me);
- if (!dir)
+ if (columns.is_empty())
{
- dir = Tuplet_bracket::get_default_dir (me);
- set_grob_direction (me, dir);
+ me->suicide ();
+ return scm_cons (scm_from_double (0),
+ scm_from_double (0));
}
-
+
+ Direction dir = get_grob_direction (me);
bool equally_long = false;
Grob *par_beam = parallel_beam (me, columns, &equally_long);
dy = rp - lp;
}
- SCM lp = me->get_property ("left-position");
- SCM rp = me->get_property ("right-position");
-
- if (scm_is_number (lp) && !scm_is_number (rp))
- rp = scm_from_double (scm_to_double (lp) + dy);
- else if (scm_is_number (rp) && !scm_is_number (lp))
- lp = scm_from_double (scm_to_double (rp) - dy);
- else if (!scm_is_number (rp) && !scm_is_number (lp))
- {
- lp = scm_from_double (offset);
- rp = scm_from_double (offset + dy);
- }
-
- me->set_property ("left-position", lp);
- me->set_property ("right-position", rp);
-
- return SCM_UNSPECIFIED;
+
+ SCM x = scm_cons (scm_from_double (offset),
+ scm_from_double (offset + dy));
+
+ return x;
}
/*
Tuplet_bracket::add_column (Grob *me, Item *n)
{
Pointer_group_interface::add_grob (me, ly_symbol2scm ("note-columns"), n);
- me->add_dependency (n);
-
add_bound_item (dynamic_cast<Spanner *> (me), n);
}
Tuplet_bracket::add_tuplet_bracket (Grob *me, Grob *bracket)
{
Pointer_group_interface::add_grob (me, ly_symbol2scm ("tuplets"), bracket);
- me->add_dependency (bracket);
}
ADD_INTERFACE (Tuplet_bracket,
"At a line break, the markups in the @code{edge-text} are printed "
"at the edges. ",
- "note-columns bracket-flare edge-height shorten-pair "
- "tuplets edge-text break-overshoot "
- "padding left-position right-position bracket-visibility "
- "number-visibility thickness direction");
+
+ /* properties */
+ "bracket-flare "
+ "bracket-visibility "
+ "break-overshoot "
+ "direction "
+ "edge-height "
+ "edge-text "
+ "positions "
+ "note-columns "
+ "number-visibility "
+ "padding "
+ "shorten-pair "
+ "staff-padding "
+ "thickness "
+ "tuplets ");