[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Line-breaking with non-aligned barlines
From: |
Thomas Morley |
Subject: |
Re: Line-breaking with non-aligned barlines |
Date: |
Mon, 29 Oct 2018 00:51:56 +0100 |
Am So., 28. Okt. 2018 um 08:07 Uhr schrieb Werner LEMBERG <address@hidden>:
>
> > A minimal would be:
> >
> > \paper { indent = 0 ragged-right = ##t }
> >
> > {
> > \override Beam.breakable = ##t
> > s2. s8
> > c'8[
> > \break
> > c'16]
> > }
> >
> > Not sure I'd call it a bug.
>
> IMHO, it is a bug.
>
> > But I'd love to have a method to change this behaviour easily,
> > currently there's none.
>
> I fully agree.
>
> > Though, you can dive into Beam deeply and reset 'beam-segments with
> > custom values. Leading to: [...]
>
> Very nice! If possible, this should be made the default. I even
> suggest to completely drop the current behaviour since I can't
> envision a situation where you really want this.
>
>
> Werner
Hi Werner,
I'll open an issue on the tracker.
As workaround a much more elaborated coding below.
It's now possible to process complex Beams, affecting them before and
after a line-break.
Not yet coded is affecting the beam-segments of the middle-beam-parts
of a more than two times broken Beam.
Though, it will not happen very often. At least I hope so.
\version "2.19.82"
\paper { indent = 0 ragged-right = ##t }
#(define (devide-at-vertical-count beam-dir dir-pred lst)
;; 'lst' is supposed to be the list of beam-segments
;; A new list is returned where all entries of same vertical-count are wrapped
;; into a sublist.
;; Relying on dir-pred those sublists appear in reversed order.
;; This is important to get have 'new-beams' working on the correct
;; beam-segment. Empty sublists would disturb, they are removed.
(remove
null?
(map
(lambda (i)
(let ((inner-list
(filter
(lambda (el) (eqv? (assoc-get 'vertical-count el) i))
lst)))
(cond ((eq? dir-pred 'first-beam)
(reverse inner-list))
((eq? dir-pred 'last-beam)
inner-list))))
;; TODO Unlikely to have more than 10 beam-segments.
;; Better than removing empty lists afterwards would be to find the correct
;; beam-count, though. Too lazy right now ...
(iota 10 0 (- beam-dir)))))
#(define (new-beams amounts dir-predicate lst)
;; Returns a new list suitable for 'beam-segments.
;; Relying on 'dir-predicate' left or right side of the beam-segments are
;; changed.
(append-map
(lambda (a el)
(cons
(list (caar el)
(let* ((hor (assoc-get 'horizontal (car el))))
(cons 'horizontal
(cond ((eqv? dir-predicate LEFT)
(cons (+ a (car hor)) (cdr hor)))
((eqv? dir-predicate RIGHT)
(cons (car hor) (+ a (cdr hor))))
(else hor)))))
(cdr el)))
amounts
lst))
shortenBrokenBeams =
#(define-music-function (amount)(list?)
"
Shorten broken Beams at line-break.
We get the 'beam-segments, rebuilding it modified.
The 'beam-segments-property is an alist of type:
'(((vertical-count . 0) (horizontal 3.865018 . 5.93))
((vertical-count . 1) (horizontal 3.865018 . 5.93)))
`vertical-count' is the beam-count, which may grow negative.
`horizontal' is the X-extent relative to 'System's 'line-width.
Regrettable this means changing `horizontal' will need to be adjusted
frequently. P.e. if Beam-direction changes.
@var{amount} is a list containing number-lists. Their values are applied to
the beam-segments at line-break.
At line-end they are applied to the right. At line-start to the left.
An empty sublist will trigger default beaming.
Limitations:
Does not work for the inner beam-parts of more than two times broken Beams.
"
#{
%% Add \once ?
\override Beam.beam-segments =
#(lambda (grob)
(let* ((middle-of-broken-beam?
(and (eq? (grob::name (ly:spanner-bound grob LEFT))
'NonMusicalPaperColumn)
(eq? (grob::name (ly:spanner-bound grob RIGHT))
'NonMusicalPaperColumn)))
(first-of-broken-beam?
(and (eq? (grob::name (ly:spanner-bound grob RIGHT))
'NonMusicalPaperColumn)
(not (eq? (grob::name (ly:spanner-bound grob LEFT))
'NonMusicalPaperColumn))))
(last-of-broken-beam?
(and (eq? (grob::name (ly:spanner-bound grob LEFT))
'NonMusicalPaperColumn)
(not (eq? (grob::name (ly:spanner-bound grob RIGHT))
'NonMusicalPaperColumn))))
(beam-segments (ly:beam::calc-beam-segments grob))
(dir (ly:grob-property grob 'direction)))
(cond
(middle-of-broken-beam?
(ly:message
"Tweaking left and right ends of a beam-segments is not yet coded.
Returning default.")
beam-segments)
(first-of-broken-beam?
;; uncomment to watch 'beam-segments' of first beam-part
;(format #t "\nBEAM-SEGMENTS of FIRST beam-part:\n~y" beam-segments)
(if (null? (car amount))
beam-segments
(new-beams
(car amount)
RIGHT
(devide-at-vertical-count dir 'first-beam beam-segments))))
(last-of-broken-beam?
;; uncomment to watch 'beam-segments' of last beam-part
;(format #t "\nBEAM-SEGMENTS of LAST beam-part:\n~y" beam-segments)
(if (null? (cadr amount))
beam-segments
(new-beams
(cadr amount)
LEFT
(devide-at-vertical-count dir 'last-beam beam-segments))))
(else beam-segments))))
#})
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% EXAMPLES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\markup "Beam at start of line"
{
\override Beam.breakable = ##t
s8*5
\shortenBrokenBeams
%% empty sublist are possible
%#'(()(0 2.239 2.239))
%#'((0 -1.852)())
#'((0 -1.852)(0 2.239 2.239))
c'16[
c'
c'8.
c'16
\break
c'32
c'8
c'16
c']
}
{
\override Beam.breakable = ##t
s8*7
\shortenBrokenBeams
#'(()(0 1))
c''8[
\break
c''16]
}
{
\override Beam.breakable = ##t
s16*15
\shortenBrokenBeams
#'((0 -1.2)())
c''16[
\break
c''8]
}
Cheers,
Harm