Le 14/01/2022 à 20:41, Valentin Petzel a écrit :
Hello Richard,
The file you’ve given us has a lot of nonsensical quoting in lines 149-153.
Actually, not completely nonsensical, but legacy. There used to
be one more level of quoting inside stencil expressions until
commit 06ba7f0823a14da773391ccf3c10244a54e812d4
Author: Han-Wen Nienhuys <hanw...@gmail.com>
Date: Sun Aug 2 21:47:25 2020 +0200
Dispatch stencil routines using explicit tables
scm_eval in GUILE became much more elaborate to deal with byte code
(2.2) and JIT compilation (3.0). This means that scm_eval has more
overhead for single shot code:
* setup temporary storage for bytecode/JIT'd x86 code
* run up and down the syntax tree applying optimizations
* other magic that compiler folks do to make things run faster
The Scheme expressions for stencils aren't generalized code; they are
just a device-independent description of the output. In particular,
they have no advanced construct (loops, conditionals, tail calls,
variable bindings, variable references), also, they are run only
once. So all the work that scm_eval does to produce faster code is
just overhead.
The change makes it explicit that the data is just literal data, and
does the one thing to specialize it from device-independent to
device-specific, which is replacing symbols with their definitions
from output-ps.scm
Because output expression do not pass through eval anymore, we stop
quoting symbol and list values.
Backend implementors should take the following changes into account:
* placebox is removed. Instead each stencil expression is surrounded
by settranslation and resettranslation
* ly:make-paper-outputter takes a single function as argument. The
function takes the Scheme expression, for example,
(circle 10 0.1 #t)
as argument.
* A paper-outputter no longer is associated with a module. For the SVG
backend, this is solved by creating some backend-specific
expressions (set-paper, set-unit-length) which the eval-svg function
treats specially.
Markup/stencil implementors should take the following changes into
account:
* Stencil expressions are no longer passed through the eval
function. This means that all inner (quasi)quoting should be
removed.
Tested
lilypond -dbackend=svg input/regression/les-nereides
Timing
In verbose mode, the backend output phase will print timing. This
timing leads to the following data for (MSDM-reduced, 2Ghz CPU):
Current master
- Guile 1.8: 0.74s
- Guile 2.2: 4.73s
- Guile 3.0: 2.49s
This commit
- Guile 1.8: 0.80s
- Guile 2.2: 1.41s
- Guile 3.0: 1.20s
Basically `(path ...) is already quasi-quoted, so there is no reason to quote
the symbol round (as it is already quoted).
Well, but there was.
`round
=> round
`'round
=> (quote round)
This extra quote was necessary in 2.20.
Also you will get an error for
line 150 where we have
`(,@',(concatenate path-final))
So we first quasi-quote something that is already quasi-quoted, then we create
a list, use an unquote splice operator (,@), which basically evaluates the
expression to a list and then gives the entries of the list instead of the
list (note we are CREATING a list first just to splice something into it –
instead of this we can simply do ,(concatenate path-final)), then we are
quoting the whole thing we just unquoted again to add another unquote, which
does not work as the last quote was not a quasi-quote.
So to get it to work closest to what’s in the file we’d need to do
(,@`,(concatenate path-final))
Or alternatively
,`(,@`,(concatenate path-final))
But much more intelligent would be simply doing this:
,(concatenate path-final)
Yes, in 2.22, and in 2.20 you are right that it
can be simplified, but to ',(concatenate path-final)
with an extra quote at the beginning.
Anyway, here is a largely simplified version of this
snippet:
\version "2.22.1"
#(use-modules (ice-9 match))
#(set-object-property! 'curvature-factor 'backend-type? number?)
vibrato =
#(define-music-function (amplitudes wave-length) (list? number?)
#{
\once \override TrillSpanner.normalized-endpoints =
#ly:spanner::calc-normalized-endpoints
\once \override TrillSpanner.curvature-factor = 0.35
\once \override TrillSpanner.stencil =
#(let* ((n-amplitudes-1 (1- (length amplitudes))))
(grob-transformer
'stencil
(lambda (grob original)
(if
(ly:stencil? original)
(match-let* (((left . right) (ly:grob-property grob
'normalized-endpoints))
(left-idx (inexact->exact (round (*
n-amplitudes-1 left))))
(right-idx (inexact->exact (round (*
n-amplitudes-1 right))))
(sublist (match (drop (take amplitudes
(1+ right-idx))
left-idx)
((one) (list one one))
(lst lst)))
(original-ext (ly:stencil-extent original X))
(len (interval-length original-ext))
((start . end) original-ext)
(position-increment (/ len (1- (length
sublist))))
(thickness (* (ly:grob-property grob
'thickness 1.0)
(ly:staff-symbol-line-thickness grob)))
(factor (ly:grob-property grob
'curvature-factor)))
(make-path-stencil
(append
`(moveto ,start 0.0)
(let loop ((position start)
(tail sublist)
(last-exact start)
(current-sign 1)
(acc '()))
(if (>= position end)
(reverse! acc)
(match-let* ((next-position (+ position
wave-length))
(intermediate1 (+ position (*
wave-length factor)))
(intermediate2 (+ position (*
wave-length (- 1 factor))))
(from-last (- position last-exact))
((previous-height next-height . _)
tail)
(height (* current-sign
(interval-index
(cons previous-height next-height)
(+ -1 (*
2 (/ from-last position-increment))))))
(path-component `(curveto
,intermediate1 ,height
,intermediate2 ,height
,next-position 0.0))
(new-acc (append-reverse path-component
acc)))
(if (>= from-last position-increment)
(loop next-position
(cdr tail)
(+ last-exact position-increment)
(- current-sign)
new-acc)
(loop next-position
tail
last-exact
(- current-sign)
new-acc))))))
thickness
1
1
#f))
'()))))
#})
{
\vibrato #'(0.5) #0.5
c'2\startTrillSpan d' e'\stopTrillSpan
}
{
\vibrato #'(0.5 2.0) #0.5
c'2\startTrillSpan d' e'\stopTrillSpan
}
{
\override TrillSpanner.thickness = 2
\vibrato #'(0.0 2.0) #3.0
c'1\startTrillSpan d' \break
e' e'\stopTrillSpan
}
{
\override TrillSpanner.bound-details.left.padding = -2
\vibrato #'(0.5 0.5 8 0.0) #0.8
c'1\startTrillSpan d' \break
e' e'\stopTrillSpan
}
{
\override TrillSpanner.bound-details.left.padding = -2
\vibrato #'(2.5 3.5 8 0.0) #0.8
c'1\startTrillSpan d' \break
e' e'\stopTrillSpan
}
Best regards,
Jean