[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Instrument names and smallest possible bounding box
From: |
Kieren MacMillan |
Subject: |
Re: Instrument names and smallest possible bounding box |
Date: |
Sun, 17 Jan 2016 09:53:28 -0500 |
Hi all,
On Jan 17, 2016, at 6:24 AM, Malte Meyn <address@hidden> wrote:
> LilyPond tries to center-align the instrument names. Long names which
> don’t fit into the margin defined by indent (default 1.5cm (?)) are
> right-aligned (“Woodwind” in your example). This “mixing” behaviour
> looks odd, I agree. You can make the indent bigger so all names are
> center-aligned or change the alignment of instrument names globally
You can also use David N’s great custom-align function — see snippet, below.
Hope this helps!
Kieren.
p.s. David N: Is this code ready to present as a patch? I think it’s not only a
very useful function, it should be Lilypond’s default setting.
%%%% SNIPPET BEGINS
\version "2.19.35"
#(define (align-to-interval victim target dir)
"Align interval @var{victim} to interval @var{target} according
to the value of @var{dir}. If @var{dir} is a number, use it to orient
both intervals. If @var{dir} is a pair, use the @code{car} for the
victim and the @code{cdr} for the target."
(let ((v-dir (if (number? dir) dir (car dir)))
(t-dir (if (number? dir) dir (cdr dir))))
(coord-translate
victim
(- (interval-index target t-dir)
(interval-index victim v-dir)))))
#(define (within-interval? point interval)
"Does interval @var{interval} enclose number @var{num}?"
(and
(interval-sane? interval)
(not (< point (car interval)))
(not (> point (cdr interval)))))
#(define (custom-align grob)
(let* ((system (ly:grob-system grob))
(elements (ly:grob-array->list
(ly:grob-object system 'elements)))
(elements (filter grob::is-live? elements))
(text-grobs
(filter
(lambda (e) (grob::has-interface e 'system-start-text-interface))
elements))
;; A delimiter is an initial barline, bracket, brace.
(delims
(filter
(lambda (elt)
(grob::has-interface elt 'system-start-delimiter-interface))
elements))
;; To determine which delimiters affect our grob, we
;; unfortunately have to calculate its Y-position and
;; that of the delimiters!
(text-grobs-delims-list
(map (lambda (tg)
(cons tg
(list
(remove
(lambda (d)
(not (within-interval?
(ly:grob-property tg 'Y-offset)
(ly:grob-extent d system Y))))
delims))))
text-grobs))
(delim-extent-list
(lambda (delim-list)
(map
(lambda (d) (ly:grob-extent d system X))
delim-list)))
; Return a list of text grobs and their associated delimiter extents
; if we have no delimiters (as will happen with a single staff), use
; the left extent of the (unoffset) text grob itself as a basis.
(text-grobs-delim-extents
(map
(lambda (tgdl)
(cons (car tgdl)
(if (null? (cadr tgdl))
(let ((me-ext (ly:grob-extent (car tgdl) system X)))
(list (cons (car me-ext) (car me-ext))))
(delim-extent-list (cadr tgdl)))))
text-grobs-delims-list))
; combine extents
(text-grobs-total-delim-extents
(map (lambda (tgde)
(cons (car tgde)
(reduce interval-union
'()
(cdr tgde))))
text-grobs-delim-extents))
; assumption?
(representative-delim-extent
(cdar text-grobs-total-delim-extents))
; In order to calculate how much to move our name, we first need
; to construct a list of target positions for all grobs.
(bar-line-width 0.1) ; Ugh.
(target
(map (lambda (tg)
(let ((len (interval-length (ly:grob-extent tg system X))))
(cons tg
(cons (- (cdr representative-delim-extent)
bar-line-width)
(+ (- (cdr representative-delim-extent) bar-line-width)
len)))))
text-grobs))
(target
(map
(lambda (re)
(cons (car re)
(coord-translate
(cdr re)
(ly:side-position-interface::x-aligned-side (car re)))))
target))
(longest
(car
(sort target
(lambda (x y) (> (interval-length (cdr x))
(interval-length (cdr y)))))))
(target
(map
(lambda (x)
(cons (car x)
(align-to-interval ;align-interval-on-other
(cdr x) (cdr longest)
(ly:grob-property (car x) 'self-alignment-X 0))))
target))
; determine overlaps of target positioning with delimiters
(overlap
(map
(lambda (x y)
(cons (car x)
(interval-intersection (cdr x) (cdr y))))
target
text-grobs-total-delim-extents))
(overlap
(filter (lambda (x) (interval-sane? (cdr x)))
overlap))
(largest-overlap
(if (null? overlap)
0.0
(apply max
(map (lambda (x) (interval-length (cdr x))) overlap))))
(right-padding
(ly:grob-property grob 'padding 0.3))
(my-extent (ly:grob-extent grob system X))
; X offset returned will displace grob's extent to match
; the target inc. any overlap with delimiters and padding.
(X-offset
(- (car (assoc-get grob target))
(car my-extent)
largest-overlap
right-padding)))
X-offset))
\layout {
indent = 1\in
\context {
\Score
\override InstrumentName.X-offset = #custom-align
\override InstrumentName.padding = #0.5
}
}
\score {
<<
\new Staff \with { instrumentName = "very long name" }
{ R1 \break R1 }
\new StaffGroup <<
\new Staff \with { instrumentName = "short" }
{ R1 \break R1 }
\new StaffGroup <<
\new Staff \with { instrumentName = "Group A" }
{ R1 \break R1 }
\new Staff \with { instrumentName = "Group B" }
{ R1 \break R1 }
>>
>>
>>
}
%%%% SNIPPET ENDS
________________________________
Kieren MacMillan, composer
‣ website: www.kierenmacmillan.info
‣ email: address@hidden
Re: Instrument names and smallest possible bounding box, Malte Meyn, 2016/01/17
Re: Instrument names and smallest possible bounding box, mskala, 2016/01/17
Re: Instrument names and smallest possible bounding box, Kieren MacMillan, 2016/01/17