* lily/tuplet-number.cc (print): new file, new interface.
* scm/define-grob-properties.scm (all-user-grob-properties):
remove number-visibility property.
* lily/tuplet-bracket.cc (calc_control_points): new function
(calc_connect_to_neighbors): new function.
(print): remove text handling for tuplet numberdef.
* lily/tuplet-engraver.cc (struct Tuplet_description): create
TupletNumbers too.
* lily/lily-guile.cc (robust_scm2booldrul): new function
* scm/define-grobs.scm (all-grob-descriptions): new grob TupletNumber
* lily/tuplet-bracket.cc (calc_position_and_height): use
staff-padding to control whether tuplet brackets are over staves.
2005-12-19 Han-Wen Nienhuys <hanwen@xs4all.nl>
+ * flower/include/offset.hh (class Offset): new operator /=
+
+ * lily/tuplet-number.cc (print): new file, new interface.
+
+ * scm/define-grob-properties.scm (all-user-grob-properties):
+ remove number-visibility property.
+
+ * lily/tuplet-bracket.cc (calc_control_points): new function
+ (calc_connect_to_neighbors): new function.
+ (print): remove text handling for tuplet numberdef.
+
+ * lily/tuplet-engraver.cc (struct Tuplet_description): create
+ TupletNumbers too.
+
+ * lily/lily-guile.cc (robust_scm2booldrul): new function
+
+ * scm/define-grobs.scm (all-grob-descriptions): new grob TupletNumber
+
+ * lily/tuplet-bracket.cc (calc_position_and_height): use
+ staff-padding to control whether tuplet brackets are over staves.
+
* lily/grob.cc (suicide): clear dim_caches_.
* lily/dimension-cache.cc (clear): new function.
@seealso
-Program reference: @internalsref{TupletBracket}, and @internalsref{TimeScaledMusic}.
+Program reference: @internalsref{TupletBracket},
+@internalsref{TupletNumber}, and @internalsref{TimeScaledMusic}.
Examples: @inputfileref{input/@/regression,tuplet@/-nest@/.ly}.
return *this;
}
+ Offset &operator /= (Real a)
+ {
+ (*this) *= 1/a;
+ return *this;
+ }
+
Offset &operator *= (Real a)
{
(*this)[X_AXIS] *= a;
return o2;
}
+inline Offset
+operator / (Offset o1, Real a)
+{
+ o1 /= a;
+ return o1;
+}
+
inline Offset
operator * (Offset o1, Real o2)
{
int robust_scm2int (SCM, int);
Direction robust_scm2dir (SCM, Direction);
Drul_array<Real> robust_scm2drul (SCM, Drul_array<Real>);
+Drul_array<bool> robust_scm2booldrul (SCM, Drul_array<bool>);
Interval robust_scm2interval (SCM, Drul_array<Real>);
Offset robust_scm2offset (SCM, Offset);
public:
DECLARE_SCHEME_CALLBACK (calc_direction, (SCM));
DECLARE_SCHEME_CALLBACK (calc_positions, (SCM));
+ DECLARE_SCHEME_CALLBACK (calc_control_points, (SCM));
DECLARE_SCHEME_CALLBACK (print, (SCM));
-
+ DECLARE_SCHEME_CALLBACK (calc_connect_to_neighbors, (SCM smob));
+
static bool has_interface (Grob *);
+ static Grob* get_common_x (Spanner *);
static void add_tuplet_bracket (Grob *me, Grob *smaller_bracket);
static void get_bounds (Grob *, Grob **, Grob **);
static void add_column (Grob *me, Item *);
return v;
}
+Drul_array<bool>
+robust_scm2booldrul (SCM k, Drul_array<bool> def)
+{
+ if (scm_is_pair (k))
+ {
+ def[LEFT] = to_boolean (scm_car (k));
+ def[RIGHT] = to_boolean (scm_cdr (k));
+ }
+ return def;
+}
+
Offset
robust_scm2offset (SCM k, Offset o)
{
#include "line-interface.hh"
#include "beam.hh"
#include "warn.hh"
-#include "font-interface.hh"
#include "output-def.hh"
+#include "font-interface.hh"
#include "text-interface.hh"
#include "stem.hh"
#include "note-column.hh"
return g;
}
+
+void
+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->internal_set_property (sym, ly_interval2scm (pair));
+}
+
+
Grob *
Tuplet_bracket::parallel_beam (Grob *me_grob, Link_array<Grob> const &cols, bool *equally_long)
{
return beams[LEFT];
}
-/*
- TODO:
- in the case that there is no bracket, but there is a (single) beam,
- follow beam precisely for determining tuplet number location.
-*/
-MAKE_SCHEME_CALLBACK (Tuplet_bracket, print, 1);
+MAKE_SCHEME_CALLBACK(Tuplet_bracket,calc_connect_to_neighbors,1);
SCM
-Tuplet_bracket::print (SCM smob)
+Tuplet_bracket::calc_connect_to_neighbors (SCM smob)
{
Spanner *me = unsmob_spanner (smob);
- Stencil mol;
- extract_grob_set (me, "note-columns", columns);
-
- 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);
- bool number_visibility = true;
-
- /*
- 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"))
- bracket_visibility = !par_beam;
-
- SCM numb = me->get_property ("number-visibility");
- if (scm_is_bool (numb))
- number_visibility = ly_scm2bool (numb);
- else if (numb == ly_symbol2scm ("if-no-beam"))
- number_visibility = !par_beam;
-
- Grob *commonx = common_refpoint_of_array (columns, me, X_AXIS);
- commonx = commonx->common_refpoint (sp->get_bound (LEFT), X_AXIS);
- commonx = commonx->common_refpoint (sp->get_bound (RIGHT), X_AXIS);
-
- Direction dir = get_grob_direction (me);
-
- Drul_array<Item *> bounds;
- bounds[LEFT] = get_x_bound_item (me, LEFT, dir);
- bounds[RIGHT] = get_x_bound_item (me, RIGHT, dir);
- Drul_array<bool> connect_to_other;
- Interval x_span;
+ 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
{
- 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 ());
+
+ 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 ())
&& (neighbor_idx < orig_spanner->broken_intos_.size ()
&& neighbor_idx >= 0)
&& 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]));
+
+ return SCM_EOL;
+}
+
+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);
+ 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)
+SCM
+Tuplet_bracket::calc_control_points (SCM smob)
+{
+ Spanner *me = unsmob_spanner (smob);
+
+ extract_grob_set (me, "note-columns", columns);
+
+ Drul_array<Real> positions
+ = ly_scm2realdrul (me->get_property ("positions"));
+
+ Grob *commonx = get_common_x (me);
+ Direction dir = get_grob_direction (me);
+
+ Drul_array<Item *> bounds;
+ 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-other"),
+ Drul_array<bool> (false, false));
+
+
+ Interval x_span;
+ Direction d = LEFT;
+ do
+ {
+ x_span[d] = robust_relative_extent (bounds[d], commonx, X_AXIS)[d];
if (connect_to_other[d])
{
}
while (flip (&d) != LEFT);
- Real w = x_span.length ();
- SCM number = me->get_property ("text");
+
+
+ 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])));
+}
- Output_def *pap = me->layout ();
- Stencil num;
- if (scm_is_string (number) && number_visibility)
- {
- SCM properties = Font_interface::text_font_alist_chain (me);
- SCM snum = Text_interface::interpret_markup (pap->self_scm (),
- properties, number);
- num = *unsmob_stencil (snum);
- num.align_to (X_AXIS, CENTER);
- num.translate_axis (w / 2, X_AXIS);
- num.align_to (Y_AXIS, CENTER);
+/*
+ TODO:
- num.translate_axis (dy / 2, Y_AXIS);
+ in the case that there is no bracket, but there is a (single) beam,
+ follow beam precisely for determining tuplet number location.
+*/
+MAKE_SCHEME_CALLBACK (Tuplet_bracket, print, 1);
+SCM
+Tuplet_bracket::print (SCM smob)
+{
+ Spanner *me = unsmob_spanner (smob);
+ Stencil mol;
- mol.add_stencil (num);
- }
+ 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);
+ /*
+ 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"))
+ bracket_visibility = !par_beam;
+
+
+ SCM cpoints = me->get_property ("control-points");
+ 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.
*/
Real gap = 0.;
- if (bracket_visibility && number_visibility)
+ if (bracket_visibility && number_grob)
{
- if (!num.extent (X_AXIS).is_empty ())
- gap = num.extent (X_AXIS).length () + 1.0;
+ Interval ext = number_grob->extent (number_grob, X_AXIS);
+ if (!ext.is_empty ())
+ {
+ gap = ext.length () + 1.0;
- if (w - gap < w / 4.0)
- bracket_visibility = false;
+ if (0.75 * x_span.length () < gap)
+ bracket_visibility = false;
+ }
}
if (bracket_visibility)
= robust_scm2drul (me->get_property ("shorten-pair"), zero);
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-other"),
+ Drul_array<bool> (false, false));
+
+ Direction d = LEFT;
do
{
if (connect_to_other[d])
while (flip (&d) != LEFT);
Stencil brack = make_bracket (me, Y_AXIS,
- Offset (w, dy),
+ points[RIGHT] - points[LEFT],
height,
/*
0.1 = more space at right due to italics
mol.add_stencil (brack);
}
- mol.translate_axis (positions[LEFT], Y_AXIS);
- mol.translate_axis (x_span[LEFT]
- - sp->get_bound (LEFT)->relative_coordinate (commonx, X_AXIS), X_AXIS);
+ mol.translate (points[LEFT]);
return mol.smobbed_copy ();
}
if (Grob *st = Staff_symbol_referencer::get_staff_symbol (me))
commony = st->common_refpoint (commony, Y_AXIS);
- Grob *commonx = common_refpoint_of_array (columns, me, X_AXIS);
+ Grob *commonx = get_common_x (me);
commonx = common_refpoint_of_array (tuplets, commonx, Y_AXIS);
- commonx = commonx->common_refpoint (me->get_bound (LEFT), X_AXIS);
- commonx = commonx->common_refpoint (me->get_bound (RIGHT), X_AXIS);
Interval staff;
if (Grob *st = Staff_symbol_referencer::get_staff_symbol (me))
{
- staff = st->extent (commony, Y_AXIS);
- Real pad = robust_scm2double (me->get_property ("staff-padding"), 0.5);
- staff.widen (pad);
+ Real pad = robust_scm2double (me->get_property ("staff-padding"), -1.0);
+ if (pad >= 0.0)
+ {
+ staff = st->extent (commony, Y_AXIS);
+ staff.widen (pad);
+ }
}
Direction dir = get_grob_direction (me);
"bracket-flare "
"bracket-visibility "
"break-overshoot "
+ "connect-to-neighbor "
+ "control-points "
"direction "
"edge-height "
"edge-text "
+ "gap "
"positions "
"note-columns "
- "number-visibility "
"padding "
+ "tuplet-number "
"shorten-pair "
"staff-padding "
"thickness "
"tuplets ");
+
Rational stop_;
Rational span_stop_;
Rational length_;
- Spanner *spanner_;
+ Spanner *bracket_;
+ Spanner *number_;
Tuplet_description ()
{
music_ = 0;
- spanner_ = 0;
+ bracket_ = 0;
+ number_ = 0;
}
static int compare (Tuplet_description const &a, Tuplet_description const &b)
{
tuplets_.sort (&Tuplet_description::compare);
for (int i = 0; i < tuplets_.size (); i++)
{
- if (tuplets_[i].spanner_)
+ if (tuplets_[i].bracket_)
continue;
- Spanner *spanner = make_spanner ("TupletBracket",
- tuplets_[i].music_->self_scm ());
- tuplets_[i].spanner_ = spanner;
+ tuplets_[i].bracket_ = make_spanner ("TupletBracket",
+ tuplets_[i].music_->self_scm ());
+ tuplets_[i].number_ = make_spanner ("TupletNumber",
+ tuplets_[i].music_->self_scm ());
+ tuplets_[i].number_->set_object ("bracket", tuplets_[i].bracket_->self_scm ());
+ tuplets_[i].bracket_->set_object ("tuplet-number", tuplets_[i].number_->self_scm ());
+
+ if (i > 0 && tuplets_[i - 1].bracket_)
+ Tuplet_bracket::add_tuplet_bracket (tuplets_[i].bracket_, tuplets_[i - 1].bracket_);
- if (i > 0 && tuplets_[i - 1].spanner_)
- Tuplet_bracket::add_tuplet_bracket (tuplets_[i].spanner_, tuplets_[i - 1].spanner_);
- if (i < tuplets_.size () - 1 && tuplets_[i + 1].spanner_)
- Tuplet_bracket::add_tuplet_bracket (tuplets_[i + 1].spanner_, tuplets_[i].spanner_);
+ if (i < tuplets_.size () - 1 && tuplets_[i + 1].bracket_)
+ Tuplet_bracket::add_tuplet_bracket (tuplets_[i + 1].bracket_, tuplets_[i].bracket_);
SCM proc = get_property ("tupletNumberFormatFunction");
if (ly_is_procedure (proc))
{
SCM t = scm_apply_0 (proc, scm_list_1 (tuplets_[i].music_->self_scm ()));
- spanner->set_property ("text", t);
+ tuplets_[i].number_->set_property ("text", t);
}
}
}
void
-Tuplet_engraver::acknowledge_note_column (Grob_info i)
+Tuplet_engraver::acknowledge_note_column (Grob_info inf)
{
for (int j = 0; j < tuplets_.size (); j++)
- if (tuplets_[j].spanner_)
- Tuplet_bracket::add_column (tuplets_[j].spanner_,
- dynamic_cast<Item *> (i.grob ()));
+ if (tuplets_[j].bracket_)
+ {
+ Item *i = dynamic_cast<Item *> (inf.grob ());
+ Tuplet_bracket::add_column (tuplets_[j].bracket_, i);
+ add_bound_item (tuplets_[j].number_, i);
+ }
}
void
if (now.main_part_ >= tuplets_[i].span_stop_)
{
- if (tuplets_[i].spanner_)
+ if (tuplets_[i].bracket_)
{
if (full_length)
{
Item *col = unsmob_item (get_property ("currentMusicalColumn"));
- tuplets_[i].spanner_->set_bound (RIGHT, col);
+ tuplets_[i].bracket_->set_bound (RIGHT, col);
+ tuplets_[i].number_->set_bound (RIGHT, col);
}
- else if (!tuplets_[i].spanner_->get_bound (RIGHT))
- tuplets_[i].spanner_->set_bound (RIGHT,
- tuplets_[i].spanner_->get_bound (LEFT));
-
- last_tuplets_.push (tuplets_[i].spanner_);
- tuplets_[i].spanner_ = 0;
+ else if (!tuplets_[i].bracket_->get_bound (RIGHT))
+ {
+ tuplets_[i].bracket_->set_bound (RIGHT,
+ tuplets_[i].bracket_->get_bound (LEFT));
+ tuplets_[i].number_->set_bound (RIGHT,
+ tuplets_[i].bracket_->get_bound (LEFT));
+ }
+ last_tuplets_.push (tuplets_[i].bracket_);
+ last_tuplets_.push (tuplets_[i].number_);
+
+ tuplets_[i].bracket_ = 0;
+ tuplets_[i].number_ = 0;
}
if (tsd)
ADD_ACKNOWLEDGER (Tuplet_engraver, note_column);
ADD_TRANSLATOR (Tuplet_engraver,
/* doc */ "Catch Time_scaled_music and generate appropriate bracket ",
- /* create */ "TupletBracket",
+ /* create */ "TupletBracket TupletNumber",
/* accept */ "time-scaled-music",
/* read */ "tupletNumberFormatFunction tupletSpannerDuration tupletFullLength",
/* write */ "");
--- /dev/null
+/*
+ tuplet-number.cc -- implement Tuplet_number
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 2005 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+*/
+
+#include "tuplet-bracket.hh"
+#include "text-interface.hh"
+#include "spanner.hh"
+#include "lookup.hh"
+
+struct Tuplet_number
+{
+ DECLARE_SCHEME_CALLBACK(print, (SCM));
+ static bool has_interface (Grob *);
+};
+
+
+MAKE_SCHEME_CALLBACK(Tuplet_number, print, 1);
+SCM
+Tuplet_number::print (SCM smob)
+{
+ Stencil *stc = unsmob_stencil (Text_interface::print (smob));
+
+ stc->align_to (X_AXIS, CENTER);
+ stc->align_to (Y_AXIS, CENTER);
+
+ Spanner *me = unsmob_spanner (smob);
+ Spanner *tuplet = unsmob_spanner (me->get_object ("bracket"));
+ SCM cpoints = tuplet->get_property ("control-points");
+ Drul_array<Offset> points;
+ points[LEFT] = ly_scm2offset (scm_car (cpoints));
+ points[RIGHT] = ly_scm2offset (scm_cadr (cpoints));
+
+ stc->translate ((points[RIGHT] + points[LEFT]) / 2);
+
+ return stc->smobbed_copy ();
+}
+
+
+ADD_INTERFACE (Tuplet_number,
+ "tuplet-number-interface",
+ "The number for a bracket. "
+ ,
+
+ /* properties */
+ "bracket ");
+
(arpeggio-direction ,ly:dir? "If set, put an
arrow on the arpeggio squiggly line.")
+
+ (arrow ,boolean? "Add an arrow to the line.")
+ (arrow-length ,number? "Arrow length.")
+ (arrow-width ,number? "Arrow width.")
+
(auto-knee-gap ,ly:dimension? "If a gap is found between note heads
where a horizontal beam fits that is larger than this number, make a kneed beam.")
(average-spacing-wishes ,boolean? "If set, the spacing wishes are averaged over staves.")
(color ,color? "The color of this grob.")
- ;;DOCME
- (control-points ,list? "List of 4 offsets (number-pairs) that form control points for the tie/slur shape.")
+ (control-points ,list? "List of offsets (number-pairs) that form
+control points for the tie/slur/bracket shape. For beziers, this
+should list the control points of a 3rd order bezier curve." )
+ (connect-to-neighbor ,pair? "Pair of booleans, indicating whether this
+grob looks as a continued break.")
(damping ,number? "Amount of beam slope damping. 0: no, 1: yes,
100000: horizontal beams.")
(dash-period ,number? "the length of one dash + white space. If
(dash-fraction ,number? "Size of the dashes, relative to
dash-period. Should be between 0.0 (no line) and 1.0 (continuous
line).")
-
- (arrow ,boolean? "Add an arrow to the line.")
- (arrow-length ,number? "Arrow length.")
- (arrow-width ,number? "Arrow width.")
-
(direction ,ly:dir? "Up or down, left or right?")
(dot-color ,symbol? "Color of dots. Options include
get stems extending to the middle staff line.")
(number-type ,symbol? "Type of numbers to use in label. Choices
include @code{roman-lower}, @code{roman-upper}, and @code{arabic}.")
- (number-visibility ,boolean-or-symbol? "Like
-@code{bracket-visibility}, but for the number.")
-
-
-
(packed-spacing ,boolean? "If set, the notes are spaced as
tightly as possible.")
(padding ,ly:dimension? "Add this much extra space between
function is to protect objects from being garbage collected.")
(arpeggio ,ly:grob? "pointer to arpeggio object.")
(beam ,ly:grob? "pointer to the beam, if applicable.")
+ (bracket ,ly:grob? "the bracket for a number.")
(direction-source ,ly:grob? "in case side-relative-direction is
set, which grob to get the direction from .")
(dot ,ly:grob? "reference to Dots object.")
(spacing-wishes ,ly:grob-array? "List of note spacing or staff spacing objects.")
(stems ,ly:grob-array? "list of stem objects, corresponding to the notes that the arpeggio has to be before.")
(tuplets ,ly:grob-array? "list of smaller tuplet brackets")
+ (tuplet-number ,ly:grob? "the number for a bracket.")
(left-neighbors ,ly:grob-array? " List of
spacing-wish grobs that are close to the current column.
(thickness . 1.6)
(edge-height . (0.7 . 0.7))
(shorten-pair . (-0.2 . -0.2))
+ (staff-padding . 0.25)
+
(direction . ,Tuplet_bracket::calc_direction)
(positions . ,Tuplet_bracket::calc_positions)
+ (connect-to-neighbor . ,Tuplet_bracket::calc_connect_to_neighbors)
+ (control-points . ,Tuplet_bracket::calc_control_points)
(stencil . ,Tuplet_bracket::print)
+
+ (meta . ((class . Spanner)
+ (interfaces . (line-interface
+ tuplet-bracket-interface))))))
+
+ (TupletNumber
+ . (
+ (stencil . ,Tuplet_number::print)
(font-shape . italic)
(font-size . -2)
(meta . ((class . Spanner)
- (interfaces . (text-interface
- line-interface
- tuplet-bracket-interface
+ (interfaces . (text-interface tuplet-number-interface
font-interface))))))
-
+
(UnaCordaPedal
. (
(stencil . ,Text_interface::print)