Le 03/04/2021 à 17:28, Thomas Morley a écrit :
Hi,
please consider the code below.
\version "2.22.0"
#(ly:set-option 'debug-skylines #t)
{
\override NoteHead.no-ledgers = ##t
%\override NoteHead.stencil = #point-stencil
\override Stem.stencil =
#(lambda (grob)
(for-each
(lambda (nh) (ly:grob-translate-axis! nh -6 Y))
(ly:grob-array->list
(ly:grob-object (ly:grob-parent grob X) 'note-heads)))
(ly:stem::print grob))
b'''8
b'''8.
}
For some graphical notation I need to move notes (i.e. at least
NoteHead, Stem, Flag) freely in Y-axis direction.
Using ly:grob-translate-axis! seemed to be nice for this pupose,
because while moving the NoteHead the mentioned other Grobs follow.
Alas, enabling 'debug-skylines shows a problem: the skyline obviously
still sees the old grob-positions.
How to avoid, circumvent, correct?
Furthermore, why there's no problem for dotted notes?
Thanks,
Harm
Hi Harm,
Skylines are generally computed early in the typesetting process. I've
never know what the default method for computing them in the absence of
a vertical-skylines callback is, but at least some grobs in
define-grobs.scm have grob::always-vertical-skylines-from-stencil in
vertical-skylines, and that is an pure-unpure container, so there is a
part computed before line breaking. I think this serves in the page
breaking algorithms, to determine how many systems can be put on the
page. If you call ly:grob-translate-axis! in a stencil callback, it
might come after the skylines have been built, and cached, and actively
used. About the dot: I added some debugging messages to see what's going on.
\version "2.23.2" #(ly:set-option 'debug-skylines #t) { \override
NoteHead.no-ledgers = ##t %\override NoteHead.stencil = #point-stencil
\override Stem.stencil = #(lambda (grob) (ly:message "Stem
callback, duration of note: ~s" (ly:event-property
(event-cause (first
(ly:grob-array->list
(ly:grob-object grob 'note-heads))))
'duration)) (for-each (lambda (nh)
(ly:grob-translate-axis! nh -6 Y)) (ly:grob-array->list
(ly:grob-object (ly:grob-parent grob X) 'note-heads)))
(ly:stem::print grob)) b'''8 b''''8. }
Output is:
Preprocessing graphical objects...
Stem callback, duration of note: #<Duration 8. >
Finding the ideal number of pages...
Fitting music on 1 page...
Drawing systems...
Stem callback, duration of note: #<Duration 8 > This looks like
something in Dots or DotColumn callbacks is triggering Stem.stencil
earlier. I have no idea what exactly. This is why side effects in
callbacks are a bit dangerous. They make the process depend on a certain
order in computing the properties. Does it fit your use case just to
write a pure-unpure callback for NoteHead.Y-offset? For example (an idea
stolen from Valentin):
\version "2.23.2" % #(ly:set-option 'debug-skylines #t) { \time 9/8
\override NoteHead.no-ledgers = ##t \override NoteHead.Y-offset =
#(ly:make-unpure-pure-container (lambda (note-head) (let* ((note-column
(ly:grob-parent note-head X)) (paper-column (ly:grob-parent note-column
X)) (moment (ly:grob-property paper-column 'when)) (main-part
(ly:moment-main moment))) (* 3 (+ (sin main-part) (sin (+ 1 (* main-part
2)))))))) \repeat unfold 30 c'4. } Not sure if the unpure-pure container
is actually needed here. I think so. At least, the default for
NoteHead.Y-offset (staff-symbol-referencer::callback) is a pure-unpure
container, so it should be safe as long as your function is pure.
Hope that helps, Jean