[ << Interfaces for programmers ] | [Top][Contents][Index] | [ LilyPond Scheme interfaces >> ] |
[ < Callback functions ] | [ Up : Interfaces for programmers ] | [ Difficult tweaks > ] |
2.8 Unpure-pure containers
Note: While this subsubsection reflects the current state, the given example is moot and does not show any effect.
Unpure-pure containers are useful for overriding Y-axis spacing
calculations – specifically Y-offset
and Y-extent
– with a
Scheme function instead of a literal (i.e., a number or pair).
For certain grobs, the Y-extent
is based on the stencil
property, overriding the stencil property of one of these will
require an additional Y-extent
override with an unpure-pure
container. When a function overrides a Y-offset
and/or
Y-extent
it is assumed that this will trigger line breaking
calculations too early during compilation. So the function is not
evaluated at all (usually returning a value of ‘0’ or
‘'(0 . 0)’) which can result in collisions. A ‘pure’ function
will not affect properties, objects or grob suicides and therefore will
always have its Y-axis-related evaluated correctly.
Currently, there are about thirty functions that are already considered ‘pure’ and Unpure-pure containers are a way to set functions not on this list as ‘pure’. The ‘pure’ function is evaluated before any line-breaking and so the horizontal spacing can be adjusted ‘in time’. The ‘unpure’ function is then evaluated after line breaking.
Note: As it is difficult to always know which functions are on this
list we recommend that any ‘pure’ functions you create do not use
Beam
or VerticalAlignment
grobs.
An unpure-pure container is constructed as follows;
(ly:make-unpure-pure-container f0 f1)
where f0
is a function taking n arguments (n >= 1)
and the first argument must always be the grob. This is the function
that gives the actual result. f1 is the function being labeled
as ‘pure’ that takes n + 2 arguments. Again, the first argument
must always still be the grob but the second and third are ‘start’
and ‘end’ arguments.
start and end are, for all intents and purposes, dummy
values that only matter for Spanners
(i.e Hairpin
or
Beam
), that can return different height estimations based on a
starting and ending column.
The rest are the other arguments to the first function (which may be none if n = 1).
The results of the second function are used as an approximation of the value needed which is then used by the first function to get the real value which is then used for fine-tuning much later during the spacing process.
#(define (square-line-circle-space grob) (let* ((pitch (ly:event-property (ly:grob-property grob 'cause) 'pitch)) (notename (ly:pitch-notename pitch))) (if (= 0 (modulo notename 2)) (make-circle-stencil 0.5 0.0 #t) (make-filled-box-stencil '(0 . 1.0) '(-0.5 . 0.5))))) squareLineCircleSpace = { \override NoteHead.stencil = #square-line-circle-space } smartSquareLineCircleSpace = { \squareLineCircleSpace \override NoteHead.Y-extent = #(ly:make-unpure-pure-container ly:grob::stencil-height (lambda (grob start end) (ly:grob::stencil-height grob))) } \new Voice \with { \remove Stem_engraver } \relative c'' { \squareLineCircleSpace cis4 ces disis d \smartSquareLineCircleSpace cis4 ces disis d }
In the first measure, without the unpure-pure container, the spacing engine does not know the width of the note head and lets it collide with the accidentals. In the second measure, with unpure-pure containers, the spacing engine knows the width of the note heads and avoids the collision by lengthening the line accordingly.
Usually for simple calculations nearly-identical functions for
both the ‘unpure’ and ‘pure’ parts can be used, by only
changing the number of arguments passed to, and the scope of, the
function. This use case is frequent enough that
ly:make-unpure-pure-container
constructs such a second
function by default when called with only one function argument.
Note: If a function is labeled as ‘pure’ and it turns out not to be, the results can be unexpected.
[ << Interfaces for programmers ] | [Top][Contents][Index] | [ LilyPond Scheme interfaces >> ] |
[ < Callback functions ] | [ Up : Interfaces for programmers ] | [ Difficult tweaks > ] |