lilypond-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: text block as spanner


From: Thomas Morley
Subject: Re: text block as spanner
Date: Sat, 2 Feb 2019 21:09:42 +0100

Am Do., 31. Jan. 2019 um 10:27 Uhr schrieb Leo Correia de Verdier
<address@hidden>:
>
> Dear List!
>
> I’m still learning lilypond and working on a piece with long text 
> instructions that appear over a note or group of notes. So far I have managed 
> to achieve this by hacking off the stencils from text spanners and replacing 
> them with the line wrapped markup, but I feel there should be a neater 
> solution out there that I just haven’t thought or learned about. This hack 
> has also reached it’s limits because it has created the need for multiple 
> simultaneous text spanners (not in the example). While I could go further 
> down the hack road by placing additional spanners in separate voices with 
> spacer rests or starting to destroy trill spanners too, that would just 
> increase the mess. Could you please point me towards a tidier path? :)
>
> Thanks a lot!
>
> /Leo
>
> \version "2.19.80"
>
> longTextInstr =
> #(define-music-function (alongtext)
>    (string?)
>    #{
>      \once \override Staff.TextSpanner.stencil =
>      #(lambda (grob)
>         (let* ((grob-X (interval-length
>                         (ly:stencil-extent (ly:line-spanner::print grob) X)))
>                (layout (ly:grob-layout grob))
>                (props (ly:grob-alist-chain grob
>                         (ly:output-def-lookup layout
>                           'text-font-defaults))))
>
>           (ly:text-interface::interpret-markup layout props
>             #{ \markup {
>               \override #(cons 'line-width grob-X)
>               \wordwrap-string #alongtext }
>             #})
>           ))
>    #}
>    )
>
> \relative {
>   c'1 \longTextInstr "this is a long text instruction to be printed 
> line-wrapped over a group of notes"
>   d \startTextSpan
>   e f
>   e \stopTextSpan
>   d
> }
Hi Leo,

you're code is fine. It does exactly what it is supposed to do.
You could consider, making it a tweak and you could use
'grob-interpret-markup' to avoid finding 'layout' 'props' yourself.

Though, it's a kown limitation that you can't use more than one
TextSpanner per Voice.

You already found the usual workaround: Additional Voices.

A bold workaround is to define the whole infrastructure for
TextSpanners with new/renamed events (class and type), grobs,
engravers and
start/stop-commands.

\version "2.19.82"

\include "multiple-spanner-grobs-engravers.ly"

\createSpannersAndEngravers  #'(X Y Z)

\layout {
  \context {
    \Global
    \grobdescriptions #all-grob-descriptions
  }
  \context {
    \Voice
    \consists \XTextSpannerEngraver
    \consists \YTextSpannerEngraver
    \consists \ZTextSpannerEngraver
  }
}

#(define (text-spanner->text text)
  (lambda (grob)
    (let* ((grob-X
             (interval-length
               (ly:stencil-extent (ly:line-spanner::print grob) X))))
      (grob-interpret-markup grob
        #{
          \markup \override #(cons 'line-width grob-X) \wordwrap-string #text
        #}))))

txtI =
"this is a long text instruction to be printed line-wrapped over a group of
notes"


txtII =
"this is another long text instruction to be printed line-wrapped below a group
of notes"

\relative {
  c'1
  d
    -\tweak stencil #(text-spanner->text txtI)
    \startTextSpan
    -\tweak stencil #(text-spanner->text txtII)
    _\x-start
  e f
  e \stopTextSpan
  d \x-stop
}

HTH,
  Harm

Attachment: multiple-spanner-grobs-engravers.ly
Description: Text Data


reply via email to

[Prev in Thread] Current Thread [Next in Thread]