Drawing boxes around grobs

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

Drawing boxes around grobs

Paolo Prete-3
Hello,

The documentation shows this example:

\override TextScript.stencil = #(make-stencil-boxer 0.1 0.3 ly:text-interface::print) c'4^"foo"


Is it possible to adapt it for other grobs too? I would like to use it for TupletBracket, OttavaBracket, Notehead and Script, but it seems that it works for TextScript only

Thanks!
P



Reply | Threaded
Open this post in threaded view
|

Re: Drawing boxes around grobs

Thomas Morley-2
Am Sa., 8. Feb. 2020 um 19:26 Uhr schrieb Paolo Prete <[hidden email]>:

>
> Hello,
>
> The documentation shows this example:
>
> \override TextScript.stencil = #(make-stencil-boxer 0.1 0.3 ly:text-interface::print) c'4^"foo"
>
> (http://lilypond.org/doc/v2.19/Documentation/snippets/tweaks-and-overrides)
>
> Is it possible to adapt it for other grobs too? I would like to use it for TupletBracket, OttavaBracket, Notehead and Script, but it seems that it works for TextScript only
>
> Thanks!
> P

Afaict, it works for all grobs with a stencil.
Sometimes you will have to deal with undesired side-effects though.

{
\override TextScript.stencil =
  #(make-stencil-boxer 0.1 0.3 ly:text-interface::print)

\override Script.stencil =
  #(make-stencil-boxer 0.1 0.3 ly:script-interface::print)

\override NoteHead.stencil =
  #(make-stencil-boxer 0.1 0.3 ly:note-head::print)
  c'4^"foo"->

\override TupletBracket.stencil =
  #(make-stencil-boxer 0.1 0.8 ly:tuplet-bracket::print)
  \tuplet 3/2 { b4 4 4 }
}

The boxed NoteHead is wider, the stem-attachment does as before, i.e.
the Stem is placed at the border...
In this case tackle stem-attachment or better, don't let the boxed
stencil be wider. Which may lead to probably unwished collisions, if
done for with grobs.

Cheers,
  Harm

Reply | Threaded
Open this post in threaded view
|

Re: Drawing boxes around grobs

Paolo Prete-3


On Sat, Feb 8, 2020 at 9:06 PM Thomas Morley <[hidden email]> wrote:
Am Sa., 8. Feb. 2020 um 19:26 Uhr schrieb Paolo Prete <[hidden email]>:
>


 
 
{
\override TextScript.stencil =
  #(make-stencil-boxer 0.1 0.3 ly:text-interface::print)

\override Script.stencil =
  #(make-stencil-boxer 0.1 0.3 ly:script-interface::print)

\override NoteHead.stencil =
  #(make-stencil-boxer 0.1 0.3 ly:note-head::print)
  c'4^"foo"->

\override TupletBracket.stencil =
  #(make-stencil-boxer 0.1 0.8 ly:tuplet-bracket::print)
  \tuplet 3/2 { b4 4 4 }
}

The boxed NoteHead is wider, the stem-attachment does as before, i.e.
the Stem is placed at the border...
In this case tackle stem-attachment or better, don't let the boxed
stencil be wider. Which may lead to probably unwished collisions, if
done for with grobs.

Cheers,
  Harm


Thank you harm.
Is it possible to override/tweak the color of the boxer?

Best,
P

 
Reply | Threaded
Open this post in threaded view
|

Re: Drawing boxes around grobs

Thomas Morley-2
Am Sa., 8. Feb. 2020 um 22:20 Uhr schrieb Paolo Prete <[hidden email]>:

>
>
>
> On Sat, Feb 8, 2020 at 9:06 PM Thomas Morley <[hidden email]> wrote:
>>
>> Am Sa., 8. Feb. 2020 um 19:26 Uhr schrieb Paolo Prete <[hidden email]>:
>> >
>
>
>
>
>
>>
>> {
>> \override TextScript.stencil =
>>   #(make-stencil-boxer 0.1 0.3 ly:text-interface::print)
>>
>> \override Script.stencil =
>>   #(make-stencil-boxer 0.1 0.3 ly:script-interface::print)
>>
>> \override NoteHead.stencil =
>>   #(make-stencil-boxer 0.1 0.3 ly:note-head::print)
>>   c'4^"foo"->
>>
>> \override TupletBracket.stencil =
>>   #(make-stencil-boxer 0.1 0.8 ly:tuplet-bracket::print)
>>   \tuplet 3/2 { b4 4 4 }
>> }
>>
>> The boxed NoteHead is wider, the stem-attachment does as before, i.e.
>> the Stem is placed at the border...
>> In this case tackle stem-attachment or better, don't let the boxed
>> stencil be wider. Which may lead to probably unwished collisions, if
>> done for with grobs.
>>
>> Cheers,
>>   Harm
>
>
>
> Thank you harm.
> Is it possible to override/tweak the color of the boxer?
>
> Best,
> P
>
>

You could redefine box-stencil to take an additional color-argument.
Also stencil-boxer to take an optional color-argument:

#(define (box-stencil stencil thickness padding color)
  "Add a box around @var{stencil}, producing a new stencil."
  (let* ((x-ext (interval-widen (ly:stencil-extent stencil 0) padding))
         (y-ext (interval-widen (ly:stencil-extent stencil 1) padding))
         (y-rule
           (stencil-with-color
             (make-filled-box-stencil (cons 0 thickness) y-ext) color))
         (x-rule
           (stencil-with-color
             (make-filled-box-stencil
                  (interval-widen x-ext thickness) (cons 0 thickness)) color)))
    (set! stencil (ly:stencil-combine-at-edge stencil X 1 y-rule padding))
    (set! stencil (ly:stencil-combine-at-edge stencil X -1 y-rule padding))
    (set! stencil (ly:stencil-combine-at-edge stencil Y 1 x-rule 0.0))
    (set! stencil (ly:stencil-combine-at-edge stencil Y -1 x-rule 0.0))
    stencil))

