+2006-07-21 Han-Wen Nienhuys <hanwen@lilypond.org>
+
+ * 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 <gpermus@gmail.com>
* lily/parser.yy: compile fix.
PACKAGE_NAME=LilyPond
MAJOR_VERSION=2
MINOR_VERSION=9
-PATCH_LEVEL=12
+PATCH_LEVEL=13
MY_PATCH_LEVEL=
-
-\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
+}
}
+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)
{
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));
--- /dev/null
+/*
+ grace-spacing-engraver.cc -- implement Grace_spacing_engraver
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 2006 Han-Wen <hanwen@lilypond.org>
+
+*/
+
+#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 */ "");
Beam_rhythmic_element ();
int count (Direction d);
+ void de_grace ();
};
/*
Beaming_pattern ();
void beamify (Context*);
+ void de_grace ();
void add_stem (Moment d, int beams);
int beamlet_count (int idx, Direction d) const;
Spacing_options();
void init_from_grob (Grob *me);
- Real get_duration_space (Moment d, bool *) const;
+ Real get_duration_space (Rational d, bool *) const;
};
/*
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 "
+
+ );
/* properties */
"between-cols "
"bounded-by-me "
+ "grace-spacing "
"line-break-system-details "
"line-break-penalty "
"line-break-permission "
#include "spacing-spanner.hh"
#include "moment.hh"
#include "paper-column.hh"
-#include "misc.hh"
#include "warn.hh"
/*
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.
else
{
bool dummy;
- *space = *fixed + options->get_duration_space (dt, &dummy);
+ *space = *fixed + options->get_duration_space (dt.main_part_, &dummy);
}
}
}
Spacing_options const *options,
bool *expand_only)
{
+ (void) me;
+
Moment shortest_playing_len = 0;
SCM s = lc->get_property ("shortest-playing-duration");
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_);
}
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;
}
-/****************************************************************/
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);
}
#include "spacing-spanner.hh"
#include "grob.hh"
+#include "misc.hh"
+#include "moment.hh"
void
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 ()
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_;
+ }
+}
+
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);
if (!lext.is_empty ())
compound_note_space += -lext[LEFT];
}
-
}
else
{
"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 "
ADD_INTERFACE (Spacing_interface, "spacing-interface",
"Something to do with line breaking and spacing. "
"Kill this one after determining line breaks.",
+
"");
\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"
"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"
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."
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?")
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.")
(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))
(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
(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<? x y)
+ x
+ y))
+ (x x)
+ (y y)))))
+
+
+ (fold moment-min #f (map get-difference (iota (1- (ly:grob-array-length cols)))))))
+