lilypond-user
[Top][All Lists]
Advanced

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

Re: TupletBrackets edge thickness


From: Karim Haddad
Subject: Re: TupletBrackets edge thickness
Date: Mon, 12 Aug 2024 13:44:10 +0200

Dear Thomas,

Sorry to bother you again with this. Your solution works like a charm. However, 
apparently in the case of a reduced magstep of a Staff it ceases to work. Any 
idea?
I am joining the example here

THanx
Best to you all

Karim


On Sun, Aug 11, 2024 at 11:19:58PM +0200, Thomas Morley wrote:
> Am Sa., 10. Aug. 2024 um 19:11 Uhr schrieb Lukas-Fabian Moser <lfm@gmx.de>:
> 
> > Hi Kieren,
> >
> > Left to do: We probably also should modify the extents of the resulting 
> > stencil to avoid collisions...
> >
> > If the thickness of the edge lines are expanded *inwards*, wouldn’t the 
> > original extent still be accurate enough to use?
> >
> > Yes, good idea. But then we see that for thick lines, LilyPond's rounded
> > line tips become a problem (actually, the problem wouldn't be just as
> > serious with box-formed line tips):
> >
> > So we should probably replace the edge line by a box, more precisely: by a
> > polygon with the correct slope at least on the connecting side. Sigh.
> >
> > Re-posting the source nevertheless, since in my first attempt I forgot
> > that TupletBrackets can point upwards or downwards.
> >
> > \version "2.24.0"
> >
> > #(define (list-add! lst k x)
> >    (list-set! lst k (+ (list-ref lst k) x)))
> >
> > {
> >   \override TupletBracket.stencil =
> >   #(grob-transformer
> >     'stencil
> >     (lambda (grob stil)
> >       (let*
> >        ((expr (ly:stencil-expr stil))
> >         (xext (ly:stencil-extent stil X))
> >         (yext (ly:stencil-extent stil Y))
> >         (lines (cdaddr expr))
> >         (right (first lines))
> >         (left (second lines))
> >         (thick (second right))
> >         (dir (- (ly:grob-property grob 'direction)))
> >         (new-thick 0.7)  ;; adjust at will
> >         (offset (/ (- new-thick thick) 2)))
> >
> >        (list-set! right 1 new-thick)
> >        (list-add! right 2 (- offset))         ; x1
> >        (list-add! right 3 (* dir offset))     ; y1
> >        (list-add! right 4 (- offset))         ; x2
> >
> >        (list-set! left 1 new-thick)
> >        (list-add! left 2 offset)              ; x1
> >        (list-add! left 3 (* dir offset))      ; y1
> >        (list-add! left 4 offset)              ; x2
> >
> >        (ly:make-stencil expr xext yext))))
> >
> >   \tupletDown
> >   \tuplet 3/2 { c'4 d' c''' }
> >   \tupletUp
> >   \tuplet 3/2 { c'4 d' e' }
> > }
> >
> > And of course: The *proper* way to handle all of this would be to just
> > swallow the pill and re-implement the a modified TupletBracket stencil in
> > Scheme.
> >
> > Lukas
> >
> 
> Here my take on it.
> Some effort is done to identify the wings drawing lines: not going for the
> position in the stencil-list, but for matching their height with the
> relevant grob edge-height. Hopefully safer...
> 
> \version "2.24.3"
> 
> #(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 (tuplet-bracket::line-parts grob stencil)
>   "Examine @code{TupletBracket.stencil), accumulate lines used to draw
> @code{TupletBracket}, divided into wings and horizontal lines."
>   (if (ly:stencil-empty? stencil)
>       '()
>       (let* ((lines '())
>              (edge-height (ly:grob-property grob 'edge-height))
>              (stil-expr (ly:stencil-expr stencil)))
> 
>         ;; accumulate the bracket-drawing lines in `lines`
>         (when (pair? stil-expr)
>           (lists-map
>             (lambda (l)
>               (when (and (list? l)
>                          (eq? (list-ref l 0) 'draw-line)
>                          ;; Broken TupletBracket may have collapsed wings,
>                          ;; don't catch them. Deal with them when this
> procedure
>                          ;; is called.
>                          (not (zero?
>                                 (- (- (list-ref l 2) (list-ref l 4))
>                                    (- (list-ref l 3) (list-ref l 5))))))
>                 (set! lines (cons l lines)))
>               l)
>             stil-expr))
> 
>         (call-with-values
>           (lambda ()
>             (partition
>               (lambda (l)
>                 (let ((height (- (list-ref l 3) (list-ref l 5))))
>                   ;; TODO looking at height is probably not safe enough.
>                   ;; Avoid rounding issues
>                   (or
>                      (> 0.0000001
>                         (abs (- (abs height) (abs (car edge-height)))))
>                      (> 0.0000001
>                         (abs (- (abs height) (abs (cdr edge-height))))))))
>               lines))
>           (lambda (x y)
>             (list (cons 'wings x) (cons 'horizontals y)))))))
> 
> #(define (tuplet-bracket::wing-thickness wing-thickness)
>   "Examine @code{TupletBracket.stencil), replace the wings by a polygon
> mimicking enlarged thickness."
>  (grob-transformer 'stencil
>   (lambda (grob orig)
>    (let* ((parts (tuplet-bracket::line-parts grob orig))
>           (raw-wings (assoc-get 'wings parts)))
>      (if (not (pair? raw-wings))
>          orig
>          (let* (
>           (horizontals (assoc-get 'horizontals parts))
>           (slopes
>            (map
>             (lambda (l)
>               (/ (- (list-ref l 5) (list-ref l 3))
>                  (- (list-ref l 4) (list-ref l 2))))
>             horizontals))
>           (wings
>            (cond ((middle-broken-spanner? grob) '(#f #f))
>                  ((first-broken-spanner? grob)
>                    (append raw-wings (list #f)))
>                  ((end-broken-spanner? grob)
>                    (cons #f raw-wings))
>                  (else raw-wings)))
>           (grob-thick
>            (ly:grob-property grob 'thickness))
>           (staff-line-thick
>            (ly:staff-symbol-line-thickness (ly:grob-object grob
> 'staff-symbol)))
>           (thick (* grob-thick staff-line-thick))
>           (edge-height (ly:grob-property grob 'edge-height))
>           (shorten-pair (ly:grob-property grob 'shorten-pair '(0 . 0)))
>           (dir (ly:grob-property grob 'direction)))
> 
>     (ly:make-stencil
>      (lists-map
>       (lambda (l)
>        (cond
>         ((equal? l (car wings))
>           (let* ((start-x (list-ref l 2))
>                  (start-y (+ (list-ref l 3) (* wing-thickness (car
> slopes))))
>                  (shorten-pair (car shorten-pair))
>                  (edge-height (car edge-height)))
>             `(polygon
>               ,(list
>                 start-x (list-ref l 3)
>                 (+ start-x wing-thickness) start-y
>                 (+ start-x wing-thickness) (+ start-y (* -1 dir
> edge-height))
>                 start-x (+ (list-ref l 3) (* dir -1 edge-height)))
>               ;; take `thick` as blot-diameter to match rounded line ends
>               ,thick
>               #t)))
>         ((equal? l (cadr wings))
>           (let* ((end-x (list-ref l 2))
>                  (start-x (- end-x wing-thickness))
>                  (start-y (* start-x (cadr slopes)))
>                  (end-y (list-ref l 5))
>                  (edge-height (cdr edge-height)))
>             `(polygon
>                ,(list
>                  end-x end-y
>                  end-x (- end-y (* dir -1 edge-height))
>                  start-x start-y
>                  start-x (+ start-y (* dir -1 edge-height)))
>                ,thick
>                #t)))
>         (else l)))
>       (ly:stencil-expr orig))
>      (ly:stencil-extent orig X)
>      (ly:stencil-extent orig Y))))))))
> 
> %%%%%%%%%%%%%%%%%%%%%%%%%%%%
> %% Examples
> %%%%%%%%%%%%%%%%%%%%%%%%%%%%
> 
> \layout {
>   \override TupletBracket.stencil = #(tuplet-bracket::wing-thickness 1)
> }
> 
> {
>   \tuplet 3/2 { b4 b b } \tuplet 3/2 { b'' b b } \tuplet 3/2 { b b b'' }
>   \tupletDown
>   \tuplet 3/2 { b4 b b } \tuplet 3/2 { b'' b b } \tuplet 3/2 { b b b'' }
> }
> 
> {
>   \tuplet 3/2 { b1 b''2 \break b4 b \break b''2 b }
> }
> 
> 
> Best,
>   Harm



-- 
Karim Haddad

Music Representations Team, IRCAM
Research and development manager.
email   : karim.haddad@ircam.fr
webpage : http://karim.haddad.free.fr

Attachment: tupletEdge.ly
Description: Text Data


reply via email to

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