#(define* (make-stencil-boxer thickness padding callback #:optional (color red))
  "Return function that adds a box around the grob passed as argument."
  (lambda (grob)
    (box-stencil (callback grob) thickness padding color)))

{
\override TextScript.stencil =
  #(make-stencil-boxer 0.1 0.3 ly:text-interface::print)

\override Script.stencil =
  #(make-stencil-boxer 0.1 0.3 ly:script-interface::print)

\override NoteHead.stencil =
  #(make-stencil-boxer 0.1 0.3 ly:note-head::print cyan)
  c'4^"foo"->

\override TupletBracket.stencil =
  #(make-stencil-boxer 0.1 0.8 ly:tuplet-bracket::print)
  \tuplet 3/2 { b4 4 4 }
}

Cheers,
  Harm

Reply | Threaded
Open this post in threaded view
|

Re: Drawing boxes around grobs

Aaron Hill
On 2020-02-08 1:36 pm, Thomas Morley wrote:

> #(define (box-stencil stencil thickness padding color)
>   "Add a box around @var{stencil}, producing a new stencil."
>   (let* ((x-ext (interval-widen (ly:stencil-extent stencil 0) padding))
>          (y-ext (interval-widen (ly:stencil-extent stencil 1) padding))
>          (y-rule
>            (stencil-with-color
>              (make-filled-box-stencil (cons 0 thickness) y-ext) color))
>          (x-rule
>            (stencil-with-color
>              (make-filled-box-stencil
>                   (interval-widen x-ext thickness) (cons 0 thickness))
> color)))
>     (set! stencil (ly:stencil-combine-at-edge stencil X 1 y-rule
> padding))
>     (set! stencil (ly:stencil-combine-at-edge stencil X -1 y-rule
> padding))
>     (set! stencil (ly:stencil-combine-at-edge stencil Y 1 x-rule 0.0))
>     (set! stencil (ly:stencil-combine-at-edge stencil Y -1 x-rule 0.0))
>     stencil))

You can restore the behavior of things like stem attachment by
outputting the modified stencil with the original extents:

