Le samedi 11 février 2023 à 15:01 +0000, Werner LEMBERG a écrit :
> ```
> 
> I'm using the `\offsetPosition` command
> ([https://lsr.di.unimi.it/LSR/Item?id=748](https://lsr.di.unimi.it/LSR/Item?id=748)).
>   Unfortunately, it fails in
> a multi-staff, real-world piece: it has zero effect, and I don't know
> why.  What could be the cause for that?  If I had a hint, creating an
> MWE would perhaps be more straightforward...
> 
> Interestingly, using the 'deprecated' part of this snippet instead I
> get warnings like
> 
>   cyclic dependency: calculation-in-progress encountered for Slur.positions
> 
> but it actually works...



I can reproduce it by just adding `\break` in the original snippet.
It fails except on the first system. This is because it assumes
that Slur.control-points is still set to its original callback
at the time `after-line-breaking` is run, which isn't true if something
like `ly:side-position-interface::move-to-extremal-staff`, in 
`BarNumber.after-line-breaking`,
reads `control-points` earlier, making `(ly:grob-property-data grob 
'control-points)`
return the computed value. A good example of how `after-line-breaking`
can be fragile.

Try

```
\version "2.24.0"

%% http://lsr.di.unimi.it/LSR/Item?id=748

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% A function to modify the shape of slurs by offsetting the positions property
% from default control-point values. Setting either y1 or y2 to zero will leave
% that attachment-point unchanged. Syntax: \offsetPositions #'(y1 . y2)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

offsetPositions =
#(define-music-function (offsets) (pair?)
  #{
    \once \override Slur.control-points =
      #(lambda (grob)
         (match-let* ((((_ . y1) _ _ (_ . y2)) (ly:slur::calc-control-points 
grob)))
           (set! (ly:grob-property grob 'positions)
                 (cons (+ y1 (car offsets))
                       (+ y2 (cdr offsets))))
           (ly:slur::calc-control-points grob)))
  #})

\relative c'' {
  c4(^"default" c, d2)
  \offsetPositions #'(0 . 1)
  c'4(^"(0 . 1)" c, d2)
  \break
  \offsetPositions #'(0 . 2)
  c'4(^"(0 . 2)" c, d2)
  \bar "||"
  \break
  g4(^"default" a d'2)
  \offsetPositions #'(1 . 0)
  g,,4(^"(1 . 0)" a d'2)
  \offsetPositions #'(2 . 0)
  g,,4(^"(2 . 0)" a d'2)
}
```


I can see why the original snippet uses `after-line-breaking`: using
`ly:slur::calc-control-points` directly here is suboptimal (needs
updating if the default changes). The use of `ly:grob-set-property!`
isn't wonderful either. Unfortunately, the slur code would need to
be structured a bit differently to get rid of the latter one, although
you could, if you care enough and with a bit more effort, address
the former by creating a variant of `grob-transformer` passing the
raw original callback to the transformer instead of the value it computes.



Attachment: signature.asc
Description: This is a digitally signed message part

Reply via email to