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 <j...@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 http://www.gregoryrowlandevans.com https://github.com/GregoryREvans https://soundcloud.com/gregory-rowland-evans