Hi everybody!

Please test and comment, patch and examples attached.

Cheers,
 Knut

>From 456cee254df6133a611f108d2e9ca3671b01886f Mon Sep 17 00:00:00 2001
From: Knut Petersen <knut_peter...@t-online.de>
Date: Mon, 12 Dec 2016 13:13:13 +0100
Subject: [PATCH] Enhance and clean lyric-extender.cc, add force-extender
 property

Allow exteners to be forced even after single notes, automatically
kill extenders that are not needed. Also removed some dead and
unnecessary code.

Signed-off-by: Knut Petersen <knut_peter...@t-online.de>
---
 lily/lyric-extender.cc         | 39 +++++++++++++++++++--------------------
 scm/define-grob-properties.scm |  4 ++++
 scm/define-grobs.scm           |  1 +
 3 files changed, 24 insertions(+), 20 deletions(-)

diff --git a/lily/lyric-extender.cc b/lily/lyric-extender.cc
index 8afe2c5569..6fd70b7c7b 100644
--- a/lily/lyric-extender.cc
+++ b/lily/lyric-extender.cc
@@ -45,51 +45,49 @@ Lyric_extender::print (SCM smob)
   common = common->common_refpoint (me->get_system (), X_AXIS);
 
   Real sl = me->layout ()->get_dimension (ly_symbol2scm ("line-thickness"));
+  bool at_start_of_line = !left_edge->internal_has_interface (ly_symbol2scm ("lyric-syllable-interface"));
+  bool at_end_of_line = me->get_bound (RIGHT)->break_status_dir ();
+  bool force_extender = to_boolean (me->get_property ("force-extender"));
 
   extract_grob_set (me, "heads", heads);
 
-  if (!heads.size ())
+  if (!heads.size () || (!force_extender && !at_start_of_line && !at_end_of_line && heads.size () < 2))
     return SCM_EOL;
 
   common = common_refpoint_of_array (heads, common, X_AXIS);
 
   Real left_point = 0.0;
-  if (left_edge->internal_has_interface (ly_symbol2scm ("lyric-syllable-interface")))
+  if (!at_start_of_line)
     left_point = left_edge->extent (common, X_AXIS)[RIGHT];
-  else if (heads.size ())
-    left_point = heads[0]->extent (common, X_AXIS)[LEFT];
   else
-    left_point = left_edge->extent (common, X_AXIS)[RIGHT];
+    left_point = heads[0]->extent (common, X_AXIS)[LEFT];
 
   if (isinf (left_point))
     return SCM_EOL;
 
-  /* It seems that short extenders are even lengthened to go past the
-     note head, but haven't found a pattern in it yet. --hwn 1/1/04  */
-  SCM minlen = me->get_property ("minimum-length");
-  Real right_point
-    = left_point + (robust_scm2double (minlen, 0));
-
-  right_point = min (right_point, me->get_system ()->get_bound (RIGHT)->relative_coordinate (common, X_AXIS));
-
-  if (heads.size ())
-    right_point = max (right_point, heads.back ()->extent (common, X_AXIS)[RIGHT]);
-
   Real h = sl * robust_scm2double (me->get_property ("thickness"), 0);
   Drul_array<Real> paddings (robust_scm2double (me->get_property ("left-padding"), h),
                              robust_scm2double (me->get_property ("right-padding"), h));
 
+  Real minlen = robust_scm2double (me->get_property ("minimum-length"), 0);
+
+  Real right_point = heads.back ()->extent (common, X_AXIS)[RIGHT];
+
+  if (force_extender)
+    right_point = max (heads.back ()->extent (common, X_AXIS)[RIGHT], left_point + minlen);
+
   if (right_text)
     right_point = min (right_point, (robust_relative_extent (right_text, common, X_AXIS)[LEFT] - paddings[RIGHT]));
 
-  /* run to end of line. */
-  if (me->get_bound (RIGHT)->break_status_dir ())
+  if (at_end_of_line)
     right_point = max (right_point, (robust_relative_extent (me->get_bound (RIGHT), common, X_AXIS)[LEFT] - paddings[RIGHT]));
 
-  left_point += paddings[LEFT];
+  if (!at_start_of_line)
+    left_point += paddings[LEFT];
+
   Real w = right_point - left_point;
 
