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