/*
- 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--2007 Jan Nieuwenhuizen <janneke@gnu.org>
+ Copyright (C) 1997--2010 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 "line-interface.hh"
#include "beam.hh"
return g;
}
-
void
-flatten_number_pair_property (Grob *me,
- Direction xdir, SCM sym)
+flatten_number_pair_property (Grob *me, Direction xdir, SCM sym)
{
Drul_array<Real> zero (0, 0);
Drul_array<Real> pair
= robust_scm2drul (me->internal_get_property (sym), zero);
pair[xdir] = 0.0;
-
+
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,
+Tuplet_bracket::parallel_beam (Grob *me_grob, vector<Grob *> const &cols,
bool *equally_long)
{
Spanner *me = dynamic_cast<Spanner *> (me_grob);
|| me->get_bound (RIGHT)->break_status_dir ())
return 0;
- Drul_array<Grob*> stems (Note_column::get_stem (cols[0]),
- Note_column::get_stem (cols.back ()));
+ Drul_array<Grob *> stems (Note_column::get_stem (cols[0]),
+ Note_column::get_stem (cols.back ()));
if (!stems[RIGHT]
|| !stems[LEFT]
- || (dynamic_cast<Item*> (stems[RIGHT])->get_column ()
+ || (dynamic_cast<Item *> (stems[RIGHT])->get_column ()
!= me->get_bound (RIGHT)->get_column ()))
return 0;
- Drul_array<Grob*> beams;
+ 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 ()))
return 0;
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);
+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));
-
+
Drul_array<bool> connect_to_other (false, false);
Direction d = LEFT;
do
{
Direction break_dir = bounds[d]->break_status_dir ();
- Spanner *orig_spanner = dynamic_cast<Spanner*> (me->original ());
+ Spanner *orig_spanner = dynamic_cast<Spanner *> (me->original ());
vsize neighbor_idx = me->get_break_index () - break_dir;
if (break_dir
&& d == RIGHT
}
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]));
-
+
return SCM_EOL;
}
-Grob*
+Grob *
Tuplet_bracket::get_common_x (Spanner *me)
{
extract_grob_set (me, "note-columns", columns);
- Grob * commonx = common_refpoint_of_array (columns, me, X_AXIS);
+ Grob *commonx = common_refpoint_of_array (columns, me, X_AXIS);
commonx = commonx->common_refpoint (me->get_bound (LEFT), X_AXIS);
commonx = commonx->common_refpoint (me->get_bound (RIGHT), X_AXIS);
return commonx;
}
-
-MAKE_SCHEME_CALLBACK (Tuplet_bracket, calc_control_points,1)
+
+MAKE_SCHEME_CALLBACK (Tuplet_bracket, calc_control_points, 1)
SCM
Tuplet_bracket::calc_control_points (SCM smob)
{
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));
+ = 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
if (d == RIGHT)
x_span[d] += d * overshoot[d];
else
- x_span[d] = robust_relative_extent (bounds[d], commonx, X_AXIS)[RIGHT]
+ x_span[d] = robust_relative_extent (bounds[d],
+ commonx, X_AXIS)[RIGHT]
- overshoot[LEFT];
}
-
+
else if (d == RIGHT
&& (columns.empty ()
|| (bounds[d]->get_column ()
/*
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);
-
-
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])));
extract_grob_set (me, "note-columns", columns);
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 */
- SCM cpoints = me->get_property ("control-points");
+
+ /*
+ 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;
- }
-
+ 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 (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"));
-
+
/*
- 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)
if (!ext.is_empty ())
{
gap = ext.length () + 1.0;
-
- if (0.75 * x_span.length () < gap)
+
+ if ((0.75 * x_span.length () < gap) && !bracket_prop)
bracket_visibility = false;
}
}
Drul_array<Stencil> edge_stencils;
Direction dir = get_grob_direction (me);
-
+
scale_drul (&height, -ss * dir);
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
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);
+ edge_text->translate_axis (x_span[d] - x_span[LEFT],
+ X_AXIS);
edge_stencils[d] = *edge_text;
}
}
*/
Stencil
Tuplet_bracket::make_bracket (Grob *me, // for line properties.
- Axis protusion_axis,
+ Axis protrusion_axis,
Offset dz,
Drul_array<Real> height,
Interval gap,
Real length = dz.length ();
Drul_array<Offset> gap_corners;
- Axis bracket_axis = other_axis (protusion_axis);
+ Axis bracket_axis = other_axis (protrusion_axis);
Drul_array<Offset> straight_corners = corners;
do
{
flare_corners[d][bracket_axis] = straight_corners[d][bracket_axis];
- flare_corners[d][protusion_axis] += height[d];
+ flare_corners[d][protrusion_axis] += height[d];
straight_corners[d][bracket_axis] += -d * flare[d];
}
while (flip (&d) != LEFT);
if (gap.is_empty ())
m.add_stencil (Line_interface::line (me, straight_corners[LEFT],
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)
+ if (pad >= 0.0)
{
staff = st->extent (commony, Y_AXIS) - my_offset;
staff.widen (pad);
}
}
-
+
Direction dir = get_grob_direction (me);
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"));
+ && !to_boolean (par_beam->get_property ("knee"));
vector<Offset> points;
if (columns.size ()
{
/*
trigger set_stem_ends
- */
+ */
(void) par_beam->get_property ("quantized-positions");
Drul_array<Grob *> stems (Note_column::get_stem (columns[0]),
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);
+ + 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);
+ + 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));
for (vsize i = 0; i < columns.size (); i++)
{
- Interval note_ext = Note_column::cross_staff_extent (columns[i], commony);
+ 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 (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.
if (!tuplets[i]->is_live ())
continue;
-
+
Direction d = LEFT;
- Drul_array<Real> positions = robust_scm2interval (tuplets[i]->get_property ("positions"),
- Interval (0,0));
+ Drul_array<Real> positions
+ = robust_scm2interval (tuplets[i]->get_property ("positions"),
+ Interval (0,0));
-
Real other_dy = positions[RIGHT] - positions[LEFT];
do
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
}
}
-
MAKE_SCHEME_CALLBACK (Tuplet_bracket, calc_direction, 1);
SCM
Tuplet_bracket::calc_direction (SCM smob)
Real dy = 0.0;
Real offset = 0.0;
calc_position_and_height (me, &offset, &dy);
-
+
SCM x = scm_cons (scm_from_double (offset),
scm_from_double (offset + dy));
-
+
return x;
}
Tuplet_bracket::calc_cross_staff (SCM smob)
{
Grob *me = unsmob_grob (smob);
- Grob *staff_symbol = 0;
extract_grob_set (me, "note-columns", cols);
+ extract_grob_set (me, "tuplets", tuplets);
+
+ Grob *commony = common_refpoint_of_array (cols, me, Y_AXIS);
+ 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);
+ if (me->check_cross_staff (commony))
+ return SCM_BOOL_T;
+
bool equally_long = false;
Grob *par_beam = parallel_beam (me, cols, &equally_long);
- if (par_beam)
- return par_beam->get_property ("cross-staff");
+ if (par_beam && to_boolean (par_beam->get_property ("cross-staff")))
+ return SCM_BOOL_T;
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")))
+ if (stem && 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;
}
"direction "
"edge-height "
"edge-text "
+ "full-length-padding "
+ "full-length-to-extent "
"gap "
"positions "
"note-columns "
"thickness "
"tuplets "
);
-
-