Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue 3304 #2

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 1 addition & 2 deletions Documentation/notation/spacing.itely
Expand Up @@ -2780,8 +2780,7 @@ more space, shorter durations get less. The shortest durations get a
fixed amount of space (which is controlled by
@code{shortest-duration-space} in the @rinternals{SpacingSpanner}
object). The longer the duration, the more space it gets: doubling a
duration adds a fixed amount (this amount is controlled by
@code{spacing-increment}) of space to the note.
duration adds @code{spacing-increment} of space to the note.

For example, the following piece contains lots of half, quarter, and
8th notes; the eighth note is followed by 1 note head width (NHW).
Expand Down
7 changes: 3 additions & 4 deletions input/regression/baerenreiter-sarabande.ly
@@ -1,6 +1,6 @@
\version "2.17.6"

forcedLastBreak = { \break }
forcedLastBreak = {} %% { \break } if needed to match original breaks

%% We want this to perfectly match the Bärenreiter spacing.
%% If we're not using 6 systems, there's definitely a problem.
Expand Down Expand Up @@ -171,10 +171,9 @@ smallerPaper = \layout {
ragged-bottom = ##t
indent = 7. \mm
line-width =183.5 \mm
obsolete-between-system-space = 25\mm
system-system-spacing #'basic-distance = #(/ obsolete-between-system-space staff-space)
system-system-spacing #'basic-distance = 14.22 % 25mm, in staff-spaces
system-system-spacing #'padding = #0
score-system-spacing #'basic-distance = #(/ obsolete-between-system-space staff-space)
score-system-spacing #'basic-distance = #0
score-system-spacing #'padding = #0
system-count = 6

Expand Down
18 changes: 4 additions & 14 deletions input/regression/spacing-multi-tuplet.ly
Expand Up @@ -2,28 +2,18 @@

\header{

texidoc = "Concurrent tuplets should be equidistant on all staves.
Such equidistant spacing is at odds with elegant engraver spacing;
hence it must be switched on explicitly with the
@code{uniform-stretching} property of @code{SpacingSpanner}."
texidoc = "Concurrent tuplets should be equidistant on all staves."
}

\layout{
\context{
\Score
\override SpacingSpanner.uniform-stretching = ##t
}
}
\paper {ragged-right = ##f }

\relative c' {
\context StaffGroup <<
\new Staff \context Voice {
\tuplet 10/2 { c8[ c c c c c c c c c] }
\tuplet 10/2 { c[ c c c c c c c c c] }
\tuplet 10/8 { c8[ c c c c c c c c c] }
}
\new Staff \context Voice {
\tuplet 11/2 { c8[ c c c c c c c c c c] }
\tuplet 11/2 { c[ c c c c c c c c c c] }
\tuplet 8/8 { c8[ c c c c c c c] }
}
>>
}
Expand Down
2 changes: 1 addition & 1 deletion input/regression/spanner-alignment.ly
Expand Up @@ -16,7 +16,7 @@ ignoring things like pedal marks.
}
\new Dynamics = "dynamics" {
\repeat unfold 2 {
s1\cresc s1\f s1\dim s1\p
s1\cresc s1\f s1\dim s1\p \break
}
}
\new Staff = "down" {
Expand Down
4 changes: 2 additions & 2 deletions lily/include/note-spacing.hh
Expand Up @@ -29,9 +29,9 @@ class Note_spacing
public:
DECLARE_GROB_INTERFACE ();

static Spring get_spacing (Grob *me, Item *, Real, Real);
static Spring get_spacing (Grob *me, Item *, Spring, Real);
static void stem_dir_correction (Grob *me, Item *next_col, Real incr,
Real *, Real *);
Real *space);
};

#endif /* NOTE_SPACING_HH */
2 changes: 1 addition & 1 deletion lily/include/spacing-spanner.hh
Expand Up @@ -45,7 +45,7 @@ private:
static bool fills_measure (Grob *, Item *, Item *);
public:
static vector<Grob *> get_columns (Grob *me);
static Real note_spacing (Grob *, Grob *, Grob *, Spacing_options const *);
static Spring note_spacing (Grob *, Grob *, Grob *, Spacing_options const *);
static Spring standard_breakable_column_spacing (Grob *me, Item *l, Item *r, Spacing_options const *);

DECLARE_SCHEME_CALLBACK (set_springs, (SCM));
Expand Down
41 changes: 16 additions & 25 deletions lily/note-spacing.cc
Expand Up @@ -36,13 +36,12 @@
#include "warn.hh"

/*
TODO: detect hshifts due to collisions, and account for them in
spacing?
Adjust the ideal and minimum distance between note columns,
based on the notehead size, skylines, and optical illusions.
*/

