From 1b6937d111e6bddf65d00fd63a99f0d83cb41836 Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Fri, 5 Aug 2005 13:44:36 +0000 Subject: [PATCH] * lily/tuplet-bracket.cc (after_line_breaking): don't suicide if columns is empty * lily/tuplet-engraver.cc (finalize): new function. Reset right bounds to currentCommandColumn for the last step. (start_translation_timestep): if tupletFullLength is set, set bound to Paper Column * lily/spacing-loose-columns.cc (set_loose_columns): space a whole clique of loose columns, eg. a set of grace notes in strict notespacing. * input/regression/spacing-strict-spacing-grace.ly: new file. * lily/spacing-determine-loose-columns.cc: new file. * input/regression/spacing-strict-notespacing.ly: new file. * lily/spacing-spanner.cc (generate_springs): rename from do_measure. (generate_pair_spacing): new function. (init, generate_pair_spacing): set between-cols for floating nonmusical columns. * lily/tuplet-bracket.cc (print): on the left, the overshoot is relative to the right edge of the prefatory matter. --- ChangeLog | 16 +++ Documentation/topdocs/NEWS.tely | 22 +++- .../regression/spacing-strict-notespacing.ly | 11 +- .../spacing-strict-spacing-grace.ly | 21 ++++ lily/include/paper-column.hh | 8 +- lily/include/spacing-spanner.hh | 8 +- lily/spacing-basic.cc | 55 +++++++--- lily/spacing-determine-loose-columns.cc | 45 ++++---- lily/spacing-loose-columns.cc | 100 +++++++++++------ lily/spacing-spanner.cc | 16 +-- lily/tuplet-bracket.cc | 102 +++++++++--------- lily/tuplet-engraver.cc | 43 ++++++-- ly/engraver-init.ly | 2 +- scm/define-context-properties.scm | 2 + scm/define-grob-properties.scm | 4 +- 15 files changed, 304 insertions(+), 151 deletions(-) create mode 100644 input/regression/spacing-strict-spacing-grace.ly diff --git a/ChangeLog b/ChangeLog index b9b5f86a01..316d4e9cf7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,21 @@ 2005-08-05 Han-Wen Nienhuys + * lily/tuplet-bracket.cc (after_line_breaking): don't suicide if + columns is empty + + * lily/tuplet-engraver.cc (finalize): new function. Reset right + bounds to currentCommandColumn for the last step. + (start_translation_timestep): if tupletFullLength is set, set + bound to Paper Column + + * input/regression/tuplet-full-length.ly (indent): new file. + + * lily/spacing-loose-columns.cc (set_loose_columns): space a whole + clique of loose columns, eg. a set of grace notes in strict + notespacing. + + * input/regression/spacing-strict-spacing-grace.ly: new file. + * lily/key-signature-interface.cc: change property name to alteration-alist diff --git a/Documentation/topdocs/NEWS.tely b/Documentation/topdocs/NEWS.tely index 99622e13bf..64158ca328 100644 --- a/Documentation/topdocs/NEWS.tely +++ b/Documentation/topdocs/NEWS.tely @@ -33,16 +33,32 @@ See user manual, \NAME\ @itemize @bullet +@item +Tuplets can be made to reach the next non-tuplet note by setting the +@code{tupletFullLength} property, + +@lilypond[fragment] +\new Voice \with { + \remove Forbid_line_break_engraver + allowBeamBreak = ##t +} +{ + \set tupletFullLength = ##t + \times 2/3 { c8[ c c] } + c4 +} +@end lilypond + + @item When @code{strict-note-spacing} is set, note are spaced without regard -for clefs and bar lines. For example, +for clefs, bar lines and grace notes. For example, @lilypond[fragment,verbatim,relative=2] \override Score.SpacingSpanner #'strict-note-spacing = ##t -\new Staff { c8[ c \clef alto c c c c] c32 c32 } +\new Staff { c8[ c \clef alto c \grace { c16[ c] } c8 c c] c32[ c32] } @end lilypond - This feature was sponsored by Trevor Baca. @item diff --git a/input/regression/spacing-strict-notespacing.ly b/input/regression/spacing-strict-notespacing.ly index 797a3a2edd..d88f8abb2c 100644 --- a/input/regression/spacing-strict-notespacing.ly +++ b/input/regression/spacing-strict-notespacing.ly @@ -25,7 +25,14 @@ time. This may cause collisions. " << \override Score.SpacingSpanner #'strict-note-spacing = ##t \set Score.proportionalNotationDuration = #(ly:make-moment 1 16) - \new Staff { c8[ c \clef alto c c c c] c4 c2 r2 } - \new Staff { c2 \times 2/3 { c8 \clef bass cis,, c } c4 c1 } + \new Staff { + c8[ c \clef alto c c \grace { d16 } c8 c] c4 c2 + \grace { c16[ c16] } + c2 } + \new Staff { + c2 \times 2/3 { c8 \clef bass cis,, c } + c4 + c1 + } >> diff --git a/input/regression/spacing-strict-spacing-grace.ly b/input/regression/spacing-strict-spacing-grace.ly new file mode 100644 index 0000000000..4af57d8c01 --- /dev/null +++ b/input/regression/spacing-strict-spacing-grace.ly @@ -0,0 +1,21 @@ +\header { + + texidoc = "With @code{strict-note-spacing} spacing for grace notes +(even multiple ones), is floating as well." + +} + +\version "2.7.4" + +\paper { + raggedright = ##t + indent = 0 +} + +\relative c'' +{ + \override Score.SpacingSpanner #'strict-note-spacing = ##t + \set Score.proportionalNotationDuration = #(ly:make-moment 1 12) + c8[ \grace { c16[ c] } c8 c8 c8] + c2 +} diff --git a/lily/include/paper-column.hh b/lily/include/paper-column.hh index 70c1d17823..ff6d642fba 100644 --- a/lily/include/paper-column.hh +++ b/lily/include/paper-column.hh @@ -27,23 +27,21 @@ public: Paper_column (Paper_column const &, int count); virtual Grob *clone (int count) const; - - static bool has_interface (Grob *); virtual void do_break_processing (); virtual Paper_column *get_column () const; virtual System *get_system () const; - static int get_rank (Grob *); int get_rank () const { return rank_; } + void set_rank (int); DECLARE_SCHEME_CALLBACK (print, (SCM)); DECLARE_SCHEME_CALLBACK (before_line_breaking, (SCM)); + static bool has_interface (Grob *); + static int get_rank (Grob *); static bool is_musical (Grob *); static Moment when_mom (Grob *); - static bool is_used (Grob *); - void set_rank (int); }; #endif // PAPER_COLUMN_HH diff --git a/lily/include/spacing-spanner.hh b/lily/include/spacing-spanner.hh index 73fffccadd..7dbfdfc8b4 100644 --- a/lily/include/spacing-spanner.hh +++ b/lily/include/spacing-spanner.hh @@ -19,11 +19,13 @@ struct Spacing_options bool packed_; bool stretch_uniformly_; bool float_nonmusical_columns_; - Rational global_shortest_; Real increment_; + Real shortest_duration_space_; - void init (Grob *me); + void init (); + void init_from_grob (Grob *me); + Real get_duration_space (Moment d, bool*) const; }; /* @@ -41,7 +43,7 @@ public: Spacing_options const*); static Real default_bar_spacing (Grob *, Grob *, Grob *, Moment); static Real note_spacing (Grob *, Grob *, Grob *, Spacing_options const*, bool *); - static Real get_duration_space (Grob *, Moment dur, Rational shortest, bool *); + static Real get_duration_space (Moment dur, Spacing_options const*, bool *); static Rational find_shortest (Grob *, Link_array const &); static Rational effective_shortest_duration (Grob *me, Link_array const &all); static void breakable_column_spacing (Grob *, Item *l, Item *r, Spacing_options const*); diff --git a/lily/spacing-basic.cc b/lily/spacing-basic.cc index 7f4a4930b0..49453e8494 100644 --- a/lily/spacing-basic.cc +++ b/lily/spacing-basic.cc @@ -24,14 +24,12 @@ Get the measure wide ant for arithmetic spacing. */ Real -Spacing_spanner::get_duration_space (Grob *me, - Moment d, - Rational shortest, bool *expand_only) +Spacing_options::get_duration_space (Moment d, + bool *expand_only) const { - Real k = robust_scm2double (me->get_property ("shortest-duration-space"), 1); - Real incr = robust_scm2double (me->get_property ("spacing-increment"), 1); + Real k = shortest_duration_space_; - if (d < shortest) + if (d < global_shortest_) { /* We don't space really short notes using the log of the @@ -49,9 +47,9 @@ Spacing_spanner::get_duration_space (Grob *me, */ - Rational ratio = d.main_part_ / shortest; + Rational ratio = d.main_part_ / global_shortest_; - return ((k - 1) + double (ratio)) * incr; + return ((k - 1) + double (ratio)) * increment_; } else { @@ -60,12 +58,12 @@ Spacing_spanner::get_duration_space (Grob *me, Report OSU-CISRC-10/87-TR35, Department of Computer and Information Science, The Ohio State University, 1987. */ - Real log = log_2 (shortest); + Real log = log_2 (global_shortest_); k -= log; Rational compdur = d.main_part_ + d.grace_part_ / Rational (3); *expand_only = false; - return (log_2 (compdur) + k) * incr; + return (log_2 (compdur) + k) * increment_; } } @@ -124,7 +122,7 @@ Spacing_spanner::standard_breakable_column_spacing (Grob *me, Item *l, Item *r, else { bool dummy; - *space = *fixed + get_duration_space (me, dt, options->global_shortest_, &dummy); + *space = *fixed + options->get_duration_space (dt, &dummy); } } } @@ -174,8 +172,8 @@ Spacing_spanner::note_spacing (Grob *me, Grob *lc, Grob *rc, Real dist = 0.0; if (delta_t.main_part_ && !lwhen.grace_part_) { - dist = get_duration_space (me, shortest_playing_len, - options->global_shortest_, expand_only); + dist = options->get_duration_space (shortest_playing_len, + expand_only); dist *= double (delta_t.main_part_ / shortest_playing_len.main_part_); } else if (delta_t.grace_part_) @@ -185,8 +183,7 @@ Spacing_spanner::note_spacing (Grob *me, Grob *lc, Grob *rc, available (namely the space for the global shortest note), and multiply that by grace-space-factor */ - dist = get_duration_space (me, options->global_shortest_, - options->global_shortest_, expand_only); + dist = options->get_duration_space (options->global_shortest_, expand_only); Real grace_fact = robust_scm2double (me->get_property ("grace-space-factor"), 1); @@ -196,3 +193,31 @@ Spacing_spanner::note_spacing (Grob *me, Grob *lc, Grob *rc, return dist; } + + +/****************************************************************/ + +void +Spacing_options::init_from_grob (Grob *me) +{ + increment_ = robust_scm2double (me->get_property ("spacing-increment"), 1); + + packed_ = to_boolean (me->get_property ("packed-spacing")); + stretch_uniformly_ = to_boolean (me->get_property ("uniform-stretching")); + float_nonmusical_columns_ + = to_boolean (me->get_property ("strict-note-spacing")); + shortest_duration_space_ = robust_scm2double (me->get_property ("shortest-duration-space"), 1); +} + + +void +Spacing_options::init () +{ + increment_ = 1.2; + packed_ = false; + stretch_uniformly_ = false; + float_nonmusical_columns_ = false; + shortest_duration_space_ = 2.0; + + global_shortest_ = Rational (1,8); +} diff --git a/lily/spacing-determine-loose-columns.cc b/lily/spacing-determine-loose-columns.cc index 610b96b320..f406425c3d 100644 --- a/lily/spacing-determine-loose-columns.cc +++ b/lily/spacing-determine-loose-columns.cc @@ -8,17 +8,17 @@ */ - +#include "staff-spacing.hh" #include "system.hh" #include "paper-column.hh" #include "column-x-positions.hh" -#include "staff-spacing.hh" #include "pointer-group-interface.hh" #include "spacing-spanner.hh" #include "note-spacing.hh" - +#include "moment.hh" #include "break-align-interface.hh" +#include "warn.hh" /* Return whether COL is fixed to its neighbors by some kind of spacing @@ -31,8 +31,16 @@ (Otherwise, we might risk core dumps, and other weird stuff.) */ static bool -is_loose_column (Grob *l, Grob *c, Grob *r) +is_loose_column (Grob *l, Grob *c, Grob *r, Spacing_options const *options) { + if (options->float_nonmusical_columns_ + && Paper_column::when_mom (c).grace_part_) + return true; + + if (Paper_column::is_musical (c) + || Item::is_breakable (c)) + return false; + extract_grob_set (c, "right-neighbors", rns); extract_grob_set (c, "left-neighbors", lns); @@ -125,18 +133,16 @@ Spacing_spanner::prune_loose_columns (Grob *me, Link_array *cols, Spacing_options const *options) { Link_array newcols; - Real increment = robust_scm2double (me->get_property ("spacing-increment"), 1.2); + for (int i = 0; i < cols->size (); i++) { - if (Item::is_breakable (cols->elem (i)) - || Paper_column::is_musical (cols->elem (i))) - { - newcols.push (cols->elem (i)); - continue; - } - Grob *c = cols->elem (i); - if (is_loose_column (cols->elem (i - 1), c, cols->elem (i + 1))) + + bool loose = (i > 0 && i < cols->size()-1) + && is_loose_column (cols->elem (i - 1), c, cols->elem (i + 1), options); + + + if (loose) { extract_grob_set (c, "right-neighbors", rns_arr); extract_grob_set (c, "left-neighbors", lns_arr); @@ -168,7 +174,6 @@ Spacing_spanner::prune_loose_columns (Grob *me, Link_array *cols, Item *lc = dynamic_cast ((d == LEFT) ? next_door[LEFT] : c); Item *rc = dynamic_cast (d == LEFT ? c : next_door[RIGHT]); - extract_grob_set (lc, "spacing-wishes", wishes); for (int k = wishes.size(); k--;) { @@ -181,7 +186,7 @@ Spacing_spanner::prune_loose_columns (Grob *me, Link_array *cols, fixed = 0.0; bool dummy; - if (d == LEFT) + if (Note_spacing::has_interface (sp)) { /* The note spacing should be taken from the musical @@ -189,13 +194,13 @@ Spacing_spanner::prune_loose_columns (Grob *me, Link_array *cols, */ Real base = note_spacing (me, lc, rc, options, &dummy); - Note_spacing::get_spacing (sp, rc, base, increment, &space, &fixed); + Note_spacing::get_spacing (sp, rc, base, options->increment_, &space, &fixed); - space -= increment; + space -= options->increment_; dists[d] = max (dists[d], space); } - else + else if (Staff_spacing::has_interface (sp)) { Real space, fixed_space; Staff_spacing::get_spacing_params (sp, @@ -203,6 +208,10 @@ Spacing_spanner::prune_loose_columns (Grob *me, Link_array *cols, dists[d] = max (dists[d], fixed_space); } + else + { + programming_error ("Subversive spacing wish"); + } } } while (flip (&d) != LEFT); diff --git a/lily/spacing-loose-columns.cc b/lily/spacing-loose-columns.cc index a2f87ba6bf..9eda23b1a1 100644 --- a/lily/spacing-loose-columns.cc +++ b/lily/spacing-loose-columns.cc @@ -12,6 +12,10 @@ #include "column-x-positions.hh" #include "pointer-group-interface.hh" #include "staff-spacing.hh" +#include "note-spacing.hh" +#include "spacing-spanner.hh" + +#include "moment.hh" /* Find the loose columns in POSNS, and drape them around the columns specified in BETWEEN-COLS. */ @@ -34,6 +38,8 @@ set_loose_columns (System *which, Column_x_positions const *posns) Item *left = 0; Item *right = 0; + + Link_array clique; while (1) { SCM between = loose->get_object ("between-cols"); @@ -51,7 +57,11 @@ set_loose_columns (System *which, Column_x_positions const *posns) left = le->get_column (); if (!left->get_system ()) left = left->find_prebroken_piece (RIGHT); + + clique.push (left); } + + clique.push (loose); divide_over++; loose = right = re->get_column (); @@ -60,49 +70,77 @@ set_loose_columns (System *which, Column_x_positions const *posns) if (!right->get_system ()) right = right->find_prebroken_piece (LEFT); - Grob *common = right->common_refpoint (left, X_AXIS); - - int count = 0; - Real total_space = 0.0; - Real total_fixed = 0.0; + clique.push (right); - extract_grob_set (col, "spacing-wishes", wishes); - for (int i = 0; i < wishes.size (); i++) + Grob *common = right->common_refpoint (left, X_AXIS); + Item *finished_right_column = clique.top(); + + for (int j = clique.size() - 2; j > 0; j--) { - Grob *spacing = wishes[i]; - if (Staff_spacing::has_interface (spacing)) + int count = 0; + Real total_space = 0.0; + Real total_fixed = 0.0; + + extract_grob_set (col, "spacing-wishes", wishes); + for (int i = 0; i < wishes.size (); i++) { + Grob *spacing = wishes[i]; Real space = 0.0; Real fixed = 0.0; - Staff_spacing::get_spacing_params (spacing, &space, &fixed); - total_fixed += fixed; - total_space += space; + if (Staff_spacing::has_interface (spacing)) + { + Staff_spacing::get_spacing_params (spacing, &space, &fixed); + } + else if (Note_spacing::has_interface (spacing)) + { + Spacing_options options; + options.init (); + + fixed = robust_relative_extent (col, col, X_AXIS)[RIGHT]; + + Moment dt = Paper_column::when_mom (right) - Paper_column::when_mom (col); + bool expand; + space = options.get_duration_space (dt, &expand); + Note_spacing::get_spacing (spacing, right, space, options.increment_, + &space, &fixed); + } + else + { + continue; + } + count++; + + total_space += space; + total_fixed += fixed; } - } - Real right_point = 0.0; - Real distance_to_next = 0.0; - if (count) - { - total_space /= count; - total_fixed /= count; + Real distance_to_next = 0.0; + Real right_point = 0.0; + if (count) + { + total_space /= count; + total_fixed /= count; - distance_to_next = total_space; - right_point = right->relative_coordinate (common, X_AXIS); - } - else - { - Interval my_extent = col->extent (col, X_AXIS); - distance_to_next = my_extent[RIGHT] + default_padding; - right_point = right->extent (common, X_AXIS)[LEFT]; - } + distance_to_next = total_space; + right_point + = finished_right_column->relative_coordinate (common, X_AXIS); + } + else + { + Interval my_extent = col->extent (col, X_AXIS); + distance_to_next = my_extent[RIGHT] + default_padding; + right_point = finished_right_column->extent (common, X_AXIS)[LEFT]; + } - Real my_offset = right_point - distance_to_next; + Real my_offset = right_point - distance_to_next; + + col->system_ = which; + col->translate_axis (my_offset - col->relative_coordinate (common, X_AXIS), X_AXIS); - col->system_ = which; - col->translate_axis (my_offset - col->relative_coordinate (common, X_AXIS), X_AXIS); + finished_right_column = col; + } } } diff --git a/lily/spacing-spanner.cc b/lily/spacing-spanner.cc index 703337bd0b..861522122e 100644 --- a/lily/spacing-spanner.cc +++ b/lily/spacing-spanner.cc @@ -25,17 +25,6 @@ -void -Spacing_options::init (Grob *me) -{ - increment_ = robust_scm2double (me->get_property ("spacing-increment"), 1); - packed_ = to_boolean (me->get_layout ()->c_variable ("packed")); - stretch_uniformly_ = to_boolean (me->get_property ("uniform-stretching")); - float_nonmusical_columns_ - = to_boolean (me->get_property ("strict-note-spacing")); -} - - Rational Spacing_spanner::effective_shortest_duration (Grob *me, Link_array const &all) { @@ -70,7 +59,7 @@ Spacing_spanner::set_springs (SCM smob) set_explicit_neighbor_columns (all); Spacing_options options; - options.init (me); + options.init_from_grob (me); options.global_shortest_ = effective_shortest_duration (me, all); prune_loose_columns (me, &all, &options); @@ -462,7 +451,8 @@ ADD_INTERFACE (Spacing_spanner, "spacing-spanner-interface", "quarter note is followed by 3 NHW, the half by 4 NHW, etc.\n", "grace-space-factor spacing-increment base-shortest-duration strict-note-spacing " - "shortest-duration-space common-shortest-duration uniform-stretching" + "shortest-duration-space common-shortest-duration uniform-stretching " + "packed-spacing " ); diff --git a/lily/tuplet-bracket.cc b/lily/tuplet-bracket.cc index 3f435d6376..194044cf00 100644 --- a/lily/tuplet-bracket.cc +++ b/lily/tuplet-bracket.cc @@ -57,16 +57,13 @@ get_x_bound_item (Grob *me_grob, Direction hdir, Direction my_dir) { g = Note_column::get_stem (g); } - + return g; } Grob * Tuplet_bracket::parallel_beam (Grob *me_grob, Link_array const &cols, bool *equally_long) { - /* - ugh: code dup. - */ Spanner *me = dynamic_cast (me_grob); if (me->get_bound (LEFT)->break_status_dir () @@ -76,6 +73,10 @@ Tuplet_bracket::parallel_beam (Grob *me_grob, Link_array const &cols, bool Grob *s1 = Note_column::get_stem (cols[0]); Grob *s2 = Note_column::get_stem (cols.top ()); + + if (s2 != me->get_bound (RIGHT)) + return 0; + Grob *b1 = s1 ? Stem::get_beam (s1) : 0; Grob *b2 = s2 ? Stem::get_beam (s2) : 0; @@ -106,13 +107,10 @@ MAKE_SCHEME_CALLBACK (Tuplet_bracket, print, 1); SCM Tuplet_bracket::print (SCM smob) { - Grob *me = unsmob_grob (smob); + Spanner *me = unsmob_spanner (smob); Stencil mol; extract_grob_set (me, "note-columns", columns); - if (!columns.size ()) - return mol.smobbed_copy (); - { SCM lp = me->get_property ("left-position"); SCM rp = me->get_property ("right-position"); @@ -160,9 +158,7 @@ Tuplet_bracket::print (SCM smob) else if (numb == ly_symbol2scm ("if-no-beam")) number_visibility = !par_beam; - Grob *commonx = columns[0]->common_refpoint (columns.top (), X_AXIS); - - + 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); @@ -172,13 +168,18 @@ Tuplet_bracket::print (SCM smob) bounds[LEFT] = get_x_bound_item (me, LEFT, dir); bounds[RIGHT] = get_x_bound_item (me, RIGHT, dir); + Drul_array connect_to_other; Interval x_span; Direction d = LEFT; do { x_span[d] = robust_relative_extent (bounds[d], commonx, X_AXIS)[d]; - - if (bounds[d]->break_status_dir()) + Direction break_dir = bounds[d]->break_status_dir (); + connect_to_other[d] + = (break_dir + && (me->get_break_index() - break_dir < me->broken_intos_.size())); + + if (connect_to_other[d]) { Interval overshoot (robust_scm2drul (me->get_property ("break-overshoot"), Interval (-0.5, 1.0))); @@ -189,6 +190,16 @@ Tuplet_bracket::print (SCM smob) x_span[d] = robust_relative_extent(bounds[d], commonx, X_AXIS)[RIGHT] - overshoot[LEFT]; } + else if (d == RIGHT && + (columns.is_empty () + || bounds[d] != columns.top())) + + { + /* + TODO: make padding tunable? + */ + x_span[d] = robust_relative_extent (bounds[d], commonx, X_AXIS) [LEFT] - 1.0; + } } while (flip (&d) != LEFT); @@ -237,19 +248,32 @@ Tuplet_bracket::print (SCM smob) = robust_scm2drul (me->get_property ("bracket-flare"), zero); Drul_array shorten = robust_scm2drul (me->get_property ("shorten-pair"), zero); - + Drul_array edge_stencils; + scale_drul (&height, -ss * dir); scale_drul (&flare, ss); scale_drul (&shorten, ss); - - do { - if (bounds[d]->break_status_dir ()) + if (connect_to_other[d]) { height[d] = 0.0; flare[d] = 0.0; shorten[d] = 0.0; + + SCM properties = Font_interface::text_font_alist_chain (me); + SCM edge_text = me->get_property ("edge-text"); + + 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); @@ -267,22 +291,8 @@ Tuplet_bracket::print (SCM smob) do { - if (bounds[d]->break_status_dir ()) - { - SCM properties = Font_interface::text_font_alist_chain (me); - SCM edge_text = me->get_property ("edge-text"); - - 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); - mol.add_stencil (*edge_text); - } - } + if (!edge_stencils[d].is_empty ()) + brack.add_stencil (edge_stencils[d]); } while (flip (&d) != LEFT); @@ -393,12 +403,16 @@ Tuplet_bracket::calc_position_and_height (Grob *me_grob, Real *offset, Real *dy) Grob *commony = common_refpoint_of_array (columns, 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); + } + Grob *commonx = common_refpoint_of_array (columns, me, X_AXIS); 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); @@ -437,9 +451,6 @@ Tuplet_bracket::calc_position_and_height (Grob *me_grob, Real *offset, Real *dy) *offset = -dir * infinity_f; - if (!columns.size ()) - return; - 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]; @@ -451,10 +462,12 @@ Tuplet_bracket::calc_position_and_height (Grob *me_grob, Real *offset, Real *dy) Real factor = columns.size () > 1 ? 1 / (x1 - x0) : 1.0; Array points; + points.push (Offset (x0, staff[dir])); + points.push (Offset (x1, staff[dir])); + for (int i = 0; i < columns.size (); i++) { Interval note_ext = columns[i]->extent (commony, Y_AXIS); - note_ext.unite (staff); Real notey = note_ext[dir] - me->relative_coordinate (commony, Y_AXIS); Real x = columns[i]->relative_coordinate (commonx, X_AXIS) - x0; @@ -467,7 +480,6 @@ Tuplet_bracket::calc_position_and_height (Grob *me_grob, Real *offset, Real *dy) We assume that the smaller bracket is 1.0 space high. */ - Real ss = Staff_symbol_referencer::staff_space (me); for (int i = 0; i < tuplets.size (); i++) { @@ -564,18 +576,6 @@ Tuplet_bracket::after_line_breaking (SCM smob) Grob *me = unsmob_grob (smob); extract_grob_set (me, "note-columns", columns); - if (!columns.size ()) - { - me->suicide (); - return SCM_UNSPECIFIED; - } - if (dynamic_cast (me)->is_broken ()) - { - me->warning (_ ("removing tuplet bracket across linebreak")); - me->suicide (); - return SCM_UNSPECIFIED; - } - Direction dir = get_grob_direction (me); if (!dir) { diff --git a/lily/tuplet-engraver.cc b/lily/tuplet-engraver.cc index 84299d2662..f5628975ee 100644 --- a/lily/tuplet-engraver.cc +++ b/lily/tuplet-engraver.cc @@ -41,9 +41,10 @@ public: protected: Array tuplets_; - + Link_array last_tuplets_; DECLARE_ACKNOWLEDGER (note_column); virtual bool try_music (Music *r); + virtual void finalize (); void start_translation_timestep (); void process_music (); }; @@ -118,19 +119,32 @@ Tuplet_engraver::start_translation_timestep () { Moment now = now_mom (); + if (tuplets_.is_empty()) + return; + + Moment tsdmom = robust_scm2moment (get_property ("tupletSpannerDuration"), Moment (0)); + bool full_length = to_boolean (get_property ("tupletFullLength")); + + last_tuplets_.clear (); for (int i = tuplets_.size (); i--;) { - Moment tsdmom = robust_scm2moment (get_property ("tupletSpannerDuration"), Moment (0)); - Rational tsd = tsdmom.main_part_; if (now.main_part_ >= tuplets_[i].span_stop_) { - if (Spanner *sp = tuplets_[i].spanner_) + if (tuplets_[i].spanner_) { - if (!sp->get_bound (RIGHT)) - sp->set_bound (RIGHT, sp->get_bound (LEFT)); - + if (full_length ) + { + Item * col = unsmob_item (get_property ("currentMusicalColumn")); + + tuplets_[i].spanner_->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; } @@ -145,6 +159,19 @@ Tuplet_engraver::start_translation_timestep () } } +void +Tuplet_engraver::finalize () +{ + if (to_boolean (get_property ("tupletFullLength"))) + { + for (int i = 0; i < last_tuplets_.size (); i++) + { + Item * col = unsmob_item (get_property ("currentCommandColumn")); + last_tuplets_[i]->set_bound (RIGHT, col); + } + } +} + Tuplet_engraver::Tuplet_engraver () { } @@ -154,5 +181,5 @@ ADD_TRANSLATOR (Tuplet_engraver, /* descr */ "Catch Time_scaled_music and generate appropriate bracket ", /* creats*/ "TupletBracket", /* accepts */ "time-scaled-music", - /* reads */ "tupletNumberFormatFunction tupletSpannerDuration", + /* reads */ "tupletNumberFormatFunction tupletSpannerDuration tupletFullLength" , /* write */ ""); diff --git a/ly/engraver-init.ly b/ly/engraver-init.ly index 3cb645460e..4189c9aca3 100644 --- a/ly/engraver-init.ly +++ b/ly/engraver-init.ly @@ -518,7 +518,7 @@ AncientRemoveEmptyStaffContext = \context { autoCautionaries = #'() printKeyCancellation = ##t - keyAccidentalOrder = #`( + keyAlterationOrder = #`( (6 . ,FLAT) (2 . ,FLAT) (5 . ,FLAT ) (1 . ,FLAT) (4 . ,FLAT) (0 . ,FLAT) (3 . ,FLAT) (3 . ,SHARP) (0 . ,SHARP) (4 . ,SHARP) (1 . ,SHARP) (5 . ,SHARP) (2 . ,SHARP) (6 . ,SHARP) (6 . ,DOUBLE-FLAT) (2 . ,DOUBLE-FLAT) (5 . ,DOUBLE-FLAT ) (1 . ,DOUBLE-FLAT) (4 . ,DOUBLE-FLAT) (0 . ,DOUBLE-FLAT) (3 . ,DOUBLE-FLAT) diff --git a/scm/define-context-properties.scm b/scm/define-context-properties.scm index 75bd2e9916..da0bbfd9f9 100644 --- a/scm/define-context-properties.scm +++ b/scm/define-context-properties.scm @@ -382,6 +382,8 @@ Switch off for cadenzas.") (tremoloFlags ,integer? "Number of tremolo flags to add if no number is specified.") + (tupletFullLength ,boolean? "If set, the tuplet is printed upto +the start of the next note.") (tupletNumberFormatFunction ,procedure? "Function taking a music as input, producing a string. This function diff --git a/scm/define-grob-properties.scm b/scm/define-grob-properties.scm index 5a285980b6..446000b509 100644 --- a/scm/define-grob-properties.scm +++ b/scm/define-grob-properties.scm @@ -348,7 +348,9 @@ spacing constraints.") 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}.") - + + (packed-spacing ,boolean? "If set, the notes are spaced as +tightly as possible.") (padding ,ly:dimension? "Add this much extra space between objects that are next to each other.") (page-penalty ,number? "Penalty for page break at -- 2.39.5