%%%%
#(define (box-stencil stencil thickness padding color)
   "Add a box around @var{stencil}, producing a new stencil."
   (let* ((x-ext-orig (ly:stencil-extent stencil X))
          (y-ext-orig (ly:stencil-extent stencil Y))
          (x-ext (interval-widen x-ext-orig padding))
          (y-ext (interval-widen y-ext-orig padding))
          (y-rule
            (stencil-with-color
              (make-filled-box-stencil (cons 0 thickness) y-ext) color))
          (x-rule
            (stencil-with-color
              (make-filled-box-stencil
                   (interval-widen x-ext thickness) (cons 0 thickness))
color)))
     (set! stencil (ly:stencil-combine-at-edge stencil X 1 y-rule
padding))
     (set! stencil (ly:stencil-combine-at-edge stencil X -1 y-rule
padding))
     (set! stencil (ly:stencil-combine-at-edge stencil Y 1 x-rule 0.0))
     (set! stencil (ly:stencil-combine-at-edge stencil Y -1 x-rule 0.0))
     (ly:make-stencil (ly:stencil-expr stencil) x-ext-orig y-ext-orig)))
%%%%

Users of the function might want to choose between using the original
dimensions and the larger ones, so an additional parameter would
probably be necessary.


-- Aaron Hill

Reply | Threaded
Open this post in threaded view
|

Re: Drawing boxes around grobs

Paolo Prete-3
In reply to this post by Thomas Morley-2


On Sat, Feb 8, 2020 at 10:36 PM Thomas Morley <[hidden email]> wrote:
Am Sa., 8. Feb. 2020 um 22:20 Uhr schrieb Paolo Prete <[hidden email]>:
>
>


You could redefine box-stencil to take an additional color-argument.
Also stencil-boxer to take an optional color-argument:

#(define (box-stencil stencil thickness padding color)
  "Add a box around @var{stencil}, producing a new stencil."
  (let* ((x-ext (interval-widen (ly:stencil-extent stencil 0) padding))
         (y-ext (interval-widen (ly:stencil-extent stencil 1) padding))
         (y-rule
           (stencil-with-color
             (make-filled-box-stencil (cons 0 thickness) y-ext) color))
         (x-rule
           (stencil-with-color
             (make-filled-box-stencil
                  (interval-widen x-ext thickness) (cons 0 thickness)) color)))
    (set! stencil (ly:stencil-combine-at-edge stencil X 1 y-rule padding))
    (set! stencil (ly:stencil-combine-at-edge stencil X -1 y-rule padding))
    (set! stencil (ly:stencil-combine-at-edge stencil Y 1 x-rule 0.0))
    (set! stencil (ly:stencil-combine-at-edge stencil Y -1 x-rule 0.0))
    stencil))

#(define* (make-stencil-boxer thickness padding callback #:optional (color red))
  "Return function that adds a box around the grob passed as argument."
  (lambda (grob)
    (box-stencil (callback grob) thickness padding color)))

{
\override TextScript.stencil =
  #(make-stencil-boxer 0.1 0.3 ly:text-interface::print)

\override Script.stencil =
  #(make-stencil-boxer 0.1 0.3 ly:script-interface::print)

\override NoteHead.stencil =
  #(make-stencil-boxer 0.1 0.3 ly:note-head::print cyan)
  c'4^"foo"->

\override TupletBracket.stencil =
  #(make-stencil-boxer 0.1 0.8 ly:tuplet-bracket::print)
  \tuplet 3/2 { b4 4 4 }
}

Cheers,
  Harm


Thanks to Harm and Aaron.

At this point, is there a way to extend the box by setting four parameters separately: 

top, bottom, left, right

..., instead of the "padding" one ?
Something like:  

 #(make-stencil-boxer 0.1 #paddingLeft #paddingRight #paddingTop #paddingBottom ly:script-interface::print cyan)

Cheers,
P
Reply | Threaded
Open this post in threaded view
|

Re: Drawing boxes around grobs

Aaron Hill
On 2020-02-09 6:54 am, Paolo Prete wrote:

> At this point, is there a way to extend the box by setting four
> parameters
> separately:
>
> top, bottom, left, right
>
> ..., instead of the "padding" one ?
> Something like:
>
>  #(make-stencil-boxer 0.1 #paddingLeft #paddingRight #paddingTop
> #paddingBottom ly:script-interface::print cyan)
I've probably over-engineered this, but I adapted the CSS model for
padding [1] so you can specify it with anywhere from one to four values.
  Additionally, I made it an option whether you want the extents to be
expanded to contain the new stencil or to preserve the original extents.

[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/padding

%%%%
\version "2.19.83"

#(define (box-stencil stencil thickness padding color expand?)
   "Add a box around @var{stencil}, producing a new stencil."
   (define (css-style-padding padding)
     ;; padding => (top right bottom left)
     (cond
       ((or (null? padding) (eqv? #f padding)) '(0 0 0 0))
       ((number? padding) (make-list 4 padding))
       ((number-pair? padding)
         (list (car padding) (cdr padding)
               (car padding) (cdr padding)))
       ((and (number-list? padding) (<= (length padding) 4))
         (case (length padding)
           ((1) (make-list 4 (first padding)))
           ((2) (list (first padding) (second padding)
                      (first padding) (second padding)))
           ((3) (list (first padding) (second padding)
                      (third padding) (second padding)))
           (else padding)))
       (else
         (begin (ly:warning "Ignoring invalid padding: ~a" padding)
                '(0 0 0 0)))))
   (let* ((padding (css-style-padding padding))
          (padding-top (first padding))
          (padding-right (second padding))
          (padding-bottom (third padding))
          (padding-left (fourth padding))

          (x-ext-orig (ly:stencil-extent stencil X))
          (y-ext-orig (ly:stencil-extent stencil Y))
          (x-ext-inner
            (cons (- (interval-start x-ext-orig) padding-left)
                  (+ (interval-end x-ext-orig) padding-right)))
          (y-ext-inner
            (cons (- (interval-start y-ext-orig) padding-bottom)
                  (+ (interval-end y-ext-orig) padding-top)))
          (x-ext-outer (interval-widen x-ext-inner thickness))
          (y-ext-outer (interval-widen y-ext-inner thickness))
          (x-ext-new (if expand? x-ext-outer x-ext-orig))
          (y-ext-new (if expand? y-ext-outer y-ext-orig))

          (x-rule (make-filled-box-stencil (cons 0 thickness)
y-ext-inner))
          (y-rule (make-filled-box-stencil x-ext-outer (cons 0
thickness)))
          (box (stencil-with-color
            (ly:stencil-add
              (ly:stencil-translate-axis y-rule (interval-end
y-ext-inner) Y)
              (ly:stencil-translate-axis x-rule (interval-end
x-ext-inner) X)
              (ly:stencil-translate-axis y-rule (interval-start
y-ext-outer) Y)
              (ly:stencil-translate-axis x-rule (interval-start
x-ext-outer) X))
            color)))
     (ly:make-stencil
       (ly:stencil-expr (ly:stencil-add stencil box))
       x-ext-new y-ext-new)))

#(define* (make-stencil-boxer thickness padding callback
            #:optional (color red) (expand? #t))
   "Return function that adds a box around the grob passed as argument."
   (lambda (grob)
     (box-stencil (callback grob) thickness padding color expand?)))

{
   \override TextScript.stencil =
     #(make-stencil-boxer 0.2 '(0.2 1.4 0.6) ly:text-interface::print
magenta)
   \override Script.stencil =
     #(make-stencil-boxer 0.2 '(1.4 1 0.6 0.2)
ly:script-interface::print)
   \override NoteHead.stencil =
     #(make-stencil-boxer 0.2 '(0.6 0.2) ly:note-head::print cyan #f)
     c'4^"foo"->
   \override TupletBracket.stencil =
     #(make-stencil-boxer 0.4 0 ly:tuplet-bracket::print)
     \tuplet 3/2 { b4 4 4 }
}
%%%%


-- Aaron Hill

box-stencil.cropped.png (11K) Download Attachment