Spring
Note_spacing::get_spacing (Grob *me, Item *right_col,
Real base_space, Real increment)
Spring base, Real increment)
{
vector<Item *> note_columns = Spacing_interface::left_note_columns (me);
Real left_head_end = 0;
Expand Down Expand Up @@ -73,16 +72,12 @@ Note_spacing::get_spacing (Grob *me, Item *right_col,
The main factor that determines the amount of space is the width of the
note head (or the rest). For example, a quarter rest gets almost 0.5 ss
less horizontal space than a note.

The other parts of a note column (eg. flags, accidentals, etc.) don't get
the full amount of space. We give them half the amount of space, but then
adjust things so there are no collisions.
*/
Real ideal = base.distance () - increment + left_head_end;
Drul_array<Skyline> skys = Spacing_interface::skylines (me, right_col);
Real distance = skys[LEFT].distance (skys[RIGHT], robust_scm2double (right_col->get_property ("skyline-vertical-padding"), 0.0));
Real min_dist = max (0.0, distance);
Real min_desired_space = left_head_end + (min_dist - left_head_end + base_space - increment) / 2;
Real ideal = base_space - increment + left_head_end;
base.set_min_distance (min_dist);

/* If we have a NonMusical column on the right, we measure the ideal distance
to the bar-line (if present), not the start of the column. */
Expand All @@ -95,24 +90,21 @@ Note_spacing::get_spacing (Grob *me, Item *right_col,
Bar_line::non_empty_barline);

if (bar)
ideal -= bar->extent (right_col, X_AXIS)[LEFT];
else
{
Real shift = bar->extent (right_col, X_AXIS)[LEFT];
ideal -= shift;
min_desired_space -= max (shift, 0.0);
/* Measure ideal distance to the right side of the NonMusical column
but keep at least half the gap we would have had to a note */
Real min_desired_space = (ideal + min_dist) / 2.0;
ideal -= right_col->extent (right_col, X_AXIS)[RIGHT];
ideal = max (ideal, min_desired_space);
}
else
ideal -= right_col->extent (right_col, X_AXIS)[RIGHT];
}

ideal = max (ideal, min_desired_space);
stem_dir_correction (me, right_col, increment, &ideal, &min_desired_space);
stem_dir_correction (me, right_col, increment, &ideal);

/* TODO: grace notes look bad when things are stretched. Should we increase
their stretch strength? */
Spring ret (max (0.0, ideal), min_dist);
ret.set_inverse_compress_strength (max (0.0, ideal - min_desired_space));
ret.set_inverse_stretch_strength (max (0.1, base_space - increment));
return ret;
base.set_distance (max (0.0, ideal));
return base;
}

static Real
Expand Down Expand Up @@ -206,7 +198,7 @@ same_direction_correction (Grob *note_spacing, Drul_array<Interval> head_posns)
void
Note_spacing::stem_dir_correction (Grob *me, Item *rcolumn,
Real increment,
Real *space, Real *fixed)
Real *space)
{
Drul_array<Direction> stem_dirs (CENTER, CENTER);
Drul_array<Interval> stem_posns;
Expand Down Expand Up @@ -310,7 +302,6 @@ Note_spacing::stem_dir_correction (Grob *me, Item *rcolumn,
&& !acc_right)
correction = same_direction_correction (me, head_posns);

*fixed += correction;
*space += correction;

/* there used to be a correction for bar_xextent () here, but
Expand Down
36 changes: 23 additions & 13 deletions lily/spacing-basic.cc
Expand Up @@ -101,7 +101,8 @@ get_measure_length (Grob *column)
return 0;
}

Real
/* Basic spring based on duration alone */
Spring
Spacing_spanner::note_spacing (Grob * /* me */,
Grob *lc,
Grob *rc,
Expand Down Expand Up @@ -144,30 +145,39 @@ Spacing_spanner::note_spacing (Grob * /* me */,
shortest_playing_len = min (shortest_playing_len, *measure_len);
}

Real dist = 0.0;
Spring ret;
if (delta_t.main_part_ && !lwhen.grace_part_)
{
dist = options->get_duration_space (shortest_playing_len.main_part_);
dist *= double (delta_t.main_part_ / shortest_playing_len.main_part_);
// A spring of length and stiffness based on the controlling duration
Real len = options->get_duration_space (shortest_playing_len.main_part_);
Real min = options->increment_; // canonical notehead width

// The portion of that spring proportional to the time between lc and rc
Real fraction = (delta_t.main_part_ / shortest_playing_len.main_part_);
ret = Spring (fraction * len, fraction * min);

// Stretch proportional to the space between canonical bare noteheads
ret.set_inverse_stretch_strength (fraction * max (0.0, (len - min)));
}
else if (delta_t.grace_part_)
{
/*
Crude hack for spacing graces: we take the shortest space
available (namely the space for the global shortest note), and
multiply that by grace-space-factor
*/
dist = options->get_duration_space (options->global_shortest_) / 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);
dist = grace_opts.get_duration_space (delta_t.grace_part_);
Real len = grace_opts.get_duration_space (delta_t.grace_part_);
Real min = grace_opts.increment_;
ret = Spring (len, min);
// Grace notes should not stretch very much
ret.set_inverse_stretch_strength (grace_opts.increment_ / 2.0);
}

else // Fallback to the old grace spacing: half that of the shortest note
ret = Spring (options->
get_duration_space (options->global_shortest_) / 2.0,
options->increment_ / 2.0);
}

