lilypond-user
[Top][All Lists]
Advanced

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

Re: DurationLine avoiding RehearsalMarks


From: Thomas Morley
Subject: Re: DurationLine avoiding RehearsalMarks
Date: Fri, 15 Apr 2022 10:13:14 +0200

Am Mi., 13. Apr. 2022 um 17:57 Uhr schrieb Jean Abou Samra <jean@abou-samra.fr>:
>
> Le 13/04/2022 à 17:03, Thomas Morley a écrit :
> > Am Di., 12. Apr. 2022 um 11:54 Uhr schrieb Jean Abou Samra 
> > <jean@abou-samra.fr>:
> >> Le 12/04/2022 à 11:16, Thomas Morley a écrit :
> > [...]
> >>> In many details DurationLine was tailored after Glissando and
> >>> Glissando _is_ effected by the breathing sign.
> > [...]
> >
> >> Well, if the goal is to have DurationLine similar to Glissando,
> >> how about reusing line-spanner-interface code? I haven't reviewed
> >> the code very thoroughly, but I assumed there was a difference
> >> warranting a different code path. If you put
> >> ly:line-spanner::calc-{left,right}-bound-info in
> >> DurationLine.{left,righ}-bound-info, that gives you X values for free
> >> in the bound info properties. Would that solve the problem?
> > If I go for ly:line-spanner::calc-{left,right}-bound-info then
> >
> > \layout {
> >     \context {
> >       \Voice
> >       \consists Duration_line_engraver
> >     }
> > }
> >
> > { b1\- }
> >
> > errors with
> >      "programming error: extremal broken spanner's bound has no parent
> > vertical axis group"
> > More complex examples may add:
> >      "programming error: bound item has no parent vertical axis group"
> > Both coming from `ly:line-spanner::calc-right-bound-info' based upon
> > `Line_spanner::calc_bound_info' in /lily/line-spanner.cc
> >
> > As a mere user I'd say: "Nice error-message, but why should I care...?"
> >
> > As a programmer, I doubt the example above can be made working with
> > ly:line-spanner::calc-right-bound-info.
> > At least, I don't know how.
>
>
> Oh, I'm sorry, I missed that detail of my own code. A DurationLine will
> always be horizontal, thus you can and should use
> ly:horizontal-line-spanner::calc-{left,right}-bound-info (with 'horizontal'
> in the name).  The difference is that the functions without 'horizontal'
> try to compute vertical positions. This falls apart here, for understandable
> reasons: the right bound of your DurationLine is a NonMusicalPaperColumn,
> so how would one tell where the line should end vertically?

Using ly:horizontal-line-spanner::calc-{left,right}-bound-info makes
for huge simplifications.
Alas, it introduces a minor and reintroduces a major problem.

The minor: the X-value depends now on attach-dir. For the start of the
DurationLine this is ofcourse RIGHT. But if starting at a skip,
left-bound is PaperColumn there we would want LEFT. Can be fixed by
accurate conditions. Count it as done.

The major: `ly:horizontal-line-spanner::calc-right-bound-info' and
`unbroken-or-last-broken-spanner?' (and friends) don't agree what's
the last part of the spanner.
To illustrate:

\version "2.23.7"

\layout {
  \context {
    \Voice
    \consists "Duration_line_engraver"
  }
}

{
 \override DurationLine.bound-details.right.foo =
   "I am last part (bound-details)"
 \override DurationLine.bound-details.right-broken.foo =
   "I am not last part (bound-details)"

 \override DurationLine.after-line-breaking =
 #(lambda (grob)
   (pretty-print
     (if (unbroken-or-last-broken-spanner? grob)
         "I am last part (unbroken-or-last-broken-spanner?)"
         "I am not last part (unbroken-or-last-broken-spanner?)"))
   (pretty-print
     (assoc-get 'foo (ly:horizontal-line-spanner::calc-right-bound-info grob))))

 b1\-
}

=>
"I am last part (unbroken-or-last-broken-spanner?)"
"I am not last part (bound-details)"

The problem occurs if we have a broken DurationLine with end-items
running to the very end of the score.
To fix it one would again need something like:

{
  \override DurationLine.bound-details =
  #(grob-transformer 'bound-details
    (lambda (grob orig)
     (if (end-broken-spanner? grob)
         (cons
           (cons 'right-broken
             (cons '(end-style . arrow) (assoc-get 'right-broken orig)))
           orig)
         orig)))
  b1\-
  \break
  s1
  \break
  s1
  \bar "|."
}

