lilypond-user
[Top][All Lists]
Advanced

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

Re: How to get bounding NoteColumns of the first of consecutive TextSpan


From: Thomas Morley
Subject: Re: How to get bounding NoteColumns of the first of consecutive TextSpanners
Date: Sat, 6 Mar 2021 17:47:00 +0100

Hi Jean,

Am Mi., 3. März 2021 um 23:05 Uhr schrieb Jean Abou Samra <jean@abou-samra.fr>:
>
>
> Le 03/03/2021 à 13:55, Thomas Morley a écrit :

> > How to get the NoteColumn at first TextSpanner's end?

> This looks tricky indeed.
>
> Maybe an engraver operating in Voice context? Here's my attempt:
[...]
> Like David's solution, this of course won't give you the note columns
> for each of the broken pieces.

Well, I'm interested in the bounds of the unbroken spanner, probably
think of (ly.grob-original <text-spanner-grob>)
Especially in the Stems of the NoteColumns (if any can be found).
A more verbose description in my previous post.

> Well, I am in fact not sure that a notion
> of the bounding note columns for a broken text spanner can even be
> defined. Thoughts?
>
> Cheers,
> Jean
>

I took the liberty to modify your engraver, looking directly for Stems
and eliminating the custom-grob-property, replacing it with
details.subproperties.
Making for:

\version "2.23.1"

Set_bounding_stems_engraver =
#(lambda (context)
    (let ((spanner-starting #f)
          (spanner-ending #f)
          (stem #f))
      (make-engraver
        (acknowledgers
          ((line-spanner-interface engraver grob source-engraver)
             (set! spanner-starting grob))
          ((stem-interface engraver grob source-engraver)
             (set! stem grob)))
        (end-acknowledgers
          ((line-spanner-interface engraver grob source-engraver)
             (set! spanner-ending grob)))
        ((stop-translation-timestep engraver)
          ;; TODO In polyphonic situations there may be more than one Stem at
          ;;      the same timestep
          ;;      How to select?
          (if spanner-starting
              (ly:grob-set-nested-property! spanner-starting
                '(details stem-left) stem))
          (if spanner-ending
              (ly:grob-set-nested-property! spanner-ending
                '(details stem-right) stem))
          (set! spanner-starting #f)
          (set! spanner-ending #f)
          (set! stem #f)))))

#(define (get-bounding-stem-dirs-jean spanner)
  (let* ((details (ly:grob-property spanner 'details))
         (stem-left (assoc-get 'stem-left details))
         (stem-left-dir
           (if (ly:grob? stem-left)
               (ly:grob-property stem-left 'direction)))
         (stem-right (assoc-get 'stem-right details))
         (stem-right-dir
           (if (ly:grob? stem-right)
               (ly:grob-property stem-right 'direction))))
    (cons stem-left-dir stem-right-dir)))

#(define (text-stencil-jean txt)
  (lambda (grob)
    (let* ((bounding-stem-dirs
             (get-bounding-stem-dirs-jean grob))
           (stem-left-dir
             (car bounding-stem-dirs))
           (stem-right-dir
             (cdr bounding-stem-dirs)))
      ;; adjust left/right padding and left/right attach-dir
      (if (and (number? stem-left-dir) (number? stem-right-dir))
          (begin
            ;; compensate Stem.thickness
            ;; IR says it's 1.3
            (ly:grob-set-nested-property! grob
              '(bound-details right padding) 0.13)
            (ly:grob-set-nested-property! grob
              '(bound-details left padding) 0)
            ;; always start at right edge of left bound
            (ly:grob-set-nested-property! grob
              '(bound-details left attach-dir) 1)

            (cond ((and (positive? stem-left-dir) (positive? stem-right-dir))
                    (ly:grob-set-nested-property! grob
                      '(bound-details right attach-dir) 1))
                  ((and (positive? stem-left-dir) (negative? stem-right-dir))
                    (ly:grob-set-nested-property! grob
                      '(bound-details right attach-dir) 0))
                  (else
                    (ly:grob-set-nested-property! grob
                      '(bound-details right attach-dir) -1)))))

      (let* ((stil (ly:line-spanner::print grob))
             (stil-center (interval-center (ly:stencil-extent stil X)))
             (text-stil
               (grob-interpret-markup grob
                 (if (not-first-broken-spanner? grob)
                     (make-parenthesize-markup txt)
                     txt)))
             (text-center (interval-center (ly:stencil-extent text-stil X))))

       (ly:stencil-add
        ;; for reference or visual debugging add:
        ;stil
        (ly:stencil-translate-axis text-stil (- stil-center text-center) X)
        )
        ))))

%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% EXAMPLEs
%%%%%%%%%%%%%%%%%%%%%%%%%%%

mus = <<
  { \repeat unfold 8 b4 }

  \new Voice \with {
    \consists \Set_bounding_stems_engraver
    \override TextSpanner.font-shape = #'upright
    \override TextSpanner.style = #'solid
  }
  {
    g'-\tweak stencil #(text-stencil-jean "1") \startTextSpan
    a'\stopTextSpan
      -\tweak stencil #(text-stencil-jean "1½") \startTextSpan
    c''\stopTextSpan
       -\tweak stencil #(text-stencil-jean "½") \startTextSpan
    b'\stopTextSpan
      -\tweak stencil #(text-stencil-jean "0") \startTextSpan
    b'\stopTextSpan
      -\tweak stencil #(text-stencil-jean "1") \startTextSpan
    a'\stopTextSpan
      -\tweak stencil #(text-stencil-jean "0") \startTextSpan
    a'\stopTextSpan
      -\tweak stencil #(text-stencil-jean "full") \startTextSpan
    b'\stopTextSpan
  }

  { \repeat unfold 8 b }
>>

\score {
  \mus
  \layout {}
  \layout {
      line-width = 120
      ragged-right = ##f
  }
  \layout {
      ragged-right = ##f
  }
}

Afaict, for my use-case both very nice codings work with line-breaks.

Many thanks,
  Harm



reply via email to

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