return dist;
return ret;
}

2 changes: 1 addition & 1 deletion lily/spacing-determine-loose-columns.cc
Expand Up @@ -155,7 +155,7 @@ Spacing_spanner::set_distances_for_loose_col (Grob *me, Grob *c,
The note spacing should be taken from the musical
columns.
*/
Real base = note_spacing (me, lc, rc, options);
Spring base = note_spacing (me, lc, rc, options);
Spring spring = Note_spacing::get_spacing (sp, rc, base, options->increment_);

dists[d] = max (dists[d], spring.min_distance ());
Expand Down
19 changes: 7 additions & 12 deletions lily/spacing-loose-columns.cc
Expand Up @@ -153,19 +153,14 @@ set_loose_columns (System *which, Column_x_positions const *posns)
if (Paper_column::is_musical (next_col)
&& Paper_column::is_musical (loose_col))
{
Real base = Spacing_spanner::note_spacing (spacing, loose_col, next_col,
&options);
Spring spring = Spacing_spanner::note_spacing (spacing, loose_col,
next_col, &options);
if (Note_spacing::has_interface (spacing))
{
Spring spring = Note_spacing::get_spacing (spacing, next_col, base, options.increment_);;
base_note_space = spring.distance ();
tight_note_space = spring.min_distance ();
}
else
{
base_note_space = base;
tight_note_space = base;
}
spring = Note_spacing::get_spacing (spacing, next_col,
spring, options.increment_);

base_note_space = spring.distance ();
tight_note_space = spring.min_distance ();
}
else
{
Expand Down
11 changes: 4 additions & 7 deletions lily/spacing-options.cc
Expand Up @@ -66,9 +66,9 @@ Spacing_options::Spacing_options ()
Real
Spacing_options::get_duration_space (Rational d) const
{
Real k = shortest_duration_space_;
Real ratio = d / global_shortest_;

if (d < global_shortest_)
if (ratio < 1.0)
{
/*
We don't space really short notes using the log of the
Expand All @@ -86,9 +86,8 @@ Spacing_options::get_duration_space (Rational d) const


*/
Rational ratio = d / global_shortest_;

return ((k - 1) + double (ratio)) * increment_;
return (shortest_duration_space_ + ratio - 1) * increment_;
}
else
{
Expand All @@ -97,10 +96,8 @@ Spacing_options::get_duration_space (Rational d) const
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;

return (log_2 (d) + k) * increment_;
return (shortest_duration_space_ + log_2 (ratio)) * increment_;
}
}

26 changes: 8 additions & 18 deletions lily/spacing-spanner.cc
Expand Up @@ -315,11 +315,13 @@ Spacing_spanner::musical_column_spacing (Grob *me,
Item *right_col,
Spacing_options const *options)
{
Real base_note_space = note_spacing (me, left_col, right_col, options);
Spring spring;
Spring spring = note_spacing (me, left_col, right_col, options);

if (options->stretch_uniformly_)
spring = Spring (base_note_space, 0.0);
{
spring.set_min_distance (0.0);
spring.set_default_strength ();
}
else
{
vector<Spring> springs;
Expand Down Expand Up @@ -359,32 +361,20 @@ Spacing_spanner::musical_column_spacing (Grob *me,
grace_opts.init_from_grob (gsp);
inc = grace_opts.increment_;
}
springs.push_back (Note_spacing::get_spacing (wish, right_col, base_note_space, inc));
springs.push_back (Note_spacing::get_spacing (wish, right_col, spring, inc));
}
}

if (springs.empty ())
{

if (!Paper_column::is_musical (right_col))
{
/*
There used to be code that examined left_col->extent
(X_AXIS), but this is resulted in unexpected wide
spacing, because the width of s^"text" output is also
taken into account here.
*/
spring = Spring (max (base_note_space, options->increment_),
options->increment_);
}
else
if (Paper_column::is_musical (right_col))
{
/*
Min distance should be 0.0. If there are no spacing
wishes, we're probably dealing with polyphonic spacing
of hemiolas.
*/
spring = Spring (base_note_space, 0.0);
spring.set_min_distance (0.0);
}
}
else
Expand Down