lilypond-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Outliner markup command


From: Thomas Morley
Subject: Re: Outliner markup command
Date: Fri, 15 Jan 2016 23:58:17 +0100

2016-01-13 22:14 GMT+01:00 Thomas Morley <address@hidden>:
> 2016-01-13 16:17 GMT+01:00 Paul Morris <address@hidden>:
>>> On Jan 12, 2016, at 6:09 PM, Thomas Morley <address@hidden> wrote:
>>>
>>> Though, there might be a bug in `stencil-whiteout-outline', Paul cc-ed.
>>>
>>> Look at:
>>>
>>> \markup \stencil
>>> #(stencil-whiteout-outline
>>>  (make-filled-box-stencil '(-1 . 1) '(-1 . 1))
>>>  0.5
>>>  red
>>>  16
>>>  1)
>>>
>>> \markup \stencil
>>> #(stencil-whiteout-outline
>>>  (stencil-with-color (make-filled-box-stencil '(-1 . 1) '(-1 . 1)) green)
>>>  0.5
>>>  red
>>>  16
>>>  1)
>>>
>>> First one is ok.
>>> But in the second one the color from the stencil is taken (green) and
>>> the specified (red) is ignored.
>>> Will investigate more detailed the upcoming days.
>>
>> Huh, that’s odd…  stencil-whiteout-box works as expected (see below), so the 
>> problem must indeed be in stencil-whiteout-outline.
>>
>> -Paul
>
> Yep.
>
> In this part of the code for stencil-whiteout-outline you try to apply
> a color to a stencil, which is derived from the original one,
>
>                 (ly:stencil-expr
>                  (stencil-with-color
>                   (radial-plot thickness stil empty-stencil)
>                   color))
>
> Though, if this original stencil is colored already, it will fail.
> See:
>
> #(define my-box-stil (make-filled-box-stencil '(-1 . 1) '(-1 . 1)))
>
> \markup {
>   \stencil #my-box-stil
>   \stencil #(stencil-with-color my-box-stil green)
>   \stencil #(stencil-with-color (stencil-with-color my-box-stil green) red)
>      }
>
> Thinking about it, I came to the conclusion it's desired behaviour.
> Otherwise the following wouldn't work:
>
> \markup \with-color #red { foo \with-color #green bar buzz }
>
> So far the reason, now looking forward to make it work anyway.
>
>
> Cheers,
>   Harm

The only way I've found, is to delete all color-settings from the stencil-expr.
Anyone with a better idea?

Below you'll find what I did.
Fixes `stencil-whiteout-outline' by applying newly defined `uncolor-stencil'
Also adding `outliner'-markup-command

\version "2.18.2"  %% sic !!

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

%%%%%%%%%%%%%%%%%%
%% EXAMPLES
%%%%%%%%%%%%%%%%%%

%% nested colors
\markup
  \outliner #2 #(x11-color 'orange)
  \with-color #(rgb-color 0.6 0.2 0.6)
  \column {
    \with-color #yellow \line { what ever this might be }
    \line { \with-color #cyan "Some" \with-color #blue "Music" }
    \line { what else this might be }
}

%% stencil-whiteout-outline with a precolored stencil
\markup
  \stencil
  #(stencil-whiteout-outline
    (stencil-with-color
      (make-filled-box-stencil '(-1 . 1) '(-1 . 1))
      green)
    0.5
    red
    16
    1)

%% simple stencils, colored/uncolored
#(define my-box-stil (make-filled-box-stencil '(-1 . 1) '(-1 . 1)))

\markup {
  \stencil
    #my-box-stil
  \stencil
    #(stencil-with-color my-box-stil green)
  \stencil
    #(stencil-with-color
      (uncolor-stencil
        (stencil-with-color my-box-stil green))
      red)
  \stencil
    #(stencil-with-color empty-stencil red)
}


Cheers,
  Harm



reply via email to

[Prev in Thread] Current Thread [Next in Thread]