Or like \lastEndStyle which you cleared with

commit 46671d13257f6ad68d1778a1cc850e59116c856a
Author: Jean Abou Samra <jean@abou-samra.fr>
Date:   Wed Dec 29 00:16:46 2021 +0100

    Fix broken spanner functions

    They were broken (pun intended) on spanners of which one bound is a
    non-musical column at a system boundary.  For example,
    unbroken-or-last-broken-spanner? would return false on a spanner
    running to the NonMusicalPaperColumn at the end of a score.  This
    fixes the known issue with duration lines running to the end of the
    piece, and will be needed in a refactoring of spanner-placement
    treatment for balloon-interface.

    While at it, document these functions.

This is unfortunate. Any chance making
`ly:horizontal-line-spanner::calc-right-bound-info' and friends
identify the last spanner-part correctly, i.e. like
`unbroken-or-last-broken-spanner?'
?

At any rate, many thanks for the hint to
ly:_horizontal:-line-spanner::calc-left/right-bound-info.
I may remember wrong, but I think I tried
ly:line-spanner::calc-left/right-bound-info already while implementing
DurationLine and excluded it for the known reasons, but was not aware
that ly:_horizontal:-line-spanner::calc-left/right-bound-info exists
at all.
Well, my bad, though, any chance to document
  ly:horizontal-line-spanner::calc-left-bound-info-and-text
  ly:horizontal-line-spanner::calc-left/right-bound-info
  ly:line-spanner::calc-left/right-bound-info
in IR 4. Scheme functions?

> >> If there is a reason to keep DurationLine calculations separate, you
> >> could go for using ly:generic-bound-extent. The line-spanner-interface
> >> uses its C++ equivalent internally.
> > Didn't try this so far.
> > But the description:
> > "Function: ly:generic-bound-extent grob common
> > Determine the extent of grob relative to common along the x axis,
> > finding its extent as a bound when it a has bound-alignment-interfaces
> > property list set and otherwise the full extent."
> > is kryptic to say the least.
>
>
> It's in a sense similar to the (so far nonexistent/C++-only) function
> ly:axis-group-interface::staff-extent we discussed, except that it
> doesn't filter grobs for having a certain grob in their ancestry,
> but for having one of certain interfaces, captured in the
> bound-alignment-interfaces property. E.g., for NonMusicalPaperColumn,
> this property defaults to '(break-alignment-interface), which means
> that
>
>    (ly:generic-bound-extent [NonMusicalPaperColumn] [System])
>
> gives you the extent of the elements of the NonMusicalPaperColumn
> that are part of a BreakAlignment, i.e. grobs with the
> break-aligned-interface,
> like BarLine, KeySignature, etc., but not those that are outside
> of a BreakAlignment, i.e. those having the break-*aligned*-interface
> (tricky difference, I know, I always need to look up which is 'alignable'
> and which is 'aligned' ...), namely MetronomeMark, RehearsalMark, ...
> There are some slightly fussy details, but that's the idea. Is that
> clear?

Your description is far better than the doc-string. There I stumbled
across "extent as a bound", with not the slightest idea what this
could mean, especially compared with "the full extent".

In general I find typical usage examples like
>    (ly:generic-bound-extent [NonMusicalPaperColumn] [System])
very helpful.

Best,
  Harm



reply via email to

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