lilypond-user
[Top][All Lists]
Advanced

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

Re: TupletBrackets edge thickness


From: haddad
Subject: Re: TupletBrackets edge thickness
Date: Mon, 12 Aug 2024 12:53:03 +0200

Dear Thomas,

Of course, this is the solution.
Although this is not an imortant feature, ie just esthetic and not that standard, it would be great to have implemented the controls of these edges in the tupletbracket properties.

Thank you all for all your fine and enlighting effrots and solutions.

Best
K

On 2024-08-11 23:19, 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



reply via email to

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