Re: Drawing boxes around grobs

2020-02-10 Thread 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

Re: Drawing boxes around grobs

2020-02-09 Thread Paolo Prete
On Sat, Feb 8, 2020 at 10:36 PM Thomas Morley 
wrote:

> Am Sa., 8. Feb. 2020 um 22:20 Uhr schrieb Paolo Prete <
> paolopr...@gmail.com>:
> >
> >
>
>
> 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


Re: Drawing boxes around grobs

2020-02-08 Thread 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



Re: Drawing boxes around grobs

2020-02-08 Thread Thomas Morley
Am Sa., 8. Feb. 2020 um 22:20 Uhr schrieb Paolo Prete :
>
>
>
> On Sat, Feb 8, 2020 at 9:06 PM Thomas Morley  wrote:
>>
>> Am Sa., 8. Feb. 2020 um 19:26 Uhr schrieb Paolo Prete :
>> >
>
>
>
>
>
>>
>> {
>> \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



Re: Drawing boxes around grobs

2020-02-08 Thread Paolo Prete
On Sat, Feb 8, 2020 at 9:06 PM Thomas Morley 
wrote:

> Am Sa., 8. Feb. 2020 um 19:26 Uhr schrieb Paolo Prete <
> paolopr...@gmail.com>:
> >
>





> {
> \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


Re: Drawing boxes around grobs

2020-02-08 Thread Thomas Morley
Am Sa., 8. Feb. 2020 um 19:26 Uhr schrieb Paolo Prete :
>
> 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