From 1bcba0490ef7ad8671d221844b16b95da22ce9a0 Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Fri, 21 Jul 2006 11:44:58 +0000 Subject: [PATCH] * scm/output-lib.scm (grace-spacing::calc-shortest-duration): new function. * scm/define-grob-properties.scm (all-user-grob-properties): remove grace-space-factor. * scm/define-grob-interfaces.scm (grace-spacing-interface): add grace-spacing-interface (spacing-options-interface): add. * ly/engraver-init.ly (AncientRemoveEmptyStaffContext): add Grace_spacing_engraver * lily/spacing-options.cc (get_duration_space): move function from spacing-basic.cc * lily/spacing-basic.cc (note_spacing): do init_from_grob on GraceSpacing object. * lily/note-spacing.cc: fix prop list formatting * lily/beaming-pattern.cc (de_grace): new function. Sensible beaming for grace notes too. * input/regression/spacing-grace.ly: update. * lily/grace-spacing-engraver.cc: new file. * lily/spacing-spanner.cc: add strict-grace-spacing. --- ChangeLog | 28 +++++++++++ VERSION | 2 +- input/regression/spacing-grace.ly | 37 ++++++++++----- lily/beaming-pattern.cc | 23 +++++++++ lily/grace-spacing-engraver.cc | 78 +++++++++++++++++++++++++++++++ lily/include/beaming-pattern.hh | 2 + lily/include/spacing-spanner.hh | 2 +- lily/note-spacing.cc | 10 +++- lily/paper-column.cc | 1 + lily/spacing-basic.cc | 70 ++++++--------------------- lily/spacing-loose-columns.cc | 3 +- lily/spacing-options.cc | 61 ++++++++++++++++++++++++ lily/spacing-spanner.cc | 6 +-- ly/engraver-init.ly | 1 + scm/define-grob-interfaces.scm | 21 +++++++-- scm/define-grob-properties.scm | 4 +- scm/define-grobs.scm | 12 +++++ scm/output-lib.scm | 25 ++++++++++ 18 files changed, 302 insertions(+), 84 deletions(-) create mode 100644 lily/grace-spacing-engraver.cc diff --git a/ChangeLog b/ChangeLog index c2cd818c18..30708b6964 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,31 @@ +2006-07-21 Han-Wen Nienhuys + + * scm/output-lib.scm (grace-spacing::calc-shortest-duration): new function. + + * scm/define-grob-properties.scm (all-user-grob-properties): + remove grace-space-factor. + + * scm/define-grob-interfaces.scm (grace-spacing-interface): add grace-spacing-interface + (spacing-options-interface): add. + + * ly/engraver-init.ly (AncientRemoveEmptyStaffContext): add Grace_spacing_engraver + + * lily/spacing-options.cc (get_duration_space): move function from spacing-basic.cc + + * lily/spacing-basic.cc (note_spacing): do init_from_grob on + GraceSpacing object. + + * lily/note-spacing.cc: fix prop list formatting + + * lily/beaming-pattern.cc (de_grace): new function. Sensible + beaming for grace notes too. + + * input/regression/spacing-grace.ly: update. + + * lily/grace-spacing-engraver.cc: new file. + + * lily/spacing-spanner.cc: add strict-grace-spacing. + 2006-07-20 Graham Percival * lily/parser.yy: compile fix. diff --git a/VERSION b/VERSION index 76e2b35efe..7d754a77ed 100644 --- a/VERSION +++ b/VERSION @@ -1,6 +1,6 @@ PACKAGE_NAME=LilyPond MAJOR_VERSION=2 MINOR_VERSION=9 -PATCH_LEVEL=12 +PATCH_LEVEL=13 MY_PATCH_LEVEL= diff --git a/input/regression/spacing-grace.ly b/input/regression/spacing-grace.ly index aedc10df7d..c4a1c466f8 100644 --- a/input/regression/spacing-grace.ly +++ b/input/regression/spacing-grace.ly @@ -1,14 +1,27 @@ - -\version "2.7.39" -\header { - texidoc = "Grace note spacing. " +\header +{ + texidoc = "Grace note runs have their own spacing variables in + @code{Score.GraceSpacing}. So differing grace note lengths inside a + run are spaced accordingly. " } -\layout { ragged-right = ##t} - - -\context Voice \relative c'' { \grace { c16[ d] } c4 } - - - - +\version "2.9.13" + +\paper { ragged-right = ##t } + +\relative c'' +{ + c4 + \grace { c16 } + c + \grace { c16 } + d + \grace { c16[ d e f] } + c + \grace { c8[ c16 d c8] } + c + \override Score.GraceSpacing #'spacing-increment = #2.0 + + \grace { c4 c16 d16 } + c +} diff --git a/lily/beaming-pattern.cc b/lily/beaming-pattern.cc index 87ff00dc63..8966657e48 100644 --- a/lily/beaming-pattern.cc +++ b/lily/beaming-pattern.cc @@ -25,6 +25,17 @@ Beam_rhythmic_element::Beam_rhythmic_element (Moment m, int i) } +void +Beam_rhythmic_element::de_grace () +{ + if (start_moment_.grace_part_) + { + start_moment_.main_part_ = + start_moment_.grace_part_; + start_moment_.grace_part_ = 0; + } +} + int count_factor_twos (int x) { @@ -96,11 +107,23 @@ Beaming_pattern::beam_extend_count (Direction d) const return min (thisbeam.beam_count_drul_[-d], next.beam_count_drul_[d]); } +void +Beaming_pattern::de_grace () +{ + for (vsize i = 0; i < infos_.size (); i ++) + { + infos_[i].de_grace (); + } +} + void Beaming_pattern::beamify (Context *context) { if (infos_.size () <= 1) return; + + if (infos_[0].start_moment_.grace_part_) + de_grace (); bool subdivide_beams = to_boolean (context->get_property ("subdivideBeams")); Moment beat_length = robust_scm2moment (context->get_property ("beatLength"), Moment (1, 4)); diff --git a/lily/grace-spacing-engraver.cc b/lily/grace-spacing-engraver.cc new file mode 100644 index 0000000000..b784358a2c --- /dev/null +++ b/lily/grace-spacing-engraver.cc @@ -0,0 +1,78 @@ +/* + grace-spacing-engraver.cc -- implement Grace_spacing_engraver + + source file of the GNU LilyPond music typesetter + + (c) 2006 Han-Wen + +*/ + +#include "engraver.hh" +#include "spanner.hh" +#include "pointer-group-interface.hh" + +#include "translator.icc" + +class Grace_spacing_engraver : public Engraver +{ + TRANSLATOR_DECLARATIONS (Grace_spacing_engraver); + +protected: + + Moment last_moment_; + Spanner *grace_spacing_; + + void process_music (); + void stop_translation_timestep (); +}; + + +Grace_spacing_engraver::Grace_spacing_engraver () +{ + grace_spacing_ = 0; +} + +void +Grace_spacing_engraver::process_music () +{ + Moment now = now_mom (); + if (!last_moment_.grace_part_ and now.grace_part_) + { + grace_spacing_ = make_spanner ("GraceSpacing", SCM_EOL); + } + + + if (grace_spacing_ && (now.grace_part_ || last_moment_.grace_part_)) + { + Grob *column = unsmob_grob (get_property ("currentMusicalColumn")); + Pointer_group_interface::add_grob (grace_spacing_, + ly_symbol2scm ("columns"), + column); + + column->set_object ("grace-spacing", grace_spacing_->self_scm ()); + } +} + +void +Grace_spacing_engraver::stop_translation_timestep () +{ + last_moment_ = now_mom (); + + if (!last_moment_.grace_part_) + grace_spacing_ = 0; +} + + +ADD_TRANSLATOR (Grace_spacing_engraver, + "Bookkeeping of shortest starting and playing notes in grace note runs.", + + /* create */ + "GraceSpacing ", + + /* accept */ + "", + + /* read */ + "currentMusicalColumn ", + + /* write */ ""); diff --git a/lily/include/beaming-pattern.hh b/lily/include/beaming-pattern.hh index 6033217668..5e0c7c30ec 100644 --- a/lily/include/beaming-pattern.hh +++ b/lily/include/beaming-pattern.hh @@ -26,6 +26,7 @@ struct Beam_rhythmic_element Beam_rhythmic_element (); int count (Direction d); + void de_grace (); }; /* @@ -38,6 +39,7 @@ public: Beaming_pattern (); void beamify (Context*); + void de_grace (); void add_stem (Moment d, int beams); int beamlet_count (int idx, Direction d) const; diff --git a/lily/include/spacing-spanner.hh b/lily/include/spacing-spanner.hh index d2259533c8..f39ea98bc3 100644 --- a/lily/include/spacing-spanner.hh +++ b/lily/include/spacing-spanner.hh @@ -26,7 +26,7 @@ struct Spacing_options Spacing_options(); void init_from_grob (Grob *me); - Real get_duration_space (Moment d, bool *) const; + Real get_duration_space (Rational d, bool *) const; }; /* diff --git a/lily/note-spacing.cc b/lily/note-spacing.cc index 619cda9b4e..2700c12835 100644 --- a/lily/note-spacing.cc +++ b/lily/note-spacing.cc @@ -457,5 +457,13 @@ Note_spacing::stem_dir_correction (Grob *me, Item *rcolumn, ADD_INTERFACE (Note_spacing, "note-spacing-interface", "This object calculates spacing wishes for individual voices.", - "left-items right-items stem-spacing-correction same-direction-correction knee-spacing-correction"); + + + "knee-spacing-correction " + "left-items " + "right-items " + "same-direction-correction " + "stem-spacing-correction " + + ); diff --git a/lily/paper-column.cc b/lily/paper-column.cc index fccdba6e7f..4da6ff3ef9 100644 --- a/lily/paper-column.cc +++ b/lily/paper-column.cc @@ -206,6 +206,7 @@ ADD_INTERFACE (Paper_column, /* properties */ "between-cols " "bounded-by-me " + "grace-spacing " "line-break-system-details " "line-break-penalty " "line-break-permission " diff --git a/lily/spacing-basic.cc b/lily/spacing-basic.cc index 86dd575d1e..4a11d75b48 100644 --- a/lily/spacing-basic.cc +++ b/lily/spacing-basic.cc @@ -9,7 +9,6 @@ #include "spacing-spanner.hh" #include "moment.hh" #include "paper-column.hh" -#include "misc.hh" #include "warn.hh" /* @@ -17,54 +16,6 @@ adding subtle adjustments to that. This file does the simple-minded spacing routines. */ - -/* - Get the measure wide ant for arithmetic spacing. -*/ -Real -Spacing_options::get_duration_space (Moment d, - bool *expand_only) const -{ - Real k = shortest_duration_space_; - - if (d < global_shortest_) - { - /* - We don't space really short notes using the log of the - duration, since it would disproportionally stretches the long - notes in a piece. In stead, we use geometric spacing with constant 0.5 - (i.e. linear.) - - This should probably be tunable, to use other base numbers. - - In Mozart hrn3 by EB., we have 8th note = 3.9 mm (total), 16th note = - 3.6 mm (total). head-width = 2.4, so we 1.2mm for 16th, 1.5 - mm for 8th. (white space), suggesting that we use - - (1.2 / 1.5)^{-log2(duration ratio)} - - - */ - Rational ratio = d.main_part_ / global_shortest_; - - return ((k - 1) + double (ratio)) * increment_; - } - else - { - /* - John S. Gourlay. ``Spacing a Line of Music, '' Technical - Report OSU-CISRC-10/87-TR35, Department of Computer and - Information Science, The Ohio State University, 1987. - */ - 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) * increment_; - } -} - /* The one-size-fits all spacing. It doesn't take into account different spacing wishes from one to the next column. @@ -119,7 +70,7 @@ Spacing_spanner::standard_breakable_column_spacing (Grob *me, Item *l, Item *r, else { bool dummy; - *space = *fixed + options->get_duration_space (dt, &dummy); + *space = *fixed + options->get_duration_space (dt.main_part_, &dummy); } } } @@ -129,6 +80,8 @@ Spacing_spanner::note_spacing (Grob *me, Grob *lc, Grob *rc, Spacing_options const *options, bool *expand_only) { + (void) me; + Moment shortest_playing_len = 0; SCM s = lc->get_property ("shortest-playing-duration"); @@ -169,7 +122,7 @@ Spacing_spanner::note_spacing (Grob *me, Grob *lc, Grob *rc, Real dist = 0.0; if (delta_t.main_part_ && !lwhen.grace_part_) { - dist = options->get_duration_space (shortest_playing_len, + dist = options->get_duration_space (shortest_playing_len.main_part_, expand_only); dist *= double (delta_t.main_part_ / shortest_playing_len.main_part_); } @@ -180,15 +133,20 @@ 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 = options->get_duration_space (options->global_shortest_, expand_only); + dist = options->get_duration_space (options->global_shortest_, expand_only) / 2.0; + Grob *grace_spacing = unsmob_grob (lc->get_object ("grace-spacing")); + if (grace_spacing) + { + Spacing_options grace_opts; + grace_opts.init_from_grob (grace_spacing); - Real grace_fact - = robust_scm2double (me->get_property ("grace-space-factor"), 1); - dist *= grace_fact; + bool bla; + dist = grace_opts.get_duration_space (delta_t.grace_part_, &bla); + } + } return dist; } -/****************************************************************/ diff --git a/lily/spacing-loose-columns.cc b/lily/spacing-loose-columns.cc index cc73fc138e..fdcc77f1b2 100644 --- a/lily/spacing-loose-columns.cc +++ b/lily/spacing-loose-columns.cc @@ -97,7 +97,8 @@ set_loose_columns (System *which, Column_x_positions const *posns) Moment dt = Paper_column::when_mom (right) - Paper_column::when_mom (col); bool expand = false; - space = options.get_duration_space (dt, &expand); + + space = options.get_duration_space (dt.main_part_, &expand); Note_spacing::get_spacing (spacing, right, space, options.increment_, &space, &fixed); } diff --git a/lily/spacing-options.cc b/lily/spacing-options.cc index 917980f5f8..916408aa73 100644 --- a/lily/spacing-options.cc +++ b/lily/spacing-options.cc @@ -9,6 +9,8 @@ #include "spacing-spanner.hh" #include "grob.hh" +#include "misc.hh" +#include "moment.hh" void Spacing_options::init_from_grob (Grob *me) @@ -22,6 +24,16 @@ Spacing_options::init_from_grob (Grob *me) float_grace_columns_ = to_boolean (me->get_property ("strict-grace-spacing")); shortest_duration_space_ = robust_scm2double (me->get_property ("shortest-duration-space"), 1); + + + Moment shortest_dur = robust_scm2moment (me->get_property ("common-shortest-duration"), + Moment (Rational (1,8), Rational (1,16))); + + if (shortest_dur.main_part_) + global_shortest_ = shortest_dur.main_part_; + else + global_shortest_ = shortest_dur.grace_part_; + } Spacing_options::Spacing_options () @@ -36,3 +48,52 @@ Spacing_options::Spacing_options () global_shortest_ = Rational (1, 8); } + + + +/* + Get the measure wide ant for arithmetic spacing. +*/ +Real +Spacing_options::get_duration_space (Rational d, + bool *expand_only) const +{ + Real k = shortest_duration_space_; + + if (d < global_shortest_) + { + /* + We don't space really short notes using the log of the + duration, since it would disproportionally stretches the long + notes in a piece. In stead, we use geometric spacing with constant 0.5 + (i.e. linear.) + + This should probably be tunable, to use other base numbers. + + In Mozart hrn3 by EB., we have 8th note = 3.9 mm (total), 16th note = + 3.6 mm (total). head-width = 2.4, so we 1.2mm for 16th, 1.5 + mm for 8th. (white space), suggesting that we use + + (1.2 / 1.5)^{-log2(duration ratio)} + + + */ + Rational ratio = d / global_shortest_; + + return ((k - 1) + double (ratio)) * increment_; + } + else + { + /* + John S. Gourlay. ``Spacing a Line of Music, '' Technical + Report OSU-CISRC-10/87-TR35, Department of Computer and + Information Science, The Ohio State University, 1987. + */ + Real log = log_2 (global_shortest_); + k -= log; + *expand_only = false; + + return (log_2 (d) + k) * increment_; + } +} + diff --git a/lily/spacing-spanner.cc b/lily/spacing-spanner.cc index 04ad54765e..b21ce3d3ab 100644 --- a/lily/spacing-spanner.cc +++ b/lily/spacing-spanner.cc @@ -54,8 +54,6 @@ Spacing_spanner::set_springs (SCM smob) Spacing_options options; options.init_from_grob (me); - options.global_shortest_ = robust_scm2moment (me->get_property ("common-shortest-duration"), - Moment (Rational (1,8))).main_part_; prune_loose_columns (me, &all, &options); set_implicit_neighbor_columns (all); @@ -266,7 +264,6 @@ Spacing_spanner::musical_column_spacing (Grob *me, if (!lext.is_empty ()) compound_note_space += -lext[LEFT]; } - } else { @@ -500,10 +497,10 @@ ADD_INTERFACE (Spacing_spanner, "spacing-spanner-interface", "average-spacing-wishes " "base-shortest-duration " "common-shortest-duration " - "grace-space-factor " "packed-spacing " "shortest-duration-space " "spacing-increment " + "strict-grace-spacing " "strict-note-spacing " "uniform-stretching " @@ -512,5 +509,6 @@ ADD_INTERFACE (Spacing_spanner, "spacing-spanner-interface", ADD_INTERFACE (Spacing_interface, "spacing-interface", "Something to do with line breaking and spacing. " "Kill this one after determining line breaks.", + ""); diff --git a/ly/engraver-init.ly b/ly/engraver-init.ly index efc14e9a35..7798bc3145 100644 --- a/ly/engraver-init.ly +++ b/ly/engraver-init.ly @@ -459,6 +459,7 @@ AncientRemoveEmptyStaffContext = \context { \consists "Metronome_mark_engraver" \consists "Break_align_engraver" \consists "Spacing_engraver" + \consists "Grace_spacing_engraver" \consists "Vertical_align_engraver" \consists "Stanza_number_align_engraver" \consists "Bar_number_engraver" diff --git a/scm/define-grob-interfaces.scm b/scm/define-grob-interfaces.scm index 2251fb4780..6ab1b55cce 100644 --- a/scm/define-grob-interfaces.scm +++ b/scm/define-grob-interfaces.scm @@ -45,17 +45,17 @@ "A fingering instruction" '()) -(ly:add-interface - 'string-number-interface - "A string number instruction" - '()) - (ly:add-interface 'fret-diagram-interface "A fret diagram" '(align-dir barre-type dot-color dot-radius finger-code fret-count label-dir number-type size string-count thickness)) +(ly:add-interface + 'grace-spacing-interface + "Keep track of durations in a run of grace notes." + '(columns common-shortest-duration)) + (ly:add-interface 'ligature-interface "A ligature" @@ -123,11 +123,22 @@ are interesting enough to maintain a hara-kiri staff." '()) + +(ly:add-interface + 'spacing-options-interface + "Supports setting of spacing variables" + '(spacing-increment shortest-duration-space)) + (ly:add-interface 'stanza-number-interface "A stanza number, to be put in from of a lyrics line" '()) +(ly:add-interface + 'string-number-interface + "A string number instruction" + '()) + (ly:add-interface 'system-start-text-interface "A text at the beginning of a system." diff --git a/scm/define-grob-properties.scm b/scm/define-grob-properties.scm index 2633e6db70..9d59719a8a 100644 --- a/scm/define-grob-properties.scm +++ b/scm/define-grob-properties.scm @@ -225,9 +225,6 @@ typeset. Valid choices depend on the function that is reading this property.") (gap ,ly:dimension? "Size of a gap in a variable symbol.") (gap-count ,integer? "Number of gapped beams for tremolo.") - (grace-space-factor ,number? "Space grace notes at this fraction -of the @code{spacing-increment}.") - (grow-direction ,ly:dir? "Crescendo or decrescendo?") (hair-thickness ,number? "Thickness of the thin line in a bar line.") (head-direction ,ly:dir? "Are the note heads left or right in a semitie?") @@ -529,6 +526,7 @@ paper-columns or note-column objects.") in addition to notes and stems.") (elements ,ly:grob-array? "list of grobs, type depending on the Grob where this is set in.") + (grace-spacing ,ly:grob-array? "a run of grace notes.") (heads ,ly:grob-array? "List of note heads.") (items-worth-living ,ly:grob-array? "A list of interesting items. If empty in a particular staff, then that staff is erased.") diff --git a/scm/define-grobs.scm b/scm/define-grobs.scm index 8f554a2fa4..61edbf6b4a 100644 --- a/scm/define-grobs.scm +++ b/scm/define-grobs.scm @@ -652,6 +652,16 @@ (interfaces . (line-interface line-spanner-interface)))))) + (GraceSpacing + . ( + (common-shortest-duration . ,grace-spacing::calc-shortest-duration) + (spacing-increment . 0.8) + (shortest-duration-space . 1.6) + (meta . ((class . Spanner) + (interfaces . (grace-spacing-interface + spacing-interface + spacing-options-interface + spanner-interface)))))) (GridPoint . ( (X-extent . (0 . 0)) @@ -1360,9 +1370,11 @@ (grace-space-factor . 0.6) (shortest-duration-space . 2.0) (spacing-increment . 1.2) + (base-shortest-duration . ,(ly:make-moment 3 16)) (meta . ((class . Spanner) (interfaces . (spacing-interface + spacing-options-interface spacing-spanner-interface)))))) (SpanBar diff --git a/scm/output-lib.scm b/scm/output-lib.scm index 561184cbe9..dd456be80c 100644 --- a/scm/output-lib.scm +++ b/scm/output-lib.scm @@ -377,3 +377,28 @@ centered, X==1 is at the right, X == -1 is at the left." (cons 0 dx) (cons (min 0 delta) (max 0 delta))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; grace spacing + + +(define-public (grace-spacing::calc-shortest-duration grob) + (let* + ((cols (ly:grob-object grob 'columns)) + (get-difference + (lambda (idx) + (ly:moment-sub (ly:grob-property (ly:grob-array-ref cols (1+ idx)) 'when) + (ly:grob-property (ly:grob-array-ref cols idx) 'when)))) + + (moment-min (lambda (x y) + (cond + ((and x y) + (if (ly:moment