|
From: | Valentin Petzel |
Subject: | Re: Note head as a custom image chosen according to note duration |
Date: | Tue, 22 Nov 2022 00:13:29 +0100 |
Hello Jean,
the line
\once \override NoteHead.stencil = #ly:text-interface::print
tells Lilypond to derive the symbol it uses for the note head as if the note head was some sort of text object (changed the old syntax NoteHead #'stencil to the new prefered syntax NoteHead.stencil). Then
\once \override NoteHead.text =
\markup {
\general-align #Y #CENTER {
\epsfile #X #2 #"./custom.eps"
}
}
tells Lilypond what sort of text this text object has, which in this case uses the markup-command
\epsfile axis size file
to include an eps file. As Jean already said these properties NoteHead.stencil and NoteHead.text may either be actual values, or they may be callbacks, that is functions with the graphical object (grob) itself as argument.
(lambda (vars ...) body)
creates an anonymous function, so #(lambda (grob) ...) simply creates a function suitable for such callbacks. This callback can then choose the appearance depending on the duration of the NoteHead.
The duration of the NoteHead is not in fact a property of the grob, but of the music event that leads to creation of the grob, accessible from the grob by the "cause"-property. Thus Jean uses
(ly:event-property (event-cause grob) 'duration)
to get the duration of the note head and then uses different markups for different values.
That being said, in my opinion the whole route of going eps -> stencil -> markup -> stencil is overly complicated, instead we can skip the whole text-interface step and directly use the stencil generated from the eps-file:
customHead =
\once \override NoteHead #'stencil = #(ly:stencil-aligned-to (eps-file->stencil X 2 "custom.eps") Y CENTER)
{ e'4 f' \customHead g'4 }
Or with Jeans callback:
\version "2.22"
customHead =
\once \override NoteHead.stencil =
#(lambda (grob)
(ly:stencil-aligned-to
(case (ly:duration-log (ly:event-property (event-cause grob) 'duration))
((0) (eps-file->stencil X 2 "custom1.eps"))
((1) (eps-file->stencil X 2 "custom2.eps"))
((2) (eps-file->stencil X 2 "custom4.eps"))
((3) (eps-file->stencil X 2 "custom8.eps"))
(else empty-stencil))
Y CENTER))
{
\customHead c'1
\customHead c'2
\customHead c'4
\customHead c'8
}
Cheers,
Valentin
Am Montag, 21. November 2022, 19:07:22 CET schrieb Jean Abou Samra:
> Le 21/11/2022 à 13:43, Jean Faure a écrit :
>
> > Hi. The code below is a copy&paste, I do not quite understand what it
> > does. Can I modify it so that an image is chosen according to the
> > following note's duration? Like custom4.eps, custom8.eps?
> >
> >
> >
> > customHead = {
> > \once \override NoteHead #'stencil = #ly:text-interface::print
> > \once \override NoteHead #'text =
> > \markup {
> > \general-align #Y #CENTER {
> > \epsfile #X #2 #"./custom.eps"
> > }
> > }
> > }
> > { e'4 f' \customHead g'4 }
>
>
>
>
>
> Yes, use a callback for that:
>
>
> \version "2.22.2"
>
> customHead = {
> \once \override NoteHead.stencil = #ly:text-interface::print
> \once \override NoteHead.text =
> #(lambda (grob)
> #{
> \markup \general-align #Y #CENTER
> #(case (ly:duration-log (ly:event-property (event-cause
> grob) 'duration))
> ;; whole note:
> ((0) #{ \markup \epsfile #X #2 "custom1.eps" #})
> ;; half note:
> ((1) #{ \markup \epsfile #X #3 "custom2.eps" #})
> ;; quarter note:
> ((2) #{ \markup \epsfile #X #4 "custom4.eps" #})
> ;; eighth note:
> ((3) #{ \markup \epsfile #X #5 "custom8.eps" #})
> ;; Add more here if necessary (keeping the "else" line
> below).
> (else ""))
> #})
> }
>
> {
> \customHead c'1
> \customHead c'2
> \customHead c'4
> \customHead c'8
> }
>
>
>
>
> Have a look at these pages:
>
> https://lilypond.org/doc/v2.22/Documentation/extending/callback-functions
> https://extending-lilypond.readthedocs.io/en/latest/backend.html#understandi
> ng-callbacks
> Best,
> Jean
>
signature.asc
Description: This is a digitally signed message part.
[Prev in Thread] | Current Thread | [Next in Thread] |