Force TextScript to staff-padding / optional \textLengthOn

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Force TextScript to staff-padding / optional \textLengthOn

Urs Liska-3

Hi,

I was struggling with this earlier, but suggestions from the list didn't help me and I had to postpone the issue. Now I've got to resolve it and while I make progress I don't seem to be able to get to the goal line :-(

I am trying to create a text command that prints items at a specific distance from the staff (in order to have multiple items on the same baseline). The behaviour of staff-padding is good enough for me, that is if one of the items is forced to be farther away to prevent collisions with the music I'm OK with adjusting the staff-padding for *all* items.

My problem is that the created markup should push other items to the right rather have them stack vertically as is the standard behaviour of TextScript - but only if there actually *is* such an item. Using \textLengthOn always pushes the next note column to the right, even when that doesn't have a text attached.

I found a solution using extra-spacing-width (but not extra-spacing-height) together with unsetting outside-staff-priority and wrapping all of this in an event-function:

\version "2.19.82"

#(define (create-foo text)
   #{
     -\tweak extra-spacing-width #(cons -0.0 .8)
     -\tweak outside-staff-priority ##f
     -\tweak staff-padding 3
     -\markup #text
   #})

this =
#(define-event-function ()()
   (create-foo "thisis."))

that =
#(define-event-function ()()
   (create-foo "thatis."))

\relative {
  e''16 \this [ f e \that d \this ]
}

In the attached 'correct.png' you can see that the *second* item "thatis." correctly pushes the next note in order to avoid the collision (the little white space comes from the .8 value to extra-spacing-width) while the first "thisis." leaves the second note alone.

However, I don't actually use a literal value for staff-padding but a callback function that modifies the staff-padding according to the direction. And as soon as staff-padding is set to that (any) callback function the behaviour is again like using \textLengthOn, as can be seen in the attached 'wrong.png' where the second note is wrongly pushed to the right:

\version "2.19.82"

#(define (calc-staff-padding grob)
   "Calculate the staff-padding value of a grob.
    This has to be done in a callback since it seems to be
    the only solution to both align texts to the baseline
    (using staff-padding) *and* to adjust upper and lower
    padding. See
    http://lists.gnu.org/archive/html/lilypond-user/2018-10/msg00267.html"
   (let ((dir (ly:grob-property grob 'direction))
         (staff-padding 4) ; in the real project this is loaded from options
         )
     (if (> dir 0)
         staff-padding
         ; NOTE: It is somewhat arbitrary to have lower texts
         ; pad by exactly 1 staff space more than above
         ; TODO: Calculate by creating a "Tq" markup and measuring its Y-extent
         (+ 1 staff-padding))))

#(define (create-foo text)
   #{
     -\tweak extra-spacing-width #(cons -0.0 .8)
     -\tweak outside-staff-priority ##f
     -\tweak staff-padding #calc-staff-padding
     -\markup #text
   #})

this =
#(define-event-function ()()
   (create-foo "thisis."))

that =
#(define-event-function ()()
   (create-foo "thatis."))

\relative {
  e''16 \this [ f e \that d \this ]
}

Can anyone explain why the TextScript is behaving differently when staff-padding is tweaked to a literal or to a callback? And - more importantly - how I can achieve my goal?

Thanks
Urs


_______________________________________________
lilypond-user mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/lilypond-user