-  if (w < 1.5 * h)
+  if (w < minlen && !at_start_of_line && !at_end_of_line && !force_extender)
     return SCM_EOL;
 
   Stencil mol (Lookup::round_filled_box (Box (Interval (0, w),
@@ -111,4 +109,5 @@ ADD_INTERFACE (Lyric_extender,
                "next "
                "right-padding "
                "thickness "
+               "force-extender "
               );
diff --git a/scm/define-grob-properties.scm b/scm/define-grob-properties.scm
index c234792dd2..2ee4fe1ed6 100644
--- a/scm/define-grob-properties.scm
+++ b/scm/define-grob-properties.scm
@@ -330,6 +330,10 @@ allowed.")
      (footnote ,boolean? "Should this be a footnote or in-note?")
      (footnote-music ,ly:music? "Music creating a footnote.")
      (footnote-text ,markup? "A footnote for the grob.")
+     (force-extender ,boolean? "Force a lyric extender to be generated
+if none would be generated otherwise and/or force it to be at least as
+wide as indicated by minimum-width unless it would collide with the
+next syllable.")
      (force-hshift ,number? "This specifies a manual shift for notes
 in collisions.  The unit is the note head width of the first voice
 note.  This is used by @rinternals{note-collision-interface}.")
diff --git a/scm/define-grobs.scm b/scm/define-grobs.scm
index e36ea12bf2..b8abe332ac 100644
--- a/scm/define-grobs.scm
+++ b/scm/define-grobs.scm
@@ -1361,6 +1361,7 @@
 
     (LyricExtender
      . (
+        (force-extender . #f)
         (minimum-length . 1.5)
         (stencil . ,ly:lyric-extender::print)
         (thickness . 0.8) ; line-thickness
-- 
2.11.0

\version "2.19.53"

\pointAndClickOff

#(set-global-staff-size 17)

\paper { ragged-right = ##f }

\score { 
  <<
    \new Staff \relative c'' { 
      \time 2/1
      \repeat volta 2 {
        r4 g4 d'2. a4 bes2~
        bes  a2 g1~
      }
      \alternative{
       { g2 fis4 e fis1 d'1 c2 bes}
       { g\repeatTie fis4 e fis1 }
      }
      \bar "|."
    }
    \addlyrics {
       of Prin- ces all __ _ _ the __  _ flow’r. Who took a-
       %% volta 2
       \once \override Lyrics.LyricExtender.force-extender = ##t
       \tweak self-alignment-X #-4 \markup \null __ 
       the __ _ flow’r.
    }
  >>
}

Attachment: 1006.pdf
Description: Adobe PDF document

\version "2.19.53"

\paper { ragged-right = ##f }

\pointAndClickOff

#(set-global-staff-size 16)


#(define (has-hyphen? event)
   (let* ((art (ly:music-property event 'articulations))
          (is-hyphen? (lambda (ev) (eq? (ly:music-property ev 'name) 'HyphenEvent))))
      (find is-hyphen? art)))


#(define (add-extender! event)
   (ly:music-set-property! event 'articulations
     (append (ly:music-property event 'articulations) (list (make-music (quote ExtenderEvent)))))
   event)


add-lyric-extenders =
#(define-music-function (parser location lyrics) (ly:music?)
   (music-map
    (lambda (event)
      (if (and (eq? (ly:music-property event 'name) 'LyricEvent)
               (not (has-hyphen? event)))
          (add-extender! event))
      event)
    lyrics))

\markup { "no extenders"} 

<<
    { c''2. 4 ~ 4 2. ~ 2. 4 ~ \break 2. 4 2 ~ 2 \bar "|." }
    \addlyrics {  foo -- bar foo -- bar foo -- bar }
>>

\markup { "automatic extenders"} 

<<
    { c''2. 4 ~ 4 2. ~ 2. 4 ~ \break 2. 4 2 ~ 2 \bar "|." }
    \addlyrics { \add-lyric-extenders \repeat unfold 3 { foo -- bar }}
>>

<<
    { c''2. 4 ~ 4 2. ~ 2. 4 ~ \break 2. 4 1 \bar "|." }
    \addlyrics { \add-lyric-extenders \repeat unfold 3 { foo -- bar }}
>>

\markup { "automatic extenders, extender on last note forced"} 

<<
    { c''2. 4 ~ 4 2. ~ 2. 4 ~ \break 2. 4 1 \bar "|." }
    \addlyrics { \add-lyric-extenders { foo -- bar foo -- bar foo -- 
    \override Lyrics.LyricExtender.minimum-length = #30 
    \override Lyrics.LyricExtender.force-extender = ##t bar }}
>>

\markup { "automatic extenders, minimum-length 8 "} 
<<
    { c''1 2 ~ 2 2 4 ~ 4 4 8 ~ 8 8  16 ~ 16 4 1  \bar "|." }
    \addlyrics { \add-lyric-extenders { \override Lyrics.LyricExtender.minimum-length = #8
                 \repeat unfold 10 {  foo -- bar }}}
>>

\markup { "automatic extenders, minimum-length 4 "} 
<<
    { c''1 2 ~ 2 2 4 ~ 4 4 8 ~ 8 8  16 ~ 16 4 1  \bar "|." }
    \addlyrics { \add-lyric-extenders { \override Lyrics.LyricExtender.minimum-length = #4
                 \repeat unfold 10 {  foo -- bar }}}
>>

\markup { "automatic extenders, minimum-length 2 "} 
<<
    { c''1 2 ~ 2 2 4 ~ 4 4 8 ~ 8 8  16 ~ 16 4 1  \bar "|." }
    \addlyrics { \add-lyric-extenders { \override Lyrics.LyricExtender.minimum-length = #2
                 \repeat unfold 10 {  foo -- bar }}}
>>

\markup { "automatic extenders, minimum-length 1 "} 
<<
    { c''1 2 ~ 2 2 4 ~ 4 4 8 ~ 8 8  16 ~ 16 4 1  \bar "|." }
    \addlyrics { \add-lyric-extenders { \override Lyrics.LyricExtender.minimum-length = #1
                 \repeat unfold 10 {  foo -- bar }}}
>>

\layout {}

Attachment: lyrextest.pdf
Description: Adobe PDF document

_______________________________________________
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user

Reply via email to