/*
- tuplet-bracket.cc -- implement Tuplet_bracket
+ This file is part of LilyPond, the GNU music typesetter.
- source file of the GNU LilyPond music typesetter
-
- (c) 1997--2009 Jan Nieuwenhuizen <janneke@gnu.org>
+ Copyright (C) 1997--2012 Jan Nieuwenhuizen <janneke@gnu.org>
Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+ LilyPond is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ LilyPond is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
*/
/*
todo: handle breaking elegantly.
*/
-
#include "tuplet-bracket.hh"
+#include "axis-group-interface.hh"
#include "line-interface.hh"
#include "beam.hh"
#include "warn.hh"
#include "note-column.hh"
#include "pointer-group-interface.hh"
#include "directional-element-interface.hh"
+#include "skyline.hh"
#include "spanner.hh"
#include "staff-symbol-referencer.hh"
#include "lookup.hh"
return g;
}
-
void
flatten_number_pair_property (Grob *me, Direction xdir, SCM sym)
{
me->set_property (sym, ly_interval2scm (pair));
}
-
/*
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)
+Tuplet_bracket::parallel_beam (Grob *me_grob, vector<Grob *> const &cols,
+ bool *equally_long)
{
Spanner *me = dynamic_cast<Spanner *> (me_grob);
return 0;
Drul_array<Grob *> stems (Note_column::get_stem (cols[0]),
- Note_column::get_stem (cols.back ()));
+ Note_column::get_stem (cols.back ()));
if (!stems[RIGHT]
|| !stems[LEFT]
- || (dynamic_cast<Item*> (stems[RIGHT])->get_column ()
- != me->get_bound (RIGHT)->get_column ()))
+ || (dynamic_cast<Item *> (stems[RIGHT])->get_column ()
+ != me->get_bound (RIGHT)->get_column ()))
return 0;
Drul_array<Grob *> beams;
Direction d = LEFT;
- do {
+ do
beams[d] = stems[d] ? Stem::get_beam (stems[d]) : 0;
- } while (flip (&d) != LEFT);
+ while (flip (&d) != LEFT);
*equally_long = false;
- if (!(beams[LEFT] && (beams[LEFT] == beams[RIGHT]) && !me->is_broken ()))
+ if (! (beams[LEFT] && (beams[LEFT] == beams[RIGHT]) && !me->is_broken ()))
return 0;
extract_grob_set (beams[LEFT], "stems", beam_stems);
return 0;
}
- *equally_long =
- (beam_stems[0] == stems[LEFT]
- && beam_stems.back () == stems[RIGHT]);
+ *equally_long
+ = (beam_stems[0] == stems[LEFT]
+ && beam_stems.back () == stems[RIGHT]);
return beams[LEFT];
}
-
MAKE_SCHEME_CALLBACK (Tuplet_bracket, calc_connect_to_neighbors, 1);
SCM
Tuplet_bracket::calc_connect_to_neighbors (SCM smob)
{
Spanner *me = unsmob_spanner (smob);
- Direction dir = get_grob_direction (me);
+ Direction dir = get_grob_direction (me);
Drul_array<Item *> bounds (get_x_bound_item (me, LEFT, dir),
- get_x_bound_item (me, RIGHT, dir));
-
+ get_x_bound_item (me, RIGHT, dir));
+
Drul_array<bool> connect_to_other (false, false);
Direction d = LEFT;
do
Spanner *orig_spanner = dynamic_cast<Spanner *> (me->original ());
vsize 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];
+ && 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");
- }
+ /* trigger possible suicide*/
+ (void) neighbor->get_property ("positions");
+ }
connect_to_other[d]
- = (break_dir
- && neighbor_idx < orig_spanner->broken_intos_.size ()
- && orig_spanner->broken_intos_[neighbor_idx]->is_live ());
+ = (break_dir
+ && neighbor_idx < orig_spanner->broken_intos_.size ()
+ && orig_spanner->broken_intos_[neighbor_idx]->is_live ());
}
while (flip (&d) != LEFT);
-
if (connect_to_other[LEFT] || connect_to_other[RIGHT])
return scm_cons (scm_from_bool (connect_to_other[LEFT]),
- scm_from_bool (connect_to_other[RIGHT]));
-
+ scm_from_bool (connect_to_other[RIGHT]));
+
return SCM_EOL;
}
-Grob *
+Grob *
Tuplet_bracket::get_common_x (Spanner *me)
{
extract_grob_set (me, "note-columns", columns);
return commonx;
}
-MAKE_SCHEME_CALLBACK (Tuplet_bracket, calc_control_points, 1)
+MAKE_SCHEME_CALLBACK (Tuplet_bracket, calc_x_positions, 1)
SCM
-Tuplet_bracket::calc_control_points (SCM smob)
+Tuplet_bracket::calc_x_positions (SCM smob)
{
Spanner *me = unsmob_spanner (smob);
-
extract_grob_set (me, "note-columns", columns);
- SCM scm_positions = me->get_property ("positions");
- if (!me->is_live ())
- return SCM_EOL;
-
- if (!scm_is_pair (scm_positions))
- programming_error ("Positions should be number pair");
-
- Drul_array<Real> positions
- = robust_scm2drul (scm_positions, Drul_array<Real> (0, 0));
-
Grob *commonx = get_common_x (me);
Direction dir = get_grob_direction (me);
bounds[LEFT] = get_x_bound_item (me, LEFT, dir);
bounds[RIGHT] = get_x_bound_item (me, RIGHT, dir);
- Drul_array<bool> connect_to_other =
- robust_scm2booldrul (me->get_property ("connect-to-neighbor"),
- Drul_array<bool> (false, false));
+ Drul_array<bool> connect_to_other
+ = robust_scm2booldrul (me->get_property ("connect-to-neighbor"),
+ Drul_array<bool> (false, false));
Interval x_span;
Direction d = LEFT;
do
{
- x_span[d] = robust_relative_extent (bounds[d], commonx, X_AXIS)[d];
-
+ x_span[d] = bounds[d]->break_status_dir ()
+ ? Axis_group_interface::generic_bound_extent (bounds[d], commonx, X_AXIS)[d]
+ : robust_relative_extent (bounds[d], commonx, X_AXIS)[d];
if (connect_to_other[d])
- {
- Interval overshoot (robust_scm2drul (me->get_property ("break-overshoot"),
- Interval (-0.5, 0.0)));
-
- if (d == RIGHT)
- x_span[d] += d * overshoot[d];
- else
- x_span[d] = robust_relative_extent (bounds[d],
- commonx, X_AXIS)[RIGHT]
- - overshoot[LEFT];
- }
+ {
+ Interval overshoot (robust_scm2drul (me->get_property ("break-overshoot"),
+ Interval (-0.5, 0.0)));
+
+ if (d == RIGHT)
+ x_span[d] += d * overshoot[d];
+ else
+ x_span[d] = (bounds[d]->break_status_dir ()
+ ? Axis_group_interface::generic_bound_extent (bounds[d], commonx, X_AXIS)[-d]
+ : robust_relative_extent (bounds[d], commonx, X_AXIS)[-d])
+ - overshoot[LEFT];
+ }
else if (d == RIGHT
- && (columns.empty ()
- || (bounds[d]->get_column ()
- != dynamic_cast<Item *> (columns.back ())->get_column ())))
- {
- /*
- We're connecting to a column, for the last bit of a broken
- fullLength bracket.
- */
- Real padding =
- robust_scm2double(me->get_property("full-length-padding"), 1.0);
-
- if (bounds[d]->break_status_dir ())
- padding = 0.0;
-
- 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;
- }
+ && (columns.empty ()
+ || (bounds[d]->get_column ()
+ != dynamic_cast<Item *> (columns.back ())->get_column ())))
+ {
+ /*
+ We're connecting to a column, for the last bit of a broken
+ fullLength bracket.
+ */
+ Real padding
+ = robust_scm2double (me->get_property ("full-length-padding"), 1.0);
+
+ if (bounds[d]->break_status_dir ())
+ padding = 0.0;
+
+ 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);
-
- x_span -= me->get_bound (LEFT)->relative_coordinate (commonx, X_AXIS);
- return scm_list_2 (ly_offset2scm (Offset (x_span[LEFT], positions[LEFT])),
- ly_offset2scm (Offset (x_span[RIGHT], positions[RIGHT])));
+ return ly_interval2scm (x_span - me->get_bound (LEFT)->relative_coordinate (commonx, X_AXIS));
}
/*
bool equally_long = false;
Grob *par_beam = parallel_beam (me, columns, &equally_long);
- bool bracket_visibility = !(par_beam && equally_long);
+ bool bracket_visibility = !(par_beam && equally_long); // Flag, print/don't print tuplet bracket.
/*
- Fixme: the type of this prop is sucky.
+ FIXME: The type of this prop is sucky.
*/
- SCM bracket = me->get_property ("bracket-visibility");
- if (scm_is_bool (bracket))
- bracket_visibility = ly_scm2bool (bracket);
- else if (bracket == ly_symbol2scm ("if-no-beam"))
+ SCM bracket_vis_prop = me->get_property ("bracket-visibility");
+ bool bracket_prop = ly_scm2bool (bracket_vis_prop); // Flag, user has set bracket-visibility prop.
+ bool bracket = (bracket_vis_prop == ly_symbol2scm ("if-no-beam"));
+ if (scm_is_bool (bracket_vis_prop))
+ bracket_visibility = bracket_prop;
+ else if (bracket)
bracket_visibility = !par_beam;
-
+
/*
Don't print a tuplet bracket and number if
- no control-points were calculated
+ no X or Y positions were calculated.
*/
- SCM cpoints = me->get_property ("control-points");
- if (scm_ilength (cpoints) < 2)
+ SCM scm_x_span = me->get_property ("X-positions");
+ SCM scm_positions = me->get_property ("positions");
+ if (!scm_is_pair (scm_x_span) || !scm_is_pair (scm_positions))
{
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;
- }
+ the bracket, but still let the number be displayed.
+ Only do this if the user has not explicitly specified bracket-visibility = #t.
+ */
+ if (!to_boolean (bracket_vis_prop)
+ && (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));
- points[RIGHT] = ly_scm2offset (scm_cadr (cpoints));
+ Interval x_span = robust_scm2interval (scm_x_span, Interval (0.0, 0.0));
+ Interval positions = robust_scm2interval (scm_positions, Interval (0.0, 0.0));
- Interval x_span (points[LEFT][X_AXIS], points[RIGHT][X_AXIS]);
- Drul_array<Real> positions (points[LEFT][Y_AXIS], points[RIGHT][Y_AXIS]);
+ Drul_array<Offset> points;
+ Direction d = LEFT;
+ do
+ points[d] = Offset (x_span[d], positions[d]);
+ while (flip (&d) != LEFT);
Output_def *pap = me->layout ();
Grob *number_grob = unsmob_grob (me->get_object ("tuplet-number"));
/*
- No bracket when it would be smaller than the number.
+ Don't print the bracket when it would be smaller than the number.
+ ...Unless the user has coded bracket-visibility = #t, that is.
*/
Real gap = 0.;
if (bracket_visibility && number_grob)
{
Interval ext = number_grob->extent (number_grob, X_AXIS);
if (!ext.is_empty ())
- {
- gap = ext.length () + 1.0;
+ {
+ gap = ext.length () + 1.0;
- if (0.75 * x_span.length () < gap)
- bracket_visibility = false;
- }
+ if ((0.75 * x_span.length () < gap) && !bracket_prop)
+ bracket_visibility = false;
+ }
}
if (bracket_visibility)
Drul_array<Real> zero (0, 0);
Real ss = Staff_symbol_referencer::staff_space (me);
Drul_array<Real> height
- = robust_scm2drul (me->get_property ("edge-height"), zero);
+ = robust_scm2drul (me->get_property ("edge-height"), zero);
Drul_array<Real> flare
- = robust_scm2drul (me->get_property ("bracket-flare"), zero);
+ = robust_scm2drul (me->get_property ("bracket-flare"), zero);
Drul_array<Real> shorten
- = robust_scm2drul (me->get_property ("shorten-pair"), zero);
+ = robust_scm2drul (me->get_property ("shorten-pair"), zero);
Drul_array<Stencil> edge_stencils;
Direction dir = get_grob_direction (me);
scale_drul (&flare, ss);
scale_drul (&shorten, ss);
- Drul_array<bool> connect_to_other =
- robust_scm2booldrul (me->get_property ("connect-to-neighbor"),
- Drul_array<bool> (false, false));
+ Drul_array<bool> connect_to_other
+ = robust_scm2booldrul (me->get_property ("connect-to-neighbor"),
+ Drul_array<bool> (false, false));
Direction d = LEFT;
do
- {
- if (connect_to_other[d])
- {
- height[d] = 0.0;
- flare[d] = 0.0;
- shorten[d] = 0.0;
-
- SCM edge_text = me->get_property ("edge-text");
-
- if (scm_is_pair (edge_text))
- {
- SCM properties = Font_interface::text_font_alist_chain (me);
- 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);
-
- Stencil *edge_text = unsmob_stencil (t);
- edge_text->translate_axis (x_span[d] - x_span[LEFT],
- X_AXIS);
- edge_stencils[d] = *edge_text;
- }
- }
- }
- }
+ {
+ if (connect_to_other[d])
+ {
+ height[d] = 0.0;
+ flare[d] = 0.0;
+ shorten[d] = 0.0;
+
+ SCM edge_text = me->get_property ("edge-text");
+
+ if (scm_is_pair (edge_text))
+ {
+ SCM properties = Font_interface::text_font_alist_chain (me);
+ 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);
+
+ Stencil *edge_text = unsmob_stencil (t);
+ edge_text->translate_axis (x_span[d] - x_span[LEFT],
+ X_AXIS);
+ edge_stencils[d] = *edge_text;
+ }
+ }
+ }
+ }
while (flip (&d) != LEFT);
Stencil brack = make_bracket (me, Y_AXIS,
- points[RIGHT] - points[LEFT],
- height,
- /*
- 0.1 = more space at right due to italics
- TODO: use italic correction of font.
- */
- Interval (-0.5, 0.5) * gap + 0.1,
- flare, shorten);
+ points[RIGHT] - points[LEFT],
+ height,
+ /*
+ 0.1 = more space at right due to italics
+ TODO: use italic correction of font.
+ */
+ Interval (-0.5, 0.5) * gap + 0.1,
+ flare, shorten);
do
- {
- if (!edge_stencils[d].is_empty ())
- brack.add_stencil (edge_stencils[d]);
- }
+ {
+ if (!edge_stencils[d].is_empty ())
+ brack.add_stencil (edge_stencils[d]);
+ }
while (flip (&d) != LEFT);
mol.add_stencil (brack);
*/
Stencil
Tuplet_bracket::make_bracket (Grob *me, // for line properties.
- Axis protrusion_axis,
- Offset dz,
- Drul_array<Real> height,
- Interval gap,
- Drul_array<Real> flare,
- Drul_array<Real> shorten)
+ Axis protrusion_axis,
+ Offset dz,
+ Drul_array<Real> height,
+ Interval gap,
+ Drul_array<Real> flare,
+ Drul_array<Real> shorten)
{
Drul_array<Offset> corners (Offset (0, 0), dz);
if (!gap.is_empty ())
{
do
- gap_corners[d] = (dz * 0.5) + gap[d] / length * dz;
+ gap_corners[d] = (dz * 0.5) + gap[d] / length * dz;
while (flip (&d) != LEFT);
}
do
{
if (!gap.is_empty ())
- m.add_stencil (Line_interface::line (me, straight_corners[d],
- gap_corners[d]));
+ m.add_stencil (Line_interface::line (me, straight_corners[d],
+ gap_corners[d]));
m.add_stencil (Line_interface::line (me, straight_corners[d],
- flare_corners[d]));
+ flare_corners[d]));
}
while (flip (&d) != LEFT);
if (gap.is_empty ())
m.add_stencil (Line_interface::line (me, straight_corners[LEFT],
- straight_corners[RIGHT]));
+ straight_corners[RIGHT]));
return m;
}
l++;
vsize r = columns.size ();
- while (r > l && Note_column::has_rests (columns[r-1]))
+ while (r > l && Note_column::has_rests (columns[r - 1]))
r--;
*left = *right = 0;
if (l < r)
{
*left = columns[l];
- *right = columns[r-1];
+ *right = columns[r - 1];
}
}
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) - my_offset;
- staff.widen (pad);
- }
+ if (pad >= 0.0)
+ {
+ staff = st->extent (commony, Y_AXIS) - my_offset;
+ 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];
bool follow_beam = par_beam
- && get_grob_direction (par_beam) == dir
- && ! to_boolean (par_beam->get_property ("knee"));
+ && get_grob_direction (par_beam) == dir
+ && !to_boolean (par_beam->get_property ("knee"));
vector<Offset> points;
if (columns.size ()
&& Note_column::get_stem (columns[0])
&& Note_column::get_stem (columns.back ()))
{
- /*
- trigger set_stem_ends
- */
- (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)
- + 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);
+ Note_column::get_stem (columns.back ()));
- *dy = rp - lp;
- points.push_back (Offset (stems[LEFT]->relative_coordinate (commonx, X_AXIS) - x0, lp));
- points.push_back (Offset (stems[RIGHT]->relative_coordinate (commonx, X_AXIS) - x0, rp));
+ Interval poss;
+ Direction side = LEFT;
+ do
+ {
+ // Trigger setting of stem lengths if necessary.
+ if (Grob *beam = Stem::get_beam (stems[side]))
+ (void) beam->get_property ("quantized-positions");
+ poss[side] = stems[side]->extent (stems[side], Y_AXIS)[get_grob_direction (stems[side])]
+ + stems[side]->get_parent (Y_AXIS)->relative_coordinate (commony, Y_AXIS);
+ }
+ while (flip (&side) != LEFT);
+
+ *dy = poss[RIGHT] - poss[LEFT];
+ points.push_back (Offset (stems[LEFT]->relative_coordinate (commonx, X_AXIS) - x0, poss[LEFT]));
+ points.push_back (Offset (stems[RIGHT]->relative_coordinate (commonx, X_AXIS) - x0, poss[RIGHT]));
}
else
{
/*
- Use outer non-rest columns to determine slope
+ Use outer non-rest columns to determine slope
*/
Grob *left_col = 0;
Grob *right_col = 0;
get_bounds (me, &left_col, &right_col);
if (left_col && right_col)
- {
- 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);
- Slice rs = Note_column::head_positions_interval (right_col);
-
- Interval musical_dy;
- musical_dy[UP] = rs[UP] - ls[UP];
- musical_dy[DOWN] = rs[DOWN] - ls[DOWN];
- if (sign (musical_dy[UP]) != sign (musical_dy[DOWN]))
- *dy = 0.0;
- else if (sign (graphical_dy) != sign (musical_dy[DOWN]))
- *dy = 0.0;
- else
- *dy = graphical_dy;
- }
+ {
+ 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);
+ Slice rs = Note_column::head_positions_interval (right_col);
+
+ Interval musical_dy;
+ musical_dy[UP] = rs[UP] - ls[UP];
+ musical_dy[DOWN] = rs[DOWN] - ls[DOWN];
+ if (sign (musical_dy[UP]) != sign (musical_dy[DOWN]))
+ *dy = 0.0;
+ else if (sign (graphical_dy) != sign (musical_dy[DOWN]))
+ *dy = 0.0;
+ else
+ *dy = graphical_dy;
+ }
else
- *dy = 0;
+ *dy = 0;
for (vsize i = 0; i < columns.size (); i++)
- {
- Interval note_ext = Note_column::cross_staff_extent (columns[i],
- commony);
- Real x = columns[i]->relative_coordinate (commonx, X_AXIS) - x0;
+ {
+ 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, note_ext[dir]));
- }
+ points.push_back (Offset (x, note_ext[dir]));
+ }
}
if (!follow_beam)
points.push_back (Offset (x0 - x0, staff[dir]));
points.push_back (Offset (x1 - x0, staff[dir]));
}
-
+
/*
This is a slight hack. We compute two encompass points from the
bbox of the smaller tuplets.
Interval tuplet_y (tuplets[i]->extent (commony, Y_AXIS));
if (!tuplets[i]->is_live ())
- continue;
+ continue;
Direction d = LEFT;
Drul_array<Real> positions
- = robust_scm2interval (tuplets[i]->get_property ("positions"),
- Interval (0,0));
+ = robust_scm2interval (tuplets[i]->get_property ("positions"),
+ Interval (0, 0));
Real other_dy = positions[RIGHT] - positions[LEFT];
do
- {
- Real y
- = tuplet_y.linear_combination (d * sign (other_dy));
-
- /*
- We don't take padding into account for nested tuplets.
- the edges can come very close to the stems, likewise for
- nested tuplets?
- */
-
- points.push_back (Offset (tuplet_x[d] - x0, y));
- }
+ {
+ Real y
+ = tuplet_y.linear_combination (d * sign (other_dy));
+
+ /*
+ We don't take padding into account for nested tuplets.
+ the edges can come very close to the stems, likewise for
+ nested tuplets?
+ */
+
+ points.push_back (Offset (tuplet_x[d] - x0, y));
+ }
while (flip (&d) != LEFT);
+ // Check for number-on-bracket collisions
+ Grob *number = unsmob_grob (tuplets[i]->get_object ("tuplet-number"));
+ if (number)
+ points.push_back (Offset (number->extent (commonx, X_AXIS).center () - x0,
+ number->extent (commony, Y_AXIS)[dir]));
+ }
+
+ if (to_boolean (me->get_property ("avoid-scripts"))
+ && !scm_is_number (me->get_property ("outside-staff-priority")))
+ {
+ extract_grob_set (me, "scripts", scripts);
+ for (vsize i = 0; i < scripts.size (); i++)
+ {
+ if (!scripts[i]->is_live ())
+ continue;
+ if (scm_is_number (scripts[i]->get_property ("outside-staff-priority")))
+ continue;
+
+ Interval script_x (scripts[i]->extent (commonx, X_AXIS));
+ Interval script_y (scripts[i]->extent (commony, Y_AXIS));
+
+ points.push_back (Offset (script_x.center () - x0,
+ script_y[dir]));
+ }
}
*offset = -dir * infinity_f;
Real tuplety = (*dy) * x * factor + my_offset;
if (points[i][Y_AXIS] * dir > (*offset + tuplety) * dir)
- *offset = points[i][Y_AXIS] - tuplety;
+ *offset = points[i][Y_AXIS] - tuplety;
}
*offset += scm_to_double (me->get_property ("padding")) * dir;
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
*offset = rint (*offset);
if (Staff_symbol_referencer::on_line (me, (int) rint (*offset)))
- *offset += dir;
+ *offset += dir;
*offset *= 0.5 * ss;
}
calc_position_and_height (me, &offset, &dy);
SCM x = scm_cons (scm_from_double (offset),
- scm_from_double (offset + dy));
+ scm_from_double (offset + dy));
return x;
}
for (vsize i = 0; i < columns.size (); i++)
{
Grob *nc = columns[i];
+ if (Note_column::has_rests (nc))
+ continue;
Direction d = Note_column::dir (nc);
if (d)
- dirs[d]++;
+ dirs[d]++;
}
- return dirs[UP] >= dirs[DOWN] ? UP : DOWN;
+ if (dirs[UP] == dirs[DOWN])
+ {
+ if (dirs[UP] == 0)
+ return UP;
+ Grob *staff = Staff_symbol_referencer::get_staff_symbol (me);
+ if (!staff)
+ return UP;
+ Interval staff_extent = staff->extent (staff, Y_AXIS);
+ Interval extremal_positions;
+ extremal_positions.set_empty ();
+ for (vsize i = 0; i < columns.size (); i++)
+ {
+ Direction d = Note_column::dir (columns[i]);
+ extremal_positions[d] = minmax (d, 1.0 * Note_column::head_positions_interval (columns[i])[d], extremal_positions[d]);
+ }
+ Direction d = LEFT;
+ do
+ extremal_positions[d] = -d * (staff_extent[d] - extremal_positions[d]);
+ while (flip (&d) != LEFT);
+
+ return extremal_positions[UP] <= extremal_positions[DOWN] ? UP : DOWN;
+ }
+
+ return dirs[UP] > dirs[DOWN] ? UP : DOWN;
}
void
add_bound_item (dynamic_cast<Spanner *> (me), n);
}
+void
+Tuplet_bracket::add_script (Grob *me, Item *s)
+{
+ Pointer_group_interface::add_grob (me, ly_symbol2scm ("scripts"), s);
+}
+
void
Tuplet_bracket::add_tuplet_bracket (Grob *me, Grob *bracket)
{
{
Grob *stem = unsmob_grob (cols[i]->get_object ("stem"));
if (stem && to_boolean (stem->get_property ("cross-staff")))
- return SCM_BOOL_T;
+ return SCM_BOOL_T;
}
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 "
- "bracket-visibility "
- "break-overshoot "
- "connect-to-neighbor "
- "control-points "
- "direction "
- "edge-height "
- "edge-text "
- "full-length-padding "
- "full-length-to-extent "
- "gap "
- "positions "
- "note-columns "
- "padding "
- "tuplet-number "
- "shorten-pair "
- "staff-padding "
- "thickness "
- "tuplets "
- );
+ "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 */
+ "avoid-scripts "
+ "bracket-flare "
+ "bracket-visibility "
+ "break-overshoot "
+ "connect-to-neighbor "
+ "direction "
+ "edge-height "
+ "edge-text "
+ "full-length-padding "
+ "full-length-to-extent "
+ "gap "
+ "positions "
+ "note-columns "
+ "padding "
+ "tuplet-number "
+ "shorten-pair "
+ "staff-padding "
+ "thickness "
+ "tuplets "
+ "X-positions "
+ );