%% LSR: http://lsr.di.unimi.it/LSR/Item?id=1016 %% Oultliner defs: %% Credits Harm => http://lilypond.1069038.n5.nabble.com/Outliner-markup-command-tt185810.html#a185946 #(define (lists-map function ls) "Apply @var{function} to @var{ls} and all of it sublists. First it recurses over the children, then the function is applied to @var{ls}." (if (list? ls) (set! ls (map (lambda (y) (lists-map function y)) ls)) ls) (function ls)) #(define (uncolor-stencil stil) "Delete colors from stencil @var{stil}" (let* ((x-ext (ly:stencil-extent stil X)) (y-ext (ly:stencil-extent stil Y)) (stil-expr (ly:stencil-expr stil)) (get-caddr-if-condition (lambda (e) (if (and (list? e) (member 'color e)) ;; the stencil-expr of a colored stencil is of type ;; (list 'color (list r g b) (list rest-of-stencil-expr)) ;; Thus we can be sure that (caddr e) is valid ;; Even for an empty-stencil it evaluates to '() (caddr e) e)))) (ly:make-stencil (lists-map get-caddr-if-condition stil-expr) x-ext y-ext))) %% If LSR is upgrade to 2.20, please check whether this version %% of`stencil-whiteout-box-outline' is in the source. #(define*-public (stencil-whiteout-box-outline stil #:optional (thickness 0.3) (color white) (angle-increments 16) (radial-increments 1)) "This function works by creating a series of white or @var{color} stencils radially offset from the original stencil with angles from 0 to 2*pi, at an increment of @code{angle-inc}, and with radii from @code{radial-inc} to @var{thickness}. @var{thickness} is how big the white outline is, as a multiple of line-thickness. @var{radial-increments} is how many copies of the white stencil we make on our way out to thickness. @var{angle-increments} is how many copies of the white stencil we make between 0 and 2*pi." (if (or (not (positive? angle-increments)) (not (positive? radial-increments))) (begin (ly:warning "Both angle-increments and radial-increments must be positive numbers.") stil) (let* ((2pi 6.283185307) (angle-inc (/ 2pi angle-increments)) (radial-inc (/ thickness radial-increments))) (define (circle-plot ang dec radius original-stil new-stil) ;; ang (angle) and dec (decrement) are in radians, not degrees (if (<= ang 0) new-stil (circle-plot (- ang dec) dec radius original-stil (ly:stencil-add new-stil (ly:stencil-translate original-stil (cons (* radius (cos ang)) (* radius (sin ang)))))))) (define (radial-plot radius original-stil new-stil) (if (<= radius 0) new-stil (ly:stencil-add new-stil (radial-plot (- radius radial-inc) original-stil (circle-plot 2pi angle-inc radius original-stil empty-stencil))))) (let ((whiteout-expr (ly:stencil-expr (stencil-with-color ;;;; `uncolor-stencil' applied (radial-plot thickness (uncolor-stencil stil) empty-stencil) color)))) (ly:stencil-add (ly:make-stencil `(delay-stencil-evaluation ,(delay whiteout-expr))) stil))))) #(define-markup-command (outliner layout props thickness color arg) (number? color? markup?) #:category other #:properties ((angle-increments 16) (radial-increments 1)) (stencil-whiteout-box-outline (interpret-markup layout props arg) (* thickness (ly:output-def-lookup layout 'line-thickness)) color angle-increments radial-increments)) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% A new G clef defs: clef-henle = #(ly:make-stencil ;; path line thickness is set to 0.001 `(path 0.001 ;; path coordinates (moveto 0.00 0.45 curveto 0.00 2.12 2.22 2.45 2.22 3.70 curveto 2.22 3.70 2.22 4.19 2.01 4.19 curveto 1.90 4.19 1.15 3.95 1.51 1.90 lineto 2.06 -1.75 curveto 2.13 -2.15 2.00 -2.83 1.20 -2.83 curveto 0.70 -2.82 0.50 -2.50 0.50 -2.15 curveto 0.50 -1.90 0.72 -1.65 0.95 -1.65 curveto 1.21 -1.65 1.36 -1.80 1.36 -2.05 curveto 1.36 -2.18 1.22 -2.40 0.95 -2.41 curveto 0.90 -2.41 0.80 -2.43 0.80 -2.47 curveto 0.80 -2.57 1.00 -2.68 1.20 -2.68 curveto 1.50 -2.68 2.05 -2.53 1.91 -1.65 lineto 1.30 2.40 curveto 0.92 4.40 1.90 4.71 1.96 4.71 curveto 2.20 4.71 2.36 4.00 2.36 3.55 curveto 2.36 1.62 0.28 1.78 0.28 0.15 curveto 0.28 -1.27 2.50 -1.34 2.50 -0.05 curveto 2.50 0.76 1.07 0.82 1.07 0.05 curveto 1.07 -0.25 1.10 -0.34 1.44 -0.61 curveto 1.54 -0.68 1.47 -0.68 1.45 -0.68 curveto 1.24 -0.68 0.83 -0.34 0.83 0.14 curveto 0.83 0.60 1.20 1.05 1.70 1.05 curveto 2.40 1.05 2.70 0.40 2.70 0.05 curveto 2.70 -0.60 2.28 -1.11 1.40 -1.11 curveto 0.70 -1.11 0.00 -0.50 0.00 0.45 closepath) ;; path cap style round ;; path join style round ;; path filled? #t or #f #t) ;; horizontal extent (cons 0 2.7) ;; vertical extent (cons -2.8 4.7)) %% Example: #(set-global-staff-size 30) some-music = \score { \relative { \tempo "Allegro" c'_( d e f g a b c) \bar "|." } \layout { indent = 0 \context { \Staff %%% Apply a new G clef ('outliner' works fine here too): \override Clef.stencil = #(lambda (grob) (let ((sz (ly:grob-property grob 'font-size 0.0))) (ly:stencil-scale clef-henle 1 1))) } } } \header { title = \markup { \with-color #yellow %% 'ouliner' with x11 color: \outliner #3 #(x11-color 'orange) { Some music } } subtitle = \markup { %% 'ouliner' with rgb color: \outliner #2 #(rgb-color 1 0.5 0.5) { \with-color #cyan { with a } \with-color #white funny \with-color #red look } } } %% Define a score as a markup %% in order to be able to apply 'outliner': \markup\left-column { \with-color #white \outliner #1.3 #(x11-color 'black) \score { \some-music } \vspace #2 \fill-line\bold\fontsize #2 { \combine \with-color #(x11-color 'DimGrey) \outliner #1.5 #(x11-color 'DimGrey) "Or shadowed:" \translate #'(0.05 . 0.1) \with-color #white "Or shadowed:" } \vspace #1 \combine \with-color #(x11-color 'DimGrey) \outliner #1 #(x11-color 'DimGrey) \score { \some-music } \translate #'(0.05 . 0.1) \with-color #white \score { \some-music } } \paper { tagline = ##f }