correct.png (12K) Download Attachment
wrong.png (13K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Force TextScript to staff-padding / optional \textLengthOn

Urs Liska-3

Hm,

after sending this request for help I (hopefully) found a solution myself. But I don't pretend to understand it ...

Am 29.01.19 um 10:55 schrieb Urs Liska:

Hi,

I was struggling with this earlier, but suggestions from the list didn't help me and I had to postpone the issue. Now I've got to resolve it and while I make progress I don't seem to be able to get to the goal line :-(

I am trying to create a text command that prints items at a specific distance from the staff (in order to have multiple items on the same baseline). The behaviour of staff-padding is good enough for me, that is if one of the items is forced to be farther away to prevent collisions with the music I'm OK with adjusting the staff-padding for *all* items.

My problem is that the created markup should push other items to the right rather have them stack vertically as is the standard behaviour of TextScript - but only if there actually *is* such an item. Using \textLengthOn always pushes the next note column to the right, even when that doesn't have a text attached.

...

However, I don't actually use a literal value for staff-padding but a callback function that modifies the staff-padding according to the direction. And as soon as staff-padding is set to that (any) callback function the behaviour is again like using \textLengthOn, as can be seen in the attached 'wrong.png' where the second note is wrongly pushed to the right:

...

#(define (create-foo text)
   #{
     -\tweak extra-spacing-width #(cons -0.0 .8)
     -\tweak outside-staff-priority ##f
     -\tweak staff-padding #calc-staff-padding
     -\markup #text
   #})

...

Can anyone explain why the TextScript is behaving differently when staff-padding is tweaked to a literal or to a callback? And - more importantly - how I can achieve my goal?


Well, as said I seem to have achieved my goal, but I would be happy to understand it better. As said tweaking 'staff-padding to a callback function makes the spacing behave like with \textLengthOn (i.e. extra-spacing-width and -height set). If on the other hand I tweak before-line-breaking to a callback, and within that callback set the staff-padding property of the grob to the calculated value there doesn't seem to be such a side effect.

#(define (apply-staff-padding grob)
   (ly:grob-set-property! grob 'staff-padding (calc-staff-padding grob)))

...

-\tweak before-line-breaking #apply-staff-padding
     -\markup #text

Any clarification?

Thanks
Urs


Thanks
Urs


_______________________________________________
lilypond-user mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/lilypond-user

_______________________________________________
lilypond-user mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/lilypond-user
Reply | Threaded
Open this post in threaded view
|

Re: Force TextScript to staff-padding / optional \textLengthOn

Trevor Bača-2
Hi Urs,

I've been learning a lot watching you work through these text alignment problems over the last months. Thanks for these, and for the clarity of the writing as you've been developing the Lily code as you work!

I have no answer to the question at the end of your previous mail ("why does the combination of these three tweaks work?"). However, I wanted to mention that I've found -- finally -- a solution for baseline-aligned textual annotations that's been working for me in my own scores now for about a year: sticking all the text in a text spanner with invisible line segments between each element in the spanner.

I remember reading through a thread where this text spanner approach for vertical alignment came up, and I remember you had good reasons for continuing to work with individual TextScript objects instead. But I just wanted to pipe up and add that after years of going the text-script-with-staff-padding route (and never getting 100% "stable" results in the vertical positioning), that switching last year to the text-spanner-with-invisible-segments route has finally yielded a solution that seems genuinely stable.

For years, the missing piece had been that Lily didn't allow multiple overlapping text spanners in a single voice; that's a nonstarter in much (probably most) recent music, of course. But then David Nalesnik provided a solution, all the way back in 2015:


I now have a bunch of custom spanner definitions using David's alternateTextSpannerEngraver, which implements spanner-id, allowing for layered spanners. David's alternateTextSpannerEngraver should *absolutely* be included by default in Lily; I'll write that to the appropriate thread in a bit. At any rate, output like this now works consistently for me, for the first time in 13 years of using Lily:

layered-text-spanners.png

(The fractions show "bow contact points": 0 for talon; 1 for point; 1/2 for midway up the bow; etc. The T and P are tasto and ponticello, as you'd expect.)

So, even though that example draws the text spanner line segments in a visible way (dashed or solid), you can easily imagine setting dash-fraction to 0 to make segments invisible, leaving markup aligned in the correct way.

Ok, that's it; I know you're elaborating the text-script-with-staff-padding way of working. But just wanted to attest that the text spanner way does seem to be a viable alternative if you later become interested in that way of working, too.


Trevor.








On Tue, Jan 29, 2019 at 5:52 AM Urs Liska <[hidden email]> wrote:

Hm,

after sending this request for help I (hopefully) found a solution myself. But I don't pretend to understand it ...

Am 29.01.19 um 10:55 schrieb Urs Liska:

Hi,

I was struggling with this earlier, but suggestions from the list didn't help me and I had to postpone the issue. Now I've got to resolve it and while I make progress I don't seem to be able to get to the goal line :-(

I am trying to create a text command that prints items at a specific distance from the staff (in order to have multiple items on the same baseline). The behaviour of staff-padding is good enough for me, that is if one of the items is forced to be farther away to prevent collisions with the music I'm OK with adjusting the staff-padding for *all* items.

My problem is that the created markup should push other items to the right rather have them stack vertically as is the standard behaviour of TextScript - but only if there actually *is* such an item. Using \textLengthOn always pushes the next note column to the right, even when that doesn't have a text attached.

...

However, I don't actually use a literal value for staff-padding but a callback function that modifies the staff-padding according to the direction. And as soon as staff-padding is set to that (any) callback function the behaviour is again like using \textLengthOn, as can be seen in the attached 'wrong.png' where the second note is wrongly pushed to the right:

...

#(define (create-foo text)
   #{
     -\tweak extra-spacing-width #(cons -0.0 .8)
     -\tweak outside-staff-priority ##f
     -\tweak staff-padding #calc-staff-padding
     -\markup #text
   #})

...

Can anyone explain why the TextScript is behaving differently when staff-padding is tweaked to a literal or to a callback? And - more importantly - how I can achieve my goal?


Well, as said I seem to have achieved my goal, but I would be happy to understand it better. As said tweaking 'staff-padding to a callback function makes the spacing behave like with \textLengthOn (i.e. extra-spacing-width and -height set). If on the other hand I tweak before-line-breaking to a callback, and within that callback set the staff-padding property of the grob to the calculated value there doesn't seem to be such a side effect.

#(define (apply-staff-padding grob)
   (ly:grob-set-property! grob 'staff-padding (calc-staff-padding grob)))

...

-\tweak before-line-breaking #apply-staff-padding
     -\markup #text

Any clarification?

Thanks
Urs


Thanks
Urs


_______________________________________________
lilypond-user mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/lilypond-user
_______________________________________________
lilypond-user mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/lilypond-user


--

_______________________________________________
lilypond-user mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/lilypond-user
Reply | Threaded
Open this post in threaded view
|

Re: Force TextScript to staff-padding / optional \textLengthOn

Urs Liska-3

Hi Trevor,

thank you for this information. While I will (for the project at hand) stick to the approach with individual objects (my objects *are* individual objects and not spanners anyway) this is something I'll definitely want to be familiar with - and maybe your post even started an effort to integrate that functionality into LilyPond itself, which would be great ...

Best
Urs

Am 12.02.19 um 21:39 schrieb Trevor Bača:
Hi Urs,

I've been learning a lot watching you work through these text alignment problems over the last months. Thanks for these, and for the clarity of the writing as you've been developing the Lily code as you work!

I have no answer to the question at the end of your previous mail ("why does the combination of these three tweaks work?"). However, I wanted to mention that I've found -- finally -- a solution for baseline-aligned textual annotations that's been working for me in my own scores now for about a year: sticking all the text in a text spanner with invisible line segments between each element in the spanner.

I remember reading through a thread where this text spanner approach for vertical alignment came up, and I remember you had good reasons for continuing to work with individual TextScript objects instead. But I just wanted to pipe up and add that after years of going the text-script-with-staff-padding route (and never getting 100% "stable" results in the vertical positioning), that switching last year to the text-spanner-with-invisible-segments route has finally yielded a solution that seems genuinely stable.

For years, the missing piece had been that Lily didn't allow multiple overlapping text spanners in a single voice; that's a nonstarter in much (probably most) recent music, of course. But then David Nalesnik provided a solution, all the way back in 2015:


I now have a bunch of custom spanner definitions using David's alternateTextSpannerEngraver, which implements spanner-id, allowing for layered spanners. David's alternateTextSpannerEngraver should *absolutely* be included by default in Lily; I'll write that to the appropriate thread in a bit. At any rate, output like this now works consistently for me, for the first time in 13 years of using Lily:

layered-text-spanners.png

(The fractions show "bow contact points": 0 for talon; 1 for point; 1/2 for midway up the bow; etc. The T and P are tasto and ponticello, as you'd expect.)

So, even though that example draws the text spanner line segments in a visible way (dashed or solid), you can easily imagine setting dash-fraction to 0 to make segments invisible, leaving markup aligned in the correct way.

Ok, that's it; I know you're elaborating the text-script-with-staff-padding way of working. But just wanted to attest that the text spanner way does seem to be a viable alternative if you later become interested in that way of working, too.


Trevor.








On Tue, Jan 29, 2019 at 5:52 AM Urs Liska <[hidden email]> wrote:

Hm,

after sending this request for help I (hopefully) found a solution myself. But I don't pretend to understand it ...

Am 29.01.19 um 10:55 schrieb Urs Liska:

Hi,

I was struggling with this earlier, but suggestions from the list didn't help me and I had to postpone the issue. Now I've got to resolve it and while I make progress I don't seem to be able to get to the goal line :-(

I am trying to create a text command that prints items at a specific distance from the staff (in order to have multiple items on the same baseline). The behaviour of staff-padding is good enough for me, that is if one of the items is forced to be farther away to prevent collisions with the music I'm OK with adjusting the staff-padding for *all* items.

My problem is that the created markup should push other items to the right rather have them stack vertically as is the standard behaviour of TextScript - but only if there actually *is* such an item. Using \textLengthOn always pushes the next note column to the right, even when that doesn't have a text attached.

...

However, I don't actually use a literal value for staff-padding but a callback function that modifies the staff-padding according to the direction. And as soon as staff-padding is set to that (any) callback function the behaviour is again like using \textLengthOn, as can be seen in the attached 'wrong.png' where the second note is wrongly pushed to the right:

...

#(define (create-foo text)
   #{
     -\tweak extra-spacing-width #(cons -0.0 .8)
     -\tweak outside-staff-priority ##f
     -\tweak staff-padding #calc-staff-padding
     -\markup #text
   #})

...

Can anyone explain why the TextScript is behaving differently when staff-padding is tweaked to a literal or to a callback? And - more importantly - how I can achieve my goal?


Well, as said I seem to have achieved my goal, but I would be happy to understand it better. As said tweaking 'staff-padding to a callback function makes the spacing behave like with \textLengthOn (i.e. extra-spacing-width and -height set). If on the other hand I tweak before-line-breaking to a callback, and within that callback set the staff-padding property of the grob to the calculated value there doesn't seem to be such a side effect.

#(define (apply-staff-padding grob)
   (ly:grob-set-property! grob 'staff-padding (calc-staff-padding grob)))

...

-\tweak before-line-breaking #apply-staff-padding
     -\markup #text

Any clarification?

Thanks
Urs


Thanks
Urs


_______________________________________________
lilypond-user mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/lilypond-user
_______________________________________________
lilypond-user mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/lilypond-user


--

_______________________________________________
lilypond-user mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/lilypond-user