Re: Drawing boxes around grobs
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
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
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
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
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
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