[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