lilypond-user
[Top][All Lists]
Advanced

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

Re: Getting grob Y position (spacing error)


From: Gregory Evans
Subject: Re: Getting grob Y position (spacing error)
Date: Fri, 18 Nov 2022 20:37:18 -0500

Hello Jean,
thank you for the information about after-line-breaking and the timing of skyline computing. Is there an equivalent property to trigger callback after the skylines are calculated? I am trying to use (ly:stencil-add ...) to add to the stencil of a notehead by drawing a line from one notehead in one staff to a notehead in another staff. The notehead grob does not appear to have a cross-staff property to delay stencil callback.

\language "english"
\version "2.23.14"

#(set-global-staff-size 12)

\score {
    <<
        \new Staff {
            \override NoteHead.cross-staff = ##t
            \once \override NoteHead.after-line-breaking = #(lambda (grob)
                    (let*
                        (
                           (sys (ly:grob-system grob))
                           (x-extent (ly:grob-extent grob sys X))
                           (y-extent (ly:grob-extent grob sys Y))
                        )
                        (display (list x-extent ))
                    )
                )
            c'1
            c'1
            c'1
            c'1
        }
        \new Staff {
            c'1
            c'1
            c'1
            c'1
        }
    >>
}

A larger example of the function (without a great deal of context) looks like this:

interrupt = #(define-music-function (value) (number?)
  #{
      \once \override Staff.NoteHead.after-line-breaking = #(lambda (grob)
              (let* (
                (stem (ly:grob-object grob 'stem))
                (stem-dir (ly:grob-property stem 'direction))
                (stem-thickness (ly:grob-property stem 'thickness))
                (thickness (/ stem-thickness 10))
                (notecol (ly:grob-parent grob X))
                (meta  (assoc 'other-grob (ly:grob-property notecol 'meta)))
                (other (if meta
                              (cdr meta)
                              grob
                      ))
                (notehead-width (cdr (ly:grob-property grob 'X-extent)))
                (sys (ly:grob-system grob))
                (now-pos (ly:grob-extent grob sys X))
                (next-pos (ly:grob-extent other sys X))

                ;;the offending lines
                (now-pos-y (ly:grob-extent grob common Y))
                (next-pos-y (ly:grob-extent other common Y))

                (x-distance
                    (if (= stem-dir -1)
                      (+ (- (get-distance now-pos next-pos) notehead-width ) (/ thickness 2))
                      (- (get-distance now-pos next-pos) (/ thickness 2))
                    ))
                (y-distance
                    (if (= stem-dir -1)
                      (+ (- (get-distance now-pos-y next-pos-y) notehead-width ) (/ thickness 2))
                      (- (get-distance now-pos-y next-pos-y) (/ thickness 2))
                    ))

                ;; alternative which takes input number
                ;(ps-bracket
                ;    (if (= stem-dir -1)
                ;      (draw-ps-bracket x-distance notehead-width (- value 0.5) thickness)
                ;      (draw-ps-bracket x-distance notehead-width value thickness)
                ;    ))
                (ps-bracket
                    (if (= stem-dir -1)
                      (draw-ps-bracket x-distance notehead-width (- y-distance 0.5) thickness)
                      (draw-ps-bracket x-distance notehead-width y-distance thickness)
                    ))
                (ps-line (draw-ps-line x-distance notehead-width thickness))
                (grob-stencil (ly:grob-property grob 'stencil))
                (stencil-bracket (ly:stencil-add grob-stencil ps-bracket ))
                (stencil-line (ly:stencil-add grob-stencil ps-line))
                )
                (if (assoc 'is-lower-in-chord (ly:grob-property grob 'meta))
                        (ly:grob-set-property! grob 'stencil stencil-line)
                        (ly:grob-set-property! grob 'stencil stencil-bracket)
                  )
              )
            )
  #}
)

best,
greg


On Fri, Nov 18, 2022 at 5:22 AM Jean Abou Samra <jean@abou-samra.fr> wrote:
Le 18/11/2022 à 00:29, Gregory Evans a écrit :
>
> Hi lilypond users,
> I have a question about getting the Y position of a grob. I saw this
> question has been asked previously but I could not find if it had been
> answered. In the following example, an after-line-breaking function is
> defined such that no change on the output should occur. The grob is
> only queried with |(ly:grob-extent grob ... Y)| but this value is not
> used. There is a difference in the vertical spacing between the staves
> of the staff group based on whether this query is present or not. The
> intention is to be able to query a grob for its Y position relative to
> another grob in order to draw cross-staff spanners, where it is
> necessary to calculate the distance between grobs not only on the X
> axis but also on the Y axis. Here, the system is being used to
> accurately get the X position, but using the system to get the Y
> position triggers this spacing error but appears to return the correct
> position before the spacing shift.
>


Because you are requesting it in after-line-breaking, which is earlier
than LilyPond can provide it to you. At this point of the compilation,
line breaking has just happened and page spacing (vertical spacing
of systems and staves in each system) has not happened yet. The
next thing LilyPond will do is computing the skylines (outlines) of the
staves in order to be able to space them. If you ask for the offset of some
staff relative to the system, it triggers these things prematurely
while they're not ready.

If you are writing a stencil callback, it is usually not OK to ask
for the coordinate of a staff relative to the whole system, because
it is a cyclic dependency: the coordinate depends on the spacing,
which depends on the outline, which depends on the stencil of your
grob. However, for cross-staff grobs, it is necessary, so if you
are writing one, you need to \override YourGrob.cross-staff = ##t,
and then LilyPond will completely ignore it for vertical spacing
purposes, and the stencil callback will only be run at a later point
where vertical spacing is already done.


\version "2.23.81"

\language "english"

#(set-global-staff-size 12)

\score {
     <<
         \new Staff {
             %% See what weird things happen to the beam if it's not
             %% properly marked cross-staff.
             \override Beam.cross-staff = ##f
             c'8[
             \change Staff = down
             c''8]
         }
         \new Staff = down {
             s4
         }
     >>
}


Best,
Jean





--
gregory rowland evans

reply via email to

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