\header{
- texidoc = "Concurrent tuplets should be equidistant on all staves."
+ 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}."
}
-\paper {ragged-right = ##f }
+\layout{
+ \context{
+ \Score
+ \override SpacingSpanner.uniform-stretching = ##t
+ }
+}
\relative c' {
\context StaffGroup <<
\new Staff \context Voice {
- \tuplet 10/8 { c8[ c c c c c c c c c] }
+ \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] }
}
\new Staff \context Voice {
- \tuplet 8/8 { c8[ c c c c c c c] }
+ \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] }
}
>>
}
public:
DECLARE_GROB_INTERFACE ();
- static Spring get_spacing (Grob *me, Item *, Spring, Real);
+ static Spring get_spacing (Grob *me, Item *, Real, Real);
static void stem_dir_correction (Grob *me, Item *next_col, Real incr,
Real *, Real *);
};
static bool fills_measure (Grob *, Item *, Item *);
public:
static vector<Grob *> get_columns (Grob *me);
- static Spring note_spacing (Grob *, Grob *, Grob *, Spacing_options const *);
+ static Real 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));
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,
- Spring base, Real increment)
+ Real base_space, Real increment)
{
vector<Item *> note_columns = Spacing_interface::left_note_columns (me);
Real left_head_end = 0;
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 = (ideal + min_dist) / 2;
- base.set_min_distance (min_dist);
+ Real min_desired_space = left_head_end + (min_dist - left_head_end + base_space - increment) / 2;
+ Real ideal = base_space - increment + left_head_end;
/* 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. */
ideal = max (ideal, min_desired_space);
stem_dir_correction (me, right_col, increment, &ideal, &min_desired_space);
- base.set_distance (max (0.0, ideal));
- base.set_inverse_compress_strength (max (0.0, ideal - min_desired_space));
- return base;
+ /* 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;
}
static Real
return 0;
}
-/* Basic spring based on duration alone */
-Spring
+Real
Spacing_spanner::note_spacing (Grob * /* me */,
Grob *lc,
Grob *rc,
shortest_playing_len = min (shortest_playing_len, *measure_len);
}
- Spring ret;
+ Real dist = 0.0;
if (delta_t.main_part_ && !lwhen.grace_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)));
+ dist = options->get_duration_space (shortest_playing_len.main_part_);
+ dist *= double (delta_t.main_part_ / shortest_playing_len.main_part_);
}
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);
- 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);
+ dist = grace_opts.get_duration_space (delta_t.grace_part_);
}
- 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 ret;
+ return dist;
}
The note spacing should be taken from the musical
columns.
*/
- Spring base = note_spacing (me, lc, rc, options);
+ Real 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 ());
if (Paper_column::is_musical (next_col)
&& Paper_column::is_musical (loose_col))
{
- Spring spring = Spacing_spanner::note_spacing (spacing, loose_col,
- next_col, &options);
+ Real base = Spacing_spanner::note_spacing (spacing, loose_col, next_col,
+ &options);
if (Note_spacing::has_interface (spacing))
- spring = Note_spacing::get_spacing (spacing, next_col,
- spring, options.increment_);
-
- base_note_space = spring.distance ();
- tight_note_space = spring.min_distance ();
+ {
+ 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;
+ }
}
else
{
Item *right_col,
Spacing_options const *options)
{
- Spring spring = note_spacing (me, left_col, right_col, options);
+ Real base_note_space = note_spacing (me, left_col, right_col, options);
+ Spring spring;
if (options->stretch_uniformly_)
- {
- spring.set_min_distance (0.0);
- spring.set_default_strength ();
- }
+ spring = Spring (base_note_space, 0.0);
else
{
vector<Spring> springs;
grace_opts.init_from_grob (gsp);
inc = grace_opts.increment_;
}
- springs.push_back (Note_spacing::get_spacing (wish, right_col, spring, inc));
+ springs.push_back (Note_spacing::get_spacing (wish, right_col, base_note_space, inc));
}
}
if (springs.empty ())
{
- if (Paper_column::is_musical (right_col))
+
+ 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
{
/*
Min distance should be 0.0. If there are no spacing
wishes, we're probably dealing with polyphonic spacing
of hemiolas.
*/
- spring.set_min_distance (0.0);
+ spring = Spring (base_note_space, 0.0);
}
}
else