That is really beautiful. Thank you. I have been giving myself a crash
course in scheme and was also getting somewhat closer to a solution
using a glissando event. Then the internet went down. And low and behold
it woke up to your response.
So this is almost what I want. And I need to dissect your code a bit
more (again, still wrapping my head around scheme). Maybe I can adapt
it. My ultimate goal is to specify the gradient within the given note
length (as opposed to giving a new color directive for every note. This
is where it gets tricky. In my current attempt (drowning in the deep
end), it is a bit tricky because you cannot change colors in the middle
of a path directive. So you need to combine several markups (as in my
original example). I was piecing together stuff I found on LSR and in
the user archive and was also having a huge problem with alignment. My
current code is pasted below. It is a mess, but getting there. I just
was reading about returning markup definitions in hopes that I could
iterate through the gradient and build the markup that way.
En fin, I will study your code. Like I said, it is almost exactly what I
want except I want the gradient within the note length. Of course, any
help in that direction will be much appreciated.
Best,
Michael
#(set-global-staff-size 16)
\layout {
indent = 0.0\cm
\context {
\Staff
% \override NoteHead.transparent =##t
\override StaffSymbol.line-count = #1
\override Glissando.minimum-length = #0
\override Glissando #'bound-details = #'((right (attach-dir . 0)
(end-on-accidental . #f) (padding . 0.)) (left (attach-dir . 0) (padding
. 0.)))
\remove "Clef_engraver"
\remove "Time_signature_engraver"
\stemDown
}
\context {
\Voice
\consists "Horizontal_bracket_engraver"
}
}
glissWidth = #1 %<< global variable for glissando width
#(define (path-gliss handle)
(lambda (grob)
(if (ly:stencil? (ly:line-spanner::print grob))
(let* ((stencil (ly:line-spanner::print grob))
(X-ext (ly:stencil-extent stencil X))
(Y-ext (ly:stencil-extent stencil Y))
(width (interval-length X-ext))
(height (interval-length Y-ext))
(lefty (cdr (assoc 'Y (ly:grob-property grob 'left-bound-info))))
(righty (cdr (assoc 'Y (ly:grob-property grob
'right-bound-info))))
(deltay (- righty lefty))
(dir (if (> deltay 0) 1 -1)))
(ly:stencil-translate
(grob-interpret-markup grob
(markup
;(#: tiny (format "~a" (ly:grob-properties grob)))
;(format "~a" (cdr (assoc 'Y (ly:grob-property grob
'left-bound-info))))
;(#: tiny (format "~a" handle))
(#:combine
(#:override
(cons (quote line-cap-style) (quote square))
(#:path glissWidth
(list (list 'moveto 0 -5)
(list 'lineto (* (- width 1.1) 0.5) -5))))
(#:override
(cons (quote line-cap-style) (quote square))
(#:with-color
(list 0.5 0.5 0.5)
(#:path glissWidth
(list (list 'moveto (* (- width 0.1) 0.5) -5)
(list 'lineto (- (* width 1) 1.1) -5)))))
(#:override
(cons (quote line-cap-style) (quote square))
(#:with-color
(list 0.8 0.5 0.5)
(#:path glissWidth
(list (list 'moveto 0 1)
(list 'lineto (* width 0.5) 1)))))
)))
(if (> dir 0)
(cons (interval-start X-ext) (+ (interval-start Y-ext) 0.1))
(cons (interval-start X-ext) (+ (interval-start Y-ext)
height)))))
#f)))
#(define (add-gliss m)
(case (ly:music-property m 'name)
((NoteEvent) (set! (ly:music-property m 'articulations)
(append (ly:music-property m 'articulations)
(list (make-music (quote GlissandoEvent)))))
m)
(else #f)))
addGliss = #(define-music-function (parser location music)
(ly:music?)
(map-some-music add-gliss music))
\new Score
\with {
%proportionalNotationDuration = #(ly:make-moment 1/16)
%\override SpacingSpanner.strict-note-spacing = ##t
%\override SpacingSpanner.uniform-stretching = ##t
}
<<
\new Staff
<<
\repeat unfold 32 { \repeat unfold 63 { s16 \noBreak } s16 \break }
{\time 4/4 \override Glissando.breakable = ##t
\override Glissando.after-line-breaking = ##t
\addGliss {
\override Glissando #'stencil = #(path-gliss '(0 0))
b'16 b'16 b'8 b'4 \override Staff.Beam.color =
#(x11-color 'grey60) b'8 b'16 b'16 ~ \once \override
NoteColumn.glissando-skip = ##t b'16 b'16 b'8
}}
>>
>>
On 01/30/2018 03:32 PM, Thomas Morley wrote:
2018-01-30 6:19 GMT+01:00 Michael Winter <mwin...@unboundedpress.org>:
A bit more here. I think I can fake this in a markup... See example pasted
below. My scheme skilz are minimal. I would like yo do this interpolating
between the x position of adjacent notes. So maybe I can do this as a custom
beam stencil. or some kind of spanner. Basically I want a scheme function
that will give me the position of a given note and the next note... Thanks!
\relative c'' {
s64
-\markup {
\combine
\override #'(line-join-style . miter)
\with-color #(x11-color 'grey60)
\path #2
#'((moveto 0 0)
(lineto 0.3 0)
(closepath)
)
\combine
\override #'(line-join-style . miter)
\with-color #(x11-color 'grey40)
\path #2
#'((moveto 0.3 0)
(lineto 0.6 0)
(closepath))
\override #'(line-join-style . miter)
\with-color #(x11-color 'grey20)
\path #2
#'((moveto 0.6 0)
(lineto 0.9 0)
(closepath))
}
}
On 01/29/2018 06:27 PM, Michael Winter wrote:
Hello...
I have tried quite a few hacks, but nothing really suitable.
What I really want is to simple draw a line beneath the staff that has a
grey scale gradient such that for each note, I give a target value.
Most of what I have tried involves doing this in increments with
overlapping spanners, I also tried the code in this thread:
https://lists.nongnu.org/archive/html/lilypond-user/2016-10/msg00097.html
I think the answer is doing this with svg directives since in the svg
documentation there are directives for linear gradients, but I do not know
how to build the function to use svg directives and such that the target
greyscale value is reached at the x-position of a given notehead.
Also, ideally I would be able to use spacer rests to give intermediary
values along the way, since the curve is actually not linear.
Thanks in advance and my apologies if I have been unclear.
Best,
Michael
Hi Michael,
not sure I've got you right.
Probably the quick hack below may give you a starting point.
It will not work with spacers though, because they don't cause a NoteColumn.
Cheers,
Harm
#(define (make-filled-box-stencil-list x-coords half-thick colors rl)
(if (null? (cdr x-coords))
rl
(make-filled-box-stencil-list
(cdr x-coords)
half-thick
(cdr colors)
(cons
(stencil-with-color
(make-filled-box-stencil
(cons (car x-coords) (cadr x-coords))
(cons (- half-thick) half-thick))
(car colors))
rl))))
\version "2.19.65"
foo =
\override TextSpanner.stencil =
#(lambda (grob)
(let* ((ncs (ly:grob-object grob 'note-columns))
(nc-ls
(if (ly:grob-array? ncs)
(ly:grob-array->list ncs)
'()))
(sys (ly:grob-system grob))
(nc-exts
(map
(lambda (nc)
(ly:grob-extent nc sys X))
nc-ls))
(left-info
(ly:grob-property grob 'left-bound-info))
(right-info
(ly:grob-property grob 'right-bound-info))
(thick (ly:grob-property grob 'thickness 1))
(x-coords
(map
(lambda (e)
(- e (assoc-get 'X left-info)))
`(
,(assoc-get 'X left-info)
,@(map
interval-center
(drop-right (drop nc-exts 1) 1))
,(assoc-get 'X right-info))))
(ls (iota (1- (length x-coords)) 20 20))
(color-gradient
(assoc-get 'color-gradient (ly:grob-property grob 'details) '(1)))
;; overkill below ...
(safe-color-gradient-ls
(append
color-gradient
(make-list (length x-coords) (last color-gradient))))
(color
(assoc-get 'color (ly:grob-property grob 'details)))
(colors
(map
(lambda (n)
(x11-color (string->symbol (format #f "~a~a" (or color
'grey) n))))
safe-color-gradient-ls)))
(apply
ly:stencil-add
(make-filled-box-stencil-list x-coords thick colors '()))))
{
\override TextSpanner.thickness = 0.5
%% make sure color and it's gradient exists, otherwise all's black
\override TextSpanner.details.color = #'grey
\override TextSpanner.details.color-gradient = #'(60 40 20)
\foo
c''2\startTextSpan
d''
e''
f''\stopTextSpan
}
{
\override TextSpanner.thickness = 0.5
\override TextSpanner.details.color = #'LightCyan
\override TextSpanner.details.color-gradient = #'(2 3 4)
\foo
c''2\startTextSpan
d''
e''
f''\stopTextSpan
}
_______________________________________________
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user