lilypond-user
[Top][All Lists]
Advanced

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

Re: Vertical positioning of rests


From: Jean Abou Samra
Subject: Re: Vertical positioning of rests
Date: Thu, 23 Sep 2021 23:56:28 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.11.0

Le 23/09/2021 à 15:35, Leo Correia de Verdier a écrit :
I’m unsure if the following can count as an MWE, but here it goes:

Call it MWE or not, it definitely helps!

There are a number of internal mechanisms under the hood
here. The primary source for a grob's vertical is Y-offset,
that's true. However, at any time, the grob may be shifted
somewhere with ly:grob-translate-axis! or its C++ equivalent.
This means that you should not look at

(ly:grob-property grob 'Y-offset)

but rather

(ly:grob-relative-coordinate grob
                             (ly:grob-parent grob Y)
                             Y)

where the second argument to ly:grob-relative-coordinate
is a reference point, that is, any grob in the ancestry
of this grob on the axis (I took the immediate parent
in this example).

Once you have the position, you can move the grob around
with ly:grob-translate-axis!. Here is an example putting
all rests 5 units above the baseline of the context
(VerticalAxisGroup grob):

\version "2.22.1"

#(define (move-rest-after-line-breaking grob)
   (let* ((vertical-axis-group (ly:grob-object grob 'axis-group-parent-Y))
          (current-coord (ly:grob-relative-coordinate grob vertical-axis-group Y))
          (desired-coord 5))
     (ly:grob-translate-axis! grob (- desired-coord current-coord) Y)))

{
  \override Staff.Rest.before-line-breaking = #move-rest-after-line-breaking
  r2
  <<
    { r4 f''4 }
    \\
    { e'4 r4 }
  >>
}

However, you should be aware that side effects like
ly:grob-translate-axis! should be done with care in callbacks.
In some cases, your callback could come after the ones
that read the position, and these will use a wrong
value. It's a good idea to stick to replacing existing
callbacks that are expected to have side effects — positioning-done
is an example. (Those callbacks that need the result of
a side effect of positioning-done start by calling it.
For example, the default callback in NoteHead.X-offset
just calls the Stem's positioning-done and lets it
translate the NoteHead. That way, it's guaranteed that
Stem.positioning-done will come in time.)

Fortunately, you don't have to worry about it here:
just use staff-position, which is meant as a user override.
It is unset by default, but you can set it to whatever
value or callback you want, and it will be honored.
The example above could be rewritten as just

\version "2.22.1"

{
  \override Staff.Rest.staff-position = 5
  r2
  <<
    { r4 f''4 }
    \\
    { e'4 r4 }
  >>
}

and a callback can handle a dynamic calculation:

\version "2.22.1"

{
  \override Staff.Rest.staff-position =
    #(lambda (grob)
       (* 5 (ly:grob-property grob 'duration-log)))
  r1 r2 r4 r8 r16 r32 r32 r16 r16 r8 r4 r2
}

Feel free to ask more questions.

Best regards,
Jean



reply via email to

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