2016-12-07 1:07 GMT+01:00 Alexander Kobel <address@hidden>:
Hi all,
yet another semi-feature request where I'm running out of knowledge...
I happily used LSR 888 (center lyrics without taking punctuation into
account) for years and only now found out that the alignment is off under
certain circumstances: The default algorithm seems to align lyrics on the
center of the note*head* of the associated voice. Which seems the right
thing to do. However, center-on-words aligns on the center of the *entire
note* - in particular, this yields different results on quavers with stems
up and "outward flags". At least, neither dots nor accidentals are taken
into account...
Even more ugly, the alignment is totally off on chords with two adjacent
notes (shifting one note). I know that this should be a forbidden situation
for vocal music, but sometimes there is a reason for writing such chords
instead of two separate voices (e.g., soprano and alto notated on a common
staff in a homorhythmic piece, with one of the voices splitting for a
cluster on just a few notes).
In such a rare case, I do not like the default algorithm's choices either
(and I'd prefer alignment on the center of the noteheads of the chord); but
center-on-words does even /way/ worse.
I attach a "test case" (including a full copy of the core of
http://lsr.di.unimi.it/LSR/Snippet?id=888), where one would expect
center-on-words to do exactly nothing, but you can notice the slight offsets
on the "nonius scale" of lyrics.
Anyone got an idea where to start to fix that? I think one would have to
figure how to get the note-column-extent without flags; but I have no clue
how to approach that.
Thanks in advance,
Alexander
Hi,
how about below?
You need a devel-version, though. Please test thoroughly. I'm too
tired to do more than the included examples.
\version "2.19.52" %% sic !!
%% http://lsr.di.unimi.it/LSR/Item?id=888
#(define space-set
(list->char-set
(string->list "—.?-;,:“†‘’–— */()[]{}|<>!`~&…")))
#(define (width grob text)
(let* ((X-extent
(ly:stencil-extent (grob-interpret-markup grob text) X)))
(if (interval-empty? X-extent)
0
(cdr X-extent))))
#(define (remove-suspended-note-heads stem note-heads)
(let* ((nc (ly:grob-common-refpoint stem (car note-heads) X))
(stem-coord
(ly:grob-relative-coordinate stem stem X))
(half-stem-thick
(/ (ly:grob-property stem 'thickness) 2))
(stem-dir (ly:grob-property stem 'direction)))
(remove
(lambda (nh)
(if (positive? stem-dir)
(> (ly:grob-relative-coordinate nh nc X)
stem-coord)
(< (ly:grob-relative-coordinate nh nc X)
(- stem-coord half-stem-thick))))
note-heads)))
#(define (center-on-word grob)
(let* ((text (ly:grob-property-data grob 'text))
(syllable (markup->string text))
(word-position
(if (string-skip syllable space-set)
(string-skip syllable space-set)
0))
(word-end
(if (string-skip-right syllable space-set)
(+ (string-skip-right syllable space-set) 1)
(string-length syllable)))
(preword (substring syllable 0 word-position))
(word (substring syllable word-position word-end))
(preword-width (width grob preword))
(word-width (width grob (if (string-null? syllable) text word)))
(note-column (ly:grob-parent grob X))
(stem (ly:grob-object note-column 'stem))
(stem-dir (ly:grob-property stem 'direction))
(sys (ly:grob-system grob))
(nh-ls
(if (ly:grob-array? (ly:grob-object note-column 'note-heads))
(ly:grob-array->list (ly:grob-object note-column 'note-heads))
'()))
(note-column-width
(interval-length
(ly:relative-group-extent
(remove-suspended-note-heads stem nh-ls) note-column X))))
(-
(*
(/ (- note-column-width word-width) 2)
(1+ (ly:grob-property-data grob 'self-alignment-X)))
preword-width)))
%%%%%%%%%%%%%%%%%%%%%%
%% EXAMPLES
%%%%%%%%%%%%%%%%%%%%%%
\layout {
\context {
\Lyrics
\override LyricText.X-offset = #center-on-word
}
}
<<
\new Voice { \voiceOne c''8 }
\addlyrics { word }
\new Voice { c''8 }
\addlyrics { ,,,word }
\new Voice { \voiceOne <c'' d''>8 }
\addlyrics { word!!! }
\new Voice { <c'' d''>8 }
\addlyrics { word }
Cheers,
Harm