%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % http://lists.gnu.org/archive/html/lilypond-user/2016-03/msg00328.html % By Abraham Lee, refactored to a more convenient function by Sharon Rosner % further edited by Harm % Thanks to Aaron and Jean for their help. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% If excecution time gets worse you may try to go for a simpler %% estimation of the length by calculating the linear distance between %% the bows endpoints. Therefore comment %% (len (bezier-approx-length cpt 0 1)) %% and uncomment the lines above in `variable-bow-thickness'. %% --Harm \paper { tagline = ##f } #(define (bezier-curve control-points t) "Given a Bezier curve of arbitrary degree specified by @var{control-points}, compute the point at the specified position @var{t}." (if (< 1 (length control-points)) (let ((q0 (bezier-curve (drop-right control-points 1) t)) (q1 (bezier-curve (drop control-points 1) t))) (cons (+ (* (car q0) (- 1 t)) (* (car q1) t)) (+ (* (cdr q0) (- 1 t)) (* (cdr q1) t)))) (car control-points))) #(define (bezier-approx-length control-points from to) "Given a Bezier curve of arbitrary degree specified by @var{control-points}, compute its approximate arc length between the positions @var{from} and @var{to}." (let* ((steps 10) (params (iota steps from (/ (- to from) (1- steps)))) (points (map (lambda (x) (bezier-curve control-points x)) params)) (length (fold (lambda (a b prev) (+ prev (ly:length (- (car a) (car b)) (- (cdr a) (cdr b))))) 0 (drop points 1) (drop-right points 1)))) ; Need to support negative length when the range is inverted. (if (< from to) length (- length)))) #(define (variable-bow-thickness min-l max-l min-t max-t) (lambda (grob) (let* ((cpf (ly:grob-property-data grob 'control-points)) (cpt (ly:grob-property grob 'control-points)) ;(cp0 (car cpt)) ;(cp3 (cadddr cpt)) ;(dx (- (car cp3) (car cp0))) ;(dy (- (cdr cp3) (cdr cp0))) ;(len (ly:length dx dy)) (len (bezier-approx-length cpt 0 1)) (thickness (cond ((< len min-l) min-t) ((> len max-l) max-t) (else (+ min-t (* (- len min-l) (/ (- max-t min-t) (- max-l min-l)))))))) (ly:grob-set-property! grob 'thickness thickness) (ly:grob-set-property! grob 'control-points (ly:unpure-call cpf grob))))) music = \relative c' { \cadenzaOn c16[( d]) ^\( c[(\) d^\( e]) c[(\) d^\( e f]) c[( d e f g])\) \bar "" \break \set tieWaitForNote = ##t c,4~ e~ g~ c~ e~ g~ \bar "|." } \score { \music \header { piece = "Thickness = 1.2 (default)" } } \score { \music \header { piece = "Thickness = 2.7 (fixed)" } \layout { \override Slur.thickness = #2.7 \override PhrasingSlur.thickness = #2.7 \override Tie.thickness = #2.7 } } \score { \music \header { piece = "Thickness = 1 to 3 (variable)" } \layout { \override PhrasingSlur.after-line-breaking = #(variable-bow-thickness 6 25 1 3) \override Slur.after-line-breaking = #(variable-bow-thickness 6 25 1 3) \override Tie.after-line-breaking = #(variable-bow-thickness 6 18 1 2) } } \score { { \override Slur.after-line-breaking = #(variable-bow-thickness 1 2 1 33) \shape #'((10 . 0) (0 . 0) (0 . 0) (0 . 0) ) Slur b1( b') b1-\shape #'((10 . 0) (0 . 0) (0 . 0) (0 . 0)) ( b') } \header { piece = "Results of \\shape are respected." } }