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 01:43:12 -0700
User-agent: Roundcube Webmail/1.4.2

On 2020-08-07 10:19 pm, Werner LEMBERG wrote:
Consider the following chord:

  { <a d'\harmonic a''> }

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).

Looking up the LSR I couldn't find a generic solution that isn't an
ad-hoc trickery, thus I'm grateful for further help.

Does something like this help?

(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.)

%%%%
\version "2.20.0"

Grouping_Parenthesis_engraver =
#(lambda (context)
  (let ((paren #f))
    (define (process-item engraver grob source)
      (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)))))
    (make-engraver
      (acknowledgers
        ((item-interface engraver grob source)
          (process-item engraver grob source)))
      ((process-acknowledged 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)
                 (ly:grob-property (car elems-list) 'font-size 0)))
            (set! paren #f)))))))

%% Code copied from output-lib.scm unmodified:
#(define (parenthesize-elements 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 (car stencils))
         (rp (cadr stencils))
         (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 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
    (ly:stencil-scale stencil 1 y-scale)
    (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]