Jump to content

Using arbitrary markup as lyric hyphen: Difference between revisions

From LilyPond wiki
m New category
No edit summary
 
(3 intermediate revisions by 2 users not shown)
Line 1: Line 1:
Lyric hyphens have several user-modifiable properties such as length and thickness; this doesn’t allow, however, for further tweaking, for example, rendering hyphens as rounded boxes to better match the font possibly used for <code>LyricText</code>, or even printing hyphens as actual glyphs rather than drawing basic boxes.
Lyric hyphens have several user-modifiable properties such as length and thickness; this doesn’t allow, however, for further tweaking, for example, rendering hyphens as rounded boxes to better match the font possibly used for <code>LyricText</code>, or even printing hyphens as actual glyphs rather than drawing basic boxes.


This snippet rewrites the <code>LyricHyphen</code> stencil procedure to use a proper glyph… or indeed any arbitrary markup.
This snippet rewrites the <code>LyricHyphen</code> stencil procedure to use a proper glyph – or indeed any arbitrary markup.


<lilypond version="2.24" full>
<lilypond version="2.24">
%% Originally contributed by Aaron Hill:
% Originally contributed by Aaron Hill:
%% https://lists.gnu.org/archive/html/lilypond-user/2019-03/msg00257.html
% https://lists.gnu.org/archive/html/lilypond-user/2019-03/msg00257.html


