From b99bd638674b599f0ead29470b954e90d0d74e4a Mon Sep 17 00:00:00 2001 From: Mike Solomon Date: Sat, 26 Jan 2013 08:06:04 +0100 Subject: [PATCH] Brings accidentals closer to chords on average. Does this by giving placement priority to columns of multiple accidentals. See accidental-grouping.ly. Also allows Accidental_placement to be controlled at the voice level via the accidentalGrouping property instead of necessitating a change of context for the Accidental_engraver. --- input/regression/accidental-grouping.ly | 16 +++++++ lily/accidental-engraver.cc | 7 ++- lily/accidental-placement.cc | 57 ++++++++++++++++++------- lily/ambitus-engraver.cc | 2 +- lily/include/accidental-placement.hh | 2 +- scm/define-context-properties.scm | 3 ++ 6 files changed, 68 insertions(+), 19 deletions(-) create mode 100644 input/regression/accidental-grouping.ly diff --git a/input/regression/accidental-grouping.ly b/input/regression/accidental-grouping.ly new file mode 100644 index 0000000000..b8cfce4fbc --- /dev/null +++ b/input/regression/accidental-grouping.ly @@ -0,0 +1,16 @@ +\version "2.17.10" + +\header { + texidoc = "By setting @code{accidentalGrouping} to @code{'voice}, +LilyPond will horizontally stagger the accidentals of octaves +in different voices as seen in this test's E-sharp. +" +} + + \relative c''' { + << { 1 } \\ + { eis, } >> + \set Staff . accidentalGrouping = #'voice + << { 1 } \\ + { eis, } >> +} diff --git a/lily/accidental-engraver.cc b/lily/accidental-engraver.cc index 12b9072238..ac525d27de 100644 --- a/lily/accidental-engraver.cc +++ b/lily/accidental-engraver.cc @@ -329,7 +329,11 @@ Accidental_engraver::make_standard_accidental (Stream_event * /* note */, if (!accidental_placement_) accidental_placement_ = make_item ("AccidentalPlacement", a->self_scm ()); - Accidental_placement::add_accidental (accidental_placement_, a); + + Accidental_placement::add_accidental + (accidental_placement_, a, + get_property ("accidentalGrouping") == ly_symbol2scm ("voice"), + (long) trans); note_head->set_object ("accidental-grob", a->self_scm ()); @@ -525,6 +529,7 @@ ADD_TRANSLATOR (Accidental_engraver, "internalBarNumber " "extraNatural " "harmonicAccidentals " + "accidentalGrouping " "keySignature " "localKeySignature ", diff --git a/lily/accidental-placement.cc b/lily/accidental-placement.cc index 169fe39fdd..1f2a943045 100644 --- a/lily/accidental-placement.cc +++ b/lily/accidental-placement.cc @@ -47,7 +47,7 @@ accidental_pitch (Grob *acc) } void -Accidental_placement::add_accidental (Grob *me, Grob *a) +Accidental_placement::add_accidental (Grob *me, Grob *a, bool stagger, long context_hash) { Pitch *p = accidental_pitch (a); if (!p) @@ -55,11 +55,12 @@ Accidental_placement::add_accidental (Grob *me, Grob *a) a->set_parent (me, X_AXIS); a->set_property ("X-offset", Grob::x_parent_positioning_proc); - int n = p->get_notename (); + long n = p->get_notename (); SCM accs = me->get_object ("accidental-grobs"); - SCM key = scm_from_int (n); - SCM entry = scm_assq (key, accs); + SCM key = scm_cons (scm_from_int (n), scm_from_long (stagger ? context_hash : 1)); + // assoc because we're dealing with pairs + SCM entry = scm_assoc (key, accs); if (entry == SCM_BOOL_F) entry = SCM_EOL; else @@ -67,7 +68,7 @@ Accidental_placement::add_accidental (Grob *me, Grob *a) entry = scm_cons (a->self_scm (), entry); - accs = scm_assq_set_x (accs, key, entry); + accs = scm_assoc_set_x (accs, key, entry); me->set_object ("accidental-grobs", accs); } @@ -129,6 +130,11 @@ Real ape_priority (Accidental_placement_entry const *a) bool ape_less (Accidental_placement_entry *const &a, Accidental_placement_entry *const &b) { + vsize size_a = a->grobs_.size (); + vsize size_b = b->grobs_.size (); + if (size_a != size_b) + return size_b < size_a; + return ape_priority (a) < ape_priority (b); } @@ -181,23 +187,42 @@ stagger_apes (vector *apes) vector asc = *apes; vector_sort (asc, &ape_less); + // we do the staggering below based on size + // this ensures that if a placement has 4 entries, it will + // always be closer to the NoteColumn than a placement with 1 + // this allows accidentals to be on-average closer to notes + // while still preserving octave alignment + vector > ascs; + + vsize sz = INT_MAX; + for (vsize i = 0; i < asc.size (); i++) + { + vsize my_sz = asc[i]->grobs_.size (); + if (sz != my_sz) + ascs.push_back (vector ()); + ascs.back ().push_back (asc[i]); + sz = my_sz; + } apes->clear (); - int parity = 1; - for (vsize i = 0; i < asc.size ();) + for (vsize i = 0; i < ascs.size (); i++) { - Accidental_placement_entry *a = 0; - if (parity) + int parity = 1; + for (vsize j = 0; j < ascs[i].size ();) { - a = asc.back (); - asc.pop_back (); - } - else - a = asc[i++]; + Accidental_placement_entry *a = 0; + if (parity) + { + a = ascs[i].back (); + ascs[i].pop_back (); + } + else + a = ascs[i][j++]; - apes->push_back (a); - parity = !parity; + apes->push_back (a); + parity = !parity; + } } reverse (*apes); diff --git a/lily/ambitus-engraver.cc b/lily/ambitus-engraver.cc index 92fee10a50..99d3f8a335 100644 --- a/lily/ambitus-engraver.cc +++ b/lily/ambitus-engraver.cc @@ -197,7 +197,7 @@ Ambitus_engraver::finalize () Separation_item::add_conditional_item (heads_[d], accidental_placement); Accidental_placement::add_accidental (accidental_placement, - accidentals_[d]); + accidentals_[d], false, 0); Pointer_group_interface::add_grob (ambitus_, ly_symbol2scm ("note-heads"), heads_[d]); diff --git a/lily/include/accidental-placement.hh b/lily/include/accidental-placement.hh index fa0902e1ae..08ba1e163f 100644 --- a/lily/include/accidental-placement.hh +++ b/lily/include/accidental-placement.hh @@ -27,7 +27,7 @@ class Accidental_placement { public: DECLARE_SCHEME_CALLBACK (alignment_callback, (SCM element)); - static void add_accidental (Grob *, Grob *); + static void add_accidental (Grob *, Grob *, bool, long); static vector get_relevant_accidentals (vector const &elts, Grob *left); static void split_accidentals (Grob *accs, diff --git a/scm/define-context-properties.scm b/scm/define-context-properties.scm index f58237a708..e9239fc65f 100644 --- a/scm/define-context-properties.scm +++ b/scm/define-context-properties.scm @@ -44,6 +44,9 @@ ;; TODO FIXME + (accidentalGrouping ,symbol? "If set to @code{'voice}, accidentals +on the same note in different octaves may be horizontally staggered +if in different voices.") (aDueText ,markup? "Text to print at a unisono passage.") (additionalPitchPrefix ,string? "Text with which to prefix additional pitches within a chord name.") -- 2.39.2