/*
This file is part of LilyPond, the GNU music typesetter.
- Copyright (C) 2001--2011 Han-Wen Nienhuys <hanwen@xs4all.nl>
+ Copyright (C) 2001--2015 Han-Wen Nienhuys <hanwen@xs4all.nl>
LilyPond is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#include "separation-item.hh"
#include "spacing-interface.hh"
#include "staff-spacing.hh"
+#include "staff-symbol-referencer.hh"
#include "stem.hh"
#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;
for (vsize i = 0; i < note_columns.size (); i++)
{
SCM r = note_columns[i]->get_object ("rest");
- Grob *g = unsmob_grob (r);
+ Grob *g = unsmob<Grob> (r);
Grob *col = note_columns[i]->get_column ();
if (!g)
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]);
+ 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. */
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
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;
Interval bar_xextent;
Interval bar_yextent;
- Direction d = LEFT;
-
bool acc_right = false;
Grob *bar = Spacing_interface::extremal_break_aligned_grob (me, RIGHT,
if (bar && dynamic_cast<Item *> (bar)->get_column () == rcolumn)
bar_yextent = Staff_spacing::bar_y_positions (bar);
- do
+ for (LEFT_and_RIGHT (d))
{
vector<Grob *> const &items (ly_scm2link_array (props [d]));
for (vsize i = 0; i < items.size (); i++)
{
Item *it = dynamic_cast<Item *> (items[i]);
- if (!Note_column::has_interface (it))
+ if (!has_interface<Note_column> (it))
continue;
if (d == RIGHT && it->get_column () != rcolumn)
continue;
Interval hp = Stem::head_positions (stem);
if (!hp.is_empty ())
{
- Real chord_start = hp[stem_dir];
-
- /*
- can't look at stem-end-position, since that triggers
- beam slope computations.
- */
- Real stem_end = hp[stem_dir]
- + stem_dir * robust_scm2double (stem->get_property ("length"), 7);
-
- stem_posns[d] = Interval (min (chord_start, stem_end),
- max (chord_start, stem_end));
+ Real ss = Staff_symbol_referencer::staff_space (stem);
+ stem_posns[d] = stem->pure_y_extent (stem, 0, INT_MAX) * (2 / ss);
head_posns[d].unite (hp);
}
}
}
- while (flip (&d) != LEFT);
Real correction = 0.0;
if (beams_drul[LEFT] && beams_drul[LEFT] == beams_drul[RIGHT])
{
correction = knee_correction (me, stems_drul[RIGHT], increment);
- *fixed += correction;
}
else
{