Score:Outliner

Zur Navigation springen Zur Suche springen

Dieses Markup-Kommando versieht einen Text mit einer Umrandung, deren Dicke und Farbe frei gewählt werden kann.

Scheme-Code

#(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)))

#(define*-public (stencil-whiteout-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-outline
    (interpret-markup layout props arg)
    (* thickness (ly:output-def-lookup layout 'line-thickness))
    color
    angle-increments
    radial-increments))