From: Mike Solomon Date: Tue, 2 Apr 2013 20:05:04 +0000 (+0200) Subject: Aligns horizontally-offset fingerings in a column if X distance is small (issue 3269) X-Git-Tag: release/2.17.16-1~38 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=02b8e806dc39fefa22147e75c2b71fd97780610e;p=lilypond.git Aligns horizontally-offset fingerings in a column if X distance is small (issue 3269) Uses a new property snap-radius to "snap" fingerings into alignment if they look like they naturally belong in a column. --- diff --git a/input/regression/fingering-column-snap-radius.ly b/input/regression/fingering-column-snap-radius.ly new file mode 100644 index 0000000000..bebd1a1b9c --- /dev/null +++ b/input/regression/fingering-column-snap-radius.ly @@ -0,0 +1,13 @@ +\version "2.17.15" + +\header { + texidoc = "Horizontally-offset @code{Fingerings} align along the Y axis when +they are within @code{FingeringColumn.snap-radius} of each other. +" +} + +\relative f'' { + \set fingeringOrientations = #'(left) + 4 + 4 +} diff --git a/lily/fingering-column.cc b/lily/fingering-column.cc index 1cc6c12b11..62d7d08db1 100644 --- a/lily/fingering-column.cc +++ b/lily/fingering-column.cc @@ -17,6 +17,7 @@ along with LilyPond. If not, see . */ +#include "directional-element-interface.hh" #include "grob.hh" #include "fingering-column.hh" #include "pointer-group-interface.hh" @@ -24,6 +25,26 @@ #include "item.hh" #include "paper-column.hh" +#define EPS 1e-5 + +struct Fingering_and_offset +{ + Grob *fingering_; + Real offset_; + Fingering_and_offset (Grob *fingering, Real offset); +}; + +Fingering_and_offset::Fingering_and_offset (Grob *fingering, Real offset) : + fingering_ (fingering), offset_ (offset) +{ +} + +bool +fingering_and_offset_less (Fingering_and_offset fo0, Fingering_and_offset fo1) +{ + return fo0.offset_ < fo1.offset_; +} + MAKE_SCHEME_CALLBACK (Fingering_column, calc_positioning_done, 1); SCM Fingering_column::calc_positioning_done (SCM smob) @@ -34,12 +55,21 @@ Fingering_column::calc_positioning_done (SCM smob) me->set_property ("positioning-done", SCM_BOOL_T); + do_y_positioning (me); + do_x_positioning (me); + + return SCM_BOOL_T; +} + +void +Fingering_column::do_y_positioning (Grob *me) +{ extract_grob_set (me, "fingerings", const_fingerings); if (const_fingerings.size () < 2) { me->programming_error ("This FingeringColumn should have never been created."); - return SCM_BOOL_T; + return; } vector fingerings; @@ -86,8 +116,40 @@ Fingering_column::calc_positioning_done (SCM smob) for (vsize i = 0; i < fingerings.size (); i++) fingerings[i]->translate_axis(shift[i], Y_AXIS); +} + +void +Fingering_column::do_x_positioning (Grob *me) +{ + extract_grob_set (me, "fingerings", fingerings); + if (!fingerings.size ()) + return; + + Grob *common_x = common_refpoint_of_array (fingerings, me, X_AXIS); + + Real snap = robust_scm2double (me->get_property ("snap-radius"), 0.3); + vector fos; + + for (vsize i = 0; i < fingerings.size (); i++) + fos.push_back (Fingering_and_offset (fingerings[i], fingerings[i]->relative_coordinate (common_x, X_AXIS))); + + vector_sort (fos, fingering_and_offset_less); + Direction dir = get_grob_direction (fingerings[0]); + if (dir == RIGHT) + reverse (fos); + + Real prev = infinity_f * dir; + for (vsize i = 0; i < fos.size (); i++) + { + if ((fabs (fos[i].offset_ - prev) < snap) + && (fabs (fos[i].offset_ - prev) > EPS)) + fos[i].offset_ = prev; + + prev = fos[i].offset_; + } - return SCM_BOOL_T; + for (vsize i = 0; i < fos.size (); i++) + fos[i].fingering_->translate_axis (fos[i].offset_ - fos[i].fingering_->relative_coordinate (common_x, X_AXIS), X_AXIS); } void @@ -100,9 +162,11 @@ Fingering_column::add_fingering (Grob *fc, Grob *f) ADD_INTERFACE (Fingering_column, "Makes sure that fingerings placed laterally" - " do not collide.", + " do not collide and that they are flush if" + " necessary.", /* properties */ "padding " "positioning-done " + "snap-radius " ); diff --git a/lily/include/fingering-column.hh b/lily/include/fingering-column.hh index 6d6bef2376..5052322f12 100644 --- a/lily/include/fingering-column.hh +++ b/lily/include/fingering-column.hh @@ -29,6 +29,8 @@ struct Fingering_column static void add_fingering (Grob *, Grob *); DECLARE_SCHEME_CALLBACK (calc_positioning_done, (SCM)); DECLARE_GROB_INTERFACE (); + static void do_x_positioning (Grob *me); + static void do_y_positioning (Grob *me); }; #endif /* FINGERING_COLUMN_HH */ diff --git a/scm/define-grob-properties.scm b/scm/define-grob-properties.scm index 9afb49a0a3..4c5c404dc7 100644 --- a/scm/define-grob-properties.scm +++ b/scm/define-grob-properties.scm @@ -830,6 +830,8 @@ slashes in percent repeat glyphs. Larger values bring the two elements closer together.") (slope ,number? "The slope of this object.") (slur-padding ,number? "Extra distance between slur and script.") + (snap-radius ,number? "The maximum distance between two objects that +will cause them to snap to alignment along an axis.") (space-alist ,list? "A table that specifies distances between prefatory items, like clef and time-signature. The format is an alist of spacing tuples: @code{(@var{break-align-symbol} @var{type} diff --git a/scm/define-grobs.scm b/scm/define-grobs.scm index 19a767fba5..e825cb1ef0 100644 --- a/scm/define-grobs.scm +++ b/scm/define-grobs.scm @@ -932,6 +932,7 @@ . ( (padding . 0.2) (positioning-done . ,ly:fingering-column::calc-positioning-done) + (snap-radius . 0.3) (meta . ((class . Item) (interfaces . (fingering-column-interface))))))