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 11:45:08 +0200

Am Fr., 15. Apr. 2022 um 10:39 Uhr schrieb Jean Abou Samra <jean@abou-samra.fr>:
>
>
>
> Le 15/04/2022 à 10:13, Thomas Morley a écrit :
> > 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?'
> > ?
>
>
>
> Ah, this one is showing up again. Yes, this is not too hard to
> fix (but please allow me some time).
>
No problem.
If you don't mind I'll open an issue for it with the code-example above.
Meanwhile I found a different workaround, without the need to have the
apply an extra override.
If testings suceed, I'll upload a patch with the new code for DurationLine.
The workaround could be removed later easily.
>
>
>
> > 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?
>
>
>
> It's not your bad: they didn't exist when you implemented DurationLine :-)
> They later came into existence with
>
> commit 817d656cecb0f899ff6e7d1b5e900a5517c31f69
> Author: Jean Abou Samra <jean@abou-samra.fr>
> Date:   Sun Nov 21 16:36:16 2021 +0100
>
>      Make user tweaks to line spanner Y positions relative to relevant
> group
>
>      For example, the value of an adjustment to
>      VoiceFollower.bound-details.left.Y is relative to the start note's
>      staff, not to the end note's one.
>
>      This requires some work.  The basic problem is that for this to work
>      we need the line spanner to compute its own coordinate relative to the
>      chosen refpoint.  This does not work for line spanners that are
>      side-positioned, such as DynamicTextSpanner: their coordinate depends
>      on their very stencil (side positioning is skyline-based). That's
>      logical: if the Y positions are already fixed relative to the staff,
>      it does not make sense to side-position afterwards.  In general, there
>      are a number of differences in handling between horizontal line
>      spanners, such as TextSpanner, DynamicTextSpanner, etc., and
>      non-horizontal line spanners, like Glissando, FingerGlideSpanner and
>      VoiceFollower.  This takes the stance of being explicit and introduces
>      a horizontal-line-spanner-interface, which is a subset of the
>      line-spanner-interface.  Horizontal line spanners now use callbacks
>      from this interface to compute bound info.  These callbacks don't try
>      to calculate Y values.  This also obviates having to set Y to 0 in
>      bound-details for horizontal line spanners.  The repartition of the
>      feature set is that while horizontal line spanners can be
>      side-positioned, the non-horizontal ones can have their Y positions
>      computed automatically.
>
>      In the future, the horizontal-line-spanner-interface may prove useful
>      for smarter cross-staff handling.
>
>      Closes #5229
>
>
> Re documenting: will take a look when I have more time.
>
>
>
> >>>> 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.
>
>
> Will take a look at improving the docstring, too.
>
> Cheers,
> Jean

Take your time and good luck.

Best,
  Harm



reply via email to

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