lilypond-user
[Top][All Lists]
Advanced

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

Re: partially parenthizing a chord


From: Aaron Hill
Subject: Re: partially parenthizing a chord
Date: Sat, 08 Aug 2020 04:58:32 -0700
User-agent: Roundcube Webmail/1.4.2

On 2020-08-08 3:59 am, Werner LEMBERG wrote:
I would like to parenthesize the lower two notes of the chord.
There should be a single parenthesis to the left and right
(contrary to what `\parenthesize` does).

Does something like this help?

Yes, very nice!

(The logic here is for the engraver to generate a single
ParenthesesItem for any given timestep, while also modifying the
print routine to vertically scale the stencil to encapsulate the
elements.  For demonstration purposes, I have \consisted the
engraver at the Voice level so that each one can have its own set of
parentheses.)

I have one wish to improve the appearance of the parentheses: Would it
be possible to scale the parentheses glyphs (i.e., scaling
`ParenthesisItem.font-size`) according to the `y-scale` value?  Right
now, the parentheses are very thin horizontally.

This was a little tricky because there is a cart-and-horse problem. We need to know how big the parens are to determine scaling, but that locks in the font-size.

Here is a version that still relies on scaling, but does so in a hopefully more visually appealing manner. Note that I am using the square root of the y-scaling factor for the x-scaling factor, as 1:1 scaling made the parens too fat in my opinion.

%%%%
\version "2.20.0"

Grouping_Parenthesis_engraver =
#(lambda (context)
  (let ((paren #f))
    (define (process-item engraver grob)
      (let* ((cause (ly:grob-property grob 'cause))
             (paren? (and (ly:prob? cause)
                          (ly:event-property cause 'parenthesize #f))))
        (if paren?
          (begin
            (or (ly:grob? paren)
                (set! paren (ly:engraver-make-grob
                              engraver 'ParenthesesItem '())))
            (ly:pointer-group-interface::add-grob
              paren 'elements grob)))))
    (define (finalize-paren engraver)
      (if (ly:grob? paren)
        (let* ((elems-array (ly:grob-object paren 'elements))
               (elems-list (ly:grob-array->list elems-array))
               (refp (ly:grob-common-refpoint-of-array
                       (car elems-list) elems-array Y)))
          (ly:grob-set-parent! paren Y refp)
          (ly:grob-set-property! paren 'font-size
            (+ (ly:grob-property paren 'font-size 0)
               (apply max
                 (map
                   (lambda (grob)
                     (ly:grob-property grob 'font-size 0))
                   elems-list))))
          (set! paren #f))))
    (make-engraver
      (acknowledgers
        ((item-interface engraver grob source)
          (process-item engraver grob)))
      ((process-acknowledged engraver)
        (finalize-paren engraver)))))

%% Code copied from output-lib.scm and *modified*:
#(define (parenthesize-elements-scaled x y grob . rest)
  (let* ((refp (if (null? rest)
                   grob
                   (car rest)))
         (elts (ly:grob-array->list (ly:grob-object grob 'elements)))
         (get-friends
           (lambda (g)
             (let ((syms (ly:grob-property g 'parenthesis-friends '()))
                   (get-friend (lambda (s)
                                 (let ((f (ly:grob-object g s)))
                                   (cond
                                     ((ly:grob? f) (list f))
((ly:grob-array? f) (ly:grob-array->list f))
                                     (else '()))))))
               (apply append (map get-friend syms)))))
         (friends (apply append elts (map get-friends elts)))
         (x-ext (ly:relative-group-extent friends refp X))
         (stencils (ly:grob-property grob 'stencils))
         (lp (ly:stencil-scale (car stencils) x y))
         (rp (ly:stencil-scale (cadr stencils) x y))
         (padding (ly:grob-property grob 'padding 0.1)))
    (ly:stencil-add
     (ly:stencil-translate-axis lp (- (car x-ext) padding) X)
     (ly:stencil-translate-axis rp (+ (cdr x-ext) padding) X))))

%% Code copied from output-lib.scm and *modified*:
#(define (parentheses-item::print-scaled me)
  (let* ((elts (ly:grob-object me 'elements))
         (y-ref (ly:grob-common-refpoint-of-array me elts Y))
         (x-ref (ly:grob-common-refpoint-of-array me elts X))
         (stencil (parenthesize-elements-scaled 1 1 me x-ref))
         (sten-y-ext (ly:stencil-extent stencil Y))
         (elt-y-ext (ly:relative-group-extent elts y-ref Y))
         (y-center (interval-center elt-y-ext))
         (y-scale (/ (interval-length elt-y-ext)
                     (interval-length sten-y-ext))))
  (ly:stencil-translate
    (parenthesize-elements-scaled
      (sqrt y-scale) y-scale me x-ref)
    (cons
      (- (ly:grob-relative-coordinate me x-ref X))
      (- y-center (ly:grob-relative-coordinate me y-ref Y))))))

\layout {
  \context {
    \Score
    \remove "Parenthesis_engraver"
  }
  \context {
    \Voice
    \consists \Grouping_Parenthesis_engraver
    \override ParenthesesItem.stencil =
      #parentheses-item::print-scaled
  }
}

soprano = \fixed c'' {
  \override ParenthesesItem.color = #red
  \parenthesize dis4
  \parenthesize <b, e gis>2
  <\parenthesize a, \parenthesize c ees>4
}
alto = \fixed c' {
  \override ParenthesesItem.color = #blue
  <cis \parenthesize e \parenthesize a>4
  \parenthesize <d fis>2
  \parenthesize c4
}

\new Staff \voices 1,2 << \soprano \\ \alto >>
%%%%


-- Aaron Hill

Attachment: paren-engraver.cropped.png
Description: PNG image


reply via email to

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