From: Janek WarchoĊ‚ Date: Wed, 27 Mar 2013 16:20:03 +0000 (+0100) Subject: Issue 2245: always align dynamics and lyrics on "main" notehead X-Git-Tag: release/2.19.10-1~13 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;ds=sidebyside;h=59a842eba0f7ad78289a58a7dfa8fa786cdf11ed;p=lilypond.git Issue 2245: always align dynamics and lyrics on "main" notehead Until now, LyricTexts and DynamicTexts had their X-parents set to the first NoteHead in the NoteColumn. This resulted in inconsistent alignment - placement of lyrics and dynamics depended on the order of notes in the input: % this was aligned differently { 1\p \p } \addlyrics { la la } By using NoteColumns themselves as the X-parents, we make sure that the input order won't matter. Since the NoteColumn contains all NoteHeads (including suspended ones, which usually should be ignored when aligning), as well as Flags and some other objects, we cannot use its X-extent directly - instead, we add a function for calculating X-extent of the "main" part of the NoteColumn, i.e. X-extent of the non-suspended NoteHeads (represented by the NoteHead furthest away from the stem). --- diff --git a/input/regression/input-order-alignment.ly b/input/regression/input-order-alignment.ly new file mode 100644 index 0000000000..cabb357364 --- /dev/null +++ b/input/regression/input-order-alignment.ly @@ -0,0 +1,25 @@ +\version "2.19.9" + +\header { + texidoc = "Alignment of lyrics, dynamics, textscripts and articulations +attached to chords with suspended notes doesn't depend on input order. +All these items are aligned on the \"main\" notehead (the one at the +end of the stem)." +} + +<< + \new Staff { + 2 s + \f s + ^"Text" s + -! s + } + \addlyrics { blah } + \new Staff { + 2 s + \f s + ^"Text" s + -! s + } + \addlyrics { blah } +>> diff --git a/lily/dynamic-engraver.cc b/lily/dynamic-engraver.cc index a91d742ee8..fdf682f773 100644 --- a/lily/dynamic-engraver.cc +++ b/lily/dynamic-engraver.cc @@ -261,11 +261,11 @@ Dynamic_engraver::acknowledge_note_column (Grob_info info) { extract_grob_set (info.grob (), "note-heads", heads); /* - Spacing constraints may require dynamics to be aligned on rests, + Spacing constraints may require dynamics to be attached to rests, so check for a rest if this note column has no note heads. */ Grob *x_parent = (heads.size () - ? heads[0] + ? info.grob () : unsmob_grob (info.grob ()->get_object ("rest"))); if (x_parent) script_->set_parent (x_parent, X_AXIS); diff --git a/lily/include/note-column.hh b/lily/include/note-column.hh index 151d9208ad..9fdabd2962 100644 --- a/lily/include/note-column.hh +++ b/lily/include/note-column.hh @@ -36,6 +36,7 @@ public: static Grob *accidentals (Grob *me); static Slice head_positions_interval (Grob *me); static Grob *first_head (Grob *me); + static Interval calc_main_heads_extent (Grob *me); static Grob *get_rest (Grob *me); static void set_stem (Grob *me, Grob *); static void add_head (Grob *me, Grob *); diff --git a/lily/lyric-engraver.cc b/lily/lyric-engraver.cc index 3ea4498baf..1cbaffeb7d 100644 --- a/lily/lyric-engraver.cc +++ b/lily/lyric-engraver.cc @@ -175,7 +175,7 @@ Lyric_engraver::stop_translation_timestep () if (head) { - text_->set_parent (head, X_AXIS); + text_->set_parent (head->get_parent(X_AXIS), X_AXIS); if (melisma_busy (voice) && !to_boolean (get_property ("ignoreMelismata"))) text_->set_property ("self-alignment-X", diff --git a/lily/note-column.cc b/lily/note-column.cc index 867542bdbd..625bed1b2f 100644 --- a/lily/note-column.cc +++ b/lily/note-column.cc @@ -156,6 +156,26 @@ Note_column::first_head (Grob *me) return st ? Stem::first_head (st) : 0; } +/* + Return extent of the noteheads in the "main column", + i.e. excluding any suspended noteheads. +*/ +Interval +Note_column::calc_main_heads_extent (Grob *me) +{ + if (get_stem (me)) + return first_head (me)->extent (me, X_AXIS); + else + { + // no stems => no suspended noteheads. + extract_grob_set (me, "note-heads", heads); + if (heads.size()) + return heads[0]->extent (me, X_AXIS); + else + return Interval (0, 0); + } +} + /* Return the first AccidentalPlacement grob that we find in a note-head. */ diff --git a/lily/self-alignment-interface.cc b/lily/self-alignment-interface.cc index d1cb1bf50c..664a111642 100644 --- a/lily/self-alignment-interface.cc +++ b/lily/self-alignment-interface.cc @@ -114,7 +114,13 @@ Self_alignment_interface::aligned_on_parent (Grob *me, Axis a) he = Paper_column::get_interface_extent (him, ly_symbol2scm ("note-column-interface"), a); else - he = him->extent (him, a); + { + if (ly_scm2bool(me->internal_get_property (ly_symbol2scm ("X-align-on-main-noteheads"))) + && Note_column::has_interface (him)) + he = Note_column::calc_main_heads_extent(him); + else + he = him->extent (him, a); + } SCM sym = (a == X_AXIS) ? ly_symbol2scm ("self-alignment-X") : ly_symbol2scm ("self-alignment-Y"); @@ -169,4 +175,5 @@ ADD_INTERFACE (Self_alignment_interface, /* properties */ "self-alignment-X " "self-alignment-Y " + "X-align-on-main-noteheads " ); diff --git a/scm/define-grob-properties.scm b/scm/define-grob-properties.scm index 24e8e3298a..fbb9d679ac 100644 --- a/scm/define-grob-properties.scm +++ b/scm/define-grob-properties.scm @@ -1023,6 +1023,8 @@ texts.") ;;; ;;; x ;;; + (X-align-on-main-noteheads ,boolean? "If true, this grob will +ignore suspended noteheads when aligning itself on NoteColumn.") (X-extent ,number-pair? "Extent (size) in the X@tie{}direction, measured in staff-space units, relative to object's reference point.") (X-offset ,number? "The horizontal amount that this object is diff --git a/scm/define-grobs.scm b/scm/define-grobs.scm index ddacbcb7ec..572f80f660 100644 --- a/scm/define-grobs.scm +++ b/scm/define-grobs.scm @@ -843,6 +843,7 @@ (stencil . ,ly:text-interface::print) (vertical-skylines . ,grob::always-vertical-skylines-from-stencil) (Y-extent . ,grob::always-Y-extent-from-stencil) + (X-align-on-main-noteheads . #t) (X-offset . ,ly:self-alignment-interface::aligned-on-x-parent) (Y-offset . ,(scale-by-font-size -0.6)) ; center on an 'm' (meta . ((class . Item) @@ -1397,6 +1398,7 @@ (word-space . 0.6) (skyline-horizontal-padding . 0.1) (vertical-skylines . ,grob::always-vertical-skylines-from-stencil) + (X-align-on-main-noteheads . #t) (X-offset . ,ly:self-alignment-interface::aligned-on-x-parent) (Y-extent . ,grob::always-Y-extent-from-stencil) (meta . ((class . Item)