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 <[email protected]> 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