Currently uses the `padding' property to space out nested tuplets.
This is the same property used to space tuplets from other objects
they encompass.
--- /dev/null
+
+\version "2.15.9"
+
+\header {
+ texidoc = "Broken nested tuplets avoid each other correctly.
+"
+}
+
+\paper {
+ ragged-right = ##t
+ indent = 0.0
+}
+
+\score {
+ \new Staff
+ <<
+ \relative c'' {
+ \override Score . Beam #'breakable = ##t
+
+ r2
+
+ \times 4/3 {
+ \times 2/3 { c8[ c c] }
+ \times 2/3 { c8[ c c] }
+ \times 2/3 { c8[ c c] }
+ }
+
+ \times 4/3 {
+ \times 2/3 { a8[ a a] }
+ \times 2/3 { a8[ a a] }
+ \times 2/3 { a8[ a a] }
+ }
+
+ \override TupletNumber #'text = #tuplet-number::calc-fraction-text
+ \times 4/6 {
+ \times 2/3 {
+ a4 a a
+ }
+ \times 3/5 {
+ a4 a a a a
+ }
+ a4
+ }
+ r2
+ }
+ { \repeat unfold 3 { s1 \break } }
+ >>
+ \layout {
+ \context {
+ \Voice \remove Forbid_line_break_engraver
+ }
+ }
+}
}
\relative c'' {
+ \times 4/3 {
+ \times 2/3 { c8[ c c] }
+ \times 2/3 { c8[ c c] }
+ \times 2/3 { c8[ c c] }
+ }
+
+ \times 4/3 {
+ \times 2/3 { a8[ a a] }
+ \times 2/3 { a8[ a a] }
+ \times 2/3 { a8[ a a] }
+ }
+
\override TupletNumber #'text = #tuplet-number::calc-fraction-text
\times 4/6 {
\times 2/3 {
- a a a
+ a4 a a
}
\times 3/5 {
- a a a a a
+ a4 a a a a
}
}
public:
DECLARE_SCHEME_CALLBACK (calc_direction, (SCM));
DECLARE_SCHEME_CALLBACK (calc_positions, (SCM));
- DECLARE_SCHEME_CALLBACK (calc_control_points, (SCM));
+ DECLARE_SCHEME_CALLBACK (calc_x_positions, (SCM));
DECLARE_SCHEME_CALLBACK (print, (SCM));
DECLARE_SCHEME_CALLBACK (calc_connect_to_neighbors, (SCM smob));
DECLARE_SCHEME_CALLBACK (calc_cross_staff, (SCM));
#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 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);
}
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));
}
/*
/*
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;
== 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 ();
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]));
}
*offset = -dir * infinity_f;
"bracket-visibility "
"break-overshoot "
"connect-to-neighbor "
- "control-points "
"direction "
"edge-height "
"edge-text "
"staff-padding "
"thickness "
"tuplets "
+ "X-positions "
);
struct Tuplet_number
{
DECLARE_SCHEME_CALLBACK (print, (SCM));
+ DECLARE_SCHEME_CALLBACK (calc_x_offset, (SCM));
+ DECLARE_SCHEME_CALLBACK (calc_y_offset, (SCM));
DECLARE_SCHEME_CALLBACK (calc_cross_staff, (SCM));
DECLARE_GROB_INTERFACE ();
+
+ static Real calc_offset (Spanner *me, Axis a);
};
MAKE_SCHEME_CALLBACK (Tuplet_number, print, 1);
stc->align_to (X_AXIS, CENTER);
stc->align_to (Y_AXIS, CENTER);
- SCM cpoints = tuplet->get_property ("control-points");
- Drul_array<Offset> points;
- if (scm_is_pair (cpoints))
- {
- points[LEFT] = ly_scm2offset (scm_car (cpoints));
- points[RIGHT] = ly_scm2offset (scm_cadr (cpoints));
- }
- else
- {
- programming_error ("wrong type for control-points");
- }
- stc->translate ((points[RIGHT] + points[LEFT]) / 2);
+ return stc->smobbed_copy ();
+}
+
+MAKE_SCHEME_CALLBACK (Tuplet_number, calc_x_offset, 1);
+SCM
+Tuplet_number::calc_x_offset (SCM smob)
+{
+ Spanner *me = unsmob_spanner (smob);
+ Spanner *tuplet = unsmob_spanner (me->get_object ("bracket"));
+
+ Interval x_positions = robust_scm2interval (tuplet->get_property ("X-positions"), Interval (0.0, 0.0));
+
+ return scm_from_double (x_positions.center ());
+}
+
+MAKE_SCHEME_CALLBACK (Tuplet_number, calc_y_offset, 1);
+SCM
+Tuplet_number::calc_y_offset (SCM smob)
+{
+
+ Spanner *me = unsmob_spanner (smob);
+ Spanner *tuplet = unsmob_spanner (me->get_object ("bracket"));
+
+ Interval positions = robust_scm2interval (tuplet->get_property ("positions"), Interval (0.0, 0.0));
- return stc_scm;
+ return scm_from_double (positions.center ());
}
MAKE_SCHEME_CALLBACK (Tuplet_number, calc_cross_staff, 1)
(X-extent ,number-pair? "Hard coded extent in X@tie{}direction.")
(X-offset ,number? "The horizontal amount that this object is
moved relative to its X-parent.")
+ (X-positions ,number-pair? "Pair of X staff coordinates of a spanner
+in the form @code{(@var{left} . @var{right})}, where both @var{left} and
+@var{right} are in @code{staff-space} units of the current staff.")
;;
;; a tuplet bracket.
(connect-to-neighbor . ,ly:tuplet-bracket::calc-connect-to-neighbors)
- (control-points . ,ly:tuplet-bracket::calc-control-points)
(direction . ,UP)
(edge-height . (0.7 . 0.7))
(padding . 2.0)
(staff-padding . 0.25)
(stencil . ,ly:tuplet-bracket::print)
(thickness . 1.6)
+ (X-positions . ,ly:tuplet-bracket::calc-x-positions)
(meta . ((class . Spanner)
(interfaces . (line-interface
tuplet-bracket-interface))))))
(TupletBracket
. (
(connect-to-neighbor . ,ly:tuplet-bracket::calc-connect-to-neighbors)
- (control-points . ,ly:tuplet-bracket::calc-control-points)
(cross-staff . ,ly:tuplet-bracket::calc-cross-staff)
(direction . ,ly:tuplet-bracket::calc-direction)
(edge-height . (0.7 . 0.7))
(staff-padding . 0.25)
(stencil . ,ly:tuplet-bracket::print)
(thickness . 1.6)
+ (X-positions . ,ly:tuplet-bracket::calc-x-positions)
(meta . ((class . Spanner)
(interfaces . (line-interface
(font-size . -2)
(stencil . ,ly:tuplet-number::print)
(text . ,tuplet-number::calc-denominator-text)
+ (X-offset . ,ly:tuplet-number::calc-x-offset)
+ (Y-offset . ,ly:tuplet-number::calc-y-offset)
(meta . ((class . Spanner)
(interfaces . (font-interface
text-interface