#(define (lyric-hyphen-text-stencil grob)
#(define (lyric-hyphen-text-stencil grob)
Line 95: Line 95:
   Lo -- rem ip -- sum do -- lor sit a -- met.
   Lo -- rem ip -- sum do -- lor sit a -- met.
    
    
   \mark \markup { "LyricHyphen.text is " \circle \with-color #red "&" }
   \mark \markup { "LyricHyphen.text is " \circle \with-color #red "" }
   \override LyricHyphen.text =  
   \override LyricHyphen.text = \markup \circle \with-color #red "♥"
    \markup
      \circle \with-color #red  
      %% For unknown reason "\xe2\x99\xa5", which is "♥", U+2665, does not work in LSR,
      %% replacing it with "&"
      %% Outside of LSR it works -- Harm
      %%
      %% Outside LSR it's possible to use "♥" directly for guile-v1 and guile-v2  --Harm (May 2022)
      #"&"
   \override LyricText.font-size = #3
   \override LyricText.font-size = #3
   Lo -- rem ip -- sum do -- lor sit a -- met.
   Lo -- rem ip -- sum do -- lor sit a -- met.


      %% Same here for "\xe2\x89\x8b", which is "≋", U+224B, does not work in LSR,
   \mark \markup { "LyricHyphen.text is blue" \with-color #blue #"" }
      %% replacing it with "~"
      %% Outside of LSR it works -- Harm
      %%
      %% Outside LSR it's possible to use "≋" directly for guile-v1 and guile-v2  --Harm (May 2022)
 
   \mark \markup { "LyricHyphen.text is blue" \with-color #blue #"~" }
   \override LyricHyphen.text =  
   \override LyricHyphen.text =  
     \markup
     \markup \scale #'(3 . 1) \with-color #blue #""
      \scale #'(3 . 1) \with-color #blue #"~"
   \override LyricText.font-size = #6
   \override LyricText.font-size = #6
   Break -- ing
   Break -- ing
Line 123: Line 108:
</lilypond>
</lilypond>


[[Category:Scheme]]
[[Category:Tweaks and overrides]]
[[Category:Vocal music]]
[[Category:Vocal music]]
[[Category:Tweaks and overrides]]
[[Category:Snippet]]
[[Category:Snippet]]

Latest revision as of 10:20, 6 December 2025

Lyric hyphens have several user-modifiable properties such as length and thickness; this doesn’t allow, however, for further tweaking, for example, rendering hyphens as rounded boxes to better match the font possibly used for LyricText, or even printing hyphens as actual glyphs rather than drawing basic boxes.

This snippet rewrites the LyricHyphen stencil procedure to use a proper glyph – or indeed any arbitrary markup.

\version "2.24"

% Originally contributed by Aaron Hill:
% https://lists.gnu.org/archive/html/lilypond-user/2019-03/msg00257.html

#(define (lyric-hyphen-text-stencil grob)
   "Draws a LyricHyphen using an arbitrary text markup."
   
   (define (span-point side common dir)
     (let ((iv
            (ly:generic-bound-extent side common)))
       (if (interval-empty? iv)
           (ly:grob-relative-coordinate side common X)
           (interval-bound iv dir))))
           
   (define (get-text-stencil grob)
     (let* ((orig (ly:grob-original grob))
            (into (ly:spanner-broken-into orig)))
       (grob-interpret-markup
        (ly:spanner-bound (if (null? into) orig (first into)) LEFT)
        (ly:grob-property grob 'text "-"))))
        
   (let* ((left-bound (ly:spanner-bound grob LEFT))
          (right-bound (ly:spanner-bound grob RIGHT))
          (common (ly:grob-common-refpoint left-bound right-bound X))
          (left-span (span-point left-bound common RIGHT))
          (right-span (span-point right-bound common LEFT))
          (span-length (- right-span left-span))
          (padding (ly:grob-property grob 'padding 0.1))
          (minimum-length (ly:grob-property grob 'minimum-length 0.3))
          (usable-length 
            (- span-length
               (if (zero? (ly:item-break-dir left-bound)) padding 0)
               (if (zero? (ly:item-break-dir right-bound)) padding 0))))
     (if (< usable-length minimum-length) '()
         (let* ((dash-sten (get-text-stencil grob))
                (dash-extent (ly:stencil-extent dash-sten X))
                (dash-length (min (interval-length dash-extent) usable-length))
                (scaled-sten (ly:stencil-scale
                              (ly:stencil-translate-axis
                               dash-sten (- (interval-start dash-extent)) X)
                              (/ dash-length (interval-length dash-extent)) 1))
                (dash-period 
                  (max (ly:grob-property grob 'dash-period 1.0) dash-length))
                (dash-count 
                  (1+ (floor (/ (- usable-length dash-length) dash-period))))
                (extra 
                  (- usable-length 
                     dash-length 
                     (* (- dash-count 1) dash-period)))
                (offset 
                  (+ (- left-span (ly:grob-relative-coordinate grob common X))
                     (if (zero? (ly:item-break-dir left-bound)) padding 0)
                     (/ extra 2))))
           (apply 
             ly:stencil-add 
             (map 
               (lambda (n)
                 (ly:stencil-translate-axis 
                   scaled-sten 
                   (+ offset (* n dash-period)) 
                   X))
               (iota dash-count)))))))

\paper {
  indent = 0
  ragged-right = ##f
  tagline = ##f
}

\relative c' {
  \omit Staff.TimeSignature
  \repeat unfold 3 {
    b4. b8 b4 b4 |
    b8 b8 b8 b8 b2 \break
  }
  r2 b'2~ \break b1~ \break b2 b2
}
\addlyrics {
  \override Score.RehearsalMark.self-alignment-X = #LEFT
  
  \mark "LyricHyphen.text is \"-\""
  \override LyricHyphen.dash-period = #5
  \override LyricHyphen.padding = #0.2
  \override LyricHyphen.stencil = #lyric-hyphen-text-stencil
  
  Lo -- rem ip -- sum do -- lor sit a -- met.
  
  \mark "LyricHyphen.text is \"–\""
  \override LyricHyphen.text = #"–" %#"\xe2\x80\x93" % U+2013
  \override LyricText.font-series = #'bold
  Lo -- rem ip -- sum do -- lor sit a -- met.
  
  \mark \markup { "LyricHyphen.text is " \circle \with-color #red "♥" }
  \override LyricHyphen.text = \markup \circle \with-color #red "♥"
  \override LyricText.font-size = #3
  Lo -- rem ip -- sum do -- lor sit a -- met.

  \mark \markup { "LyricHyphen.text is blue" \with-color #blue #"≋" }
  \override LyricHyphen.text = 
    \markup \scale #'(3 . 1) \with-color #blue #"≋"
  \override LyricText.font-size = #6
  Break -- ing
}