Re: how to change extents of a grob?

2022-04-14 Thread David Kastrup
Werner LEMBERG  writes:

> Dear LilyPonders,
>
>
> I can get the extents of a grob with `ly:grob-extent`.  What is the
> corresponding Scheme function to set the extents?
>
> Or to ask in a different way: At the time when properties are
> processed and you have to manipulate stencils, changing the stencil of
> a grob doesn't change the extents of this grob, AFAICS.

You are not supposed to change stencils at all.  They are not entities
with identity.

It's like asking how to change the exponent of a floating point number.
Whatever ability on the machine level exists for that, it does not make
sense to export an interface.

> How can I adjust the extents at this stage to fit the dimensions of
> the stencil (even if LilyPond no longer needs and/or uses the values
> for positioning)?

Create a new stencil with different dimensions and use that.

-- 
David Kastrup



Re: how to change extents of a grob?

2022-04-14 Thread Werner LEMBERG


>> Or to ask in a different way: At the time when properties are
>> processed and you have to manipulate stencils, changing the stencil
>> of a grob doesn't change the extents of this grob, AFAICS.
> 
> You are not supposed to change stencils at all.  They are not
> entities with identity.
> 
> Create a new stencil with different dimensions and use that.

OK, thanks.


Werner



Custom Spanner with variable length sections

2022-04-14 Thread Dimitris Marinakis
I need a custom spanner that has x sections with different symbols. This is
going to be tricky so any help is appreciated.

I already have a hacky solution for fixed length spanners but it is pain to
maintain it. I'd like a more usable solution that can handle variable
lengths.

It would be nice to have control over the percentage that each section
takes. e.g. #'(20 30 50)
results: --***#

I imagine it would need to check the length of the section and divide it by
the X-extent of the symbol and then round the number to get the number of
symbols that fit inside the section.

The problem is that the code needs to check somehow if the surrounding
sections don't fill up or overflow to avoid missing symbols or collisions
between sections especially the inner ones. Trills are concatenated symbols
so they aren't always 100% of the computed width.

Maybe it would be useful to also allow separate symbols for each transition
between sections. That would help in some cases.

Also line breaks are as always a problem. Not only the line breaks must
work but also the pattern needs to apply for the whole spanner and not
repeat for each broken part.


Re: Custom Spanner with variable length sections

2022-04-14 Thread Kieren MacMillan
Hi Dimitris,

> I need a custom spanner that has x sections with different symbols. This is 
> going to be tricky so any help is appreciated.

https://github.com/davidnalesnik/lilypond-text-spanner-inner-texts

Hope that helps!
Kieren.


Re: bug in magnetic snapping lyrics engraver

2022-04-14 Thread Werner LEMBERG


> There is a problem with ligatures at the syllable boundaries (and
> kerning).  [...]  it is not sufficient to shift the right syllable
> in a syllable pair to the left.  Instead, the following should be
> done.  [...]

Meanwhile I could implement this :-)

I will submit a MR soon.


Werner



Re: bug in magnetic snapping lyrics engraver

2022-04-14 Thread Jean Abou Samra

Le 14/04/2022 à 17:39, Werner LEMBERG a écrit :

There is a problem with ligatures at the syllable boundaries (and
kerning).  [...]  it is not sufficient to shift the right syllable
in a syllable pair to the left.  Instead, the following should be
done.  [...]

Meanwhile I could implement this :-)

I will submit a MR soon.



How did you do that? Sorry to rain on your parade, but
I would not want you to put a lot of work in it if it
will not be of mergeable quality.

Jean





Re: how to change extents of a grob?

2022-04-14 Thread Jean Abou Samra

Le 14/04/2022 à 11:41, Werner LEMBERG a écrit :

Or to ask in a different way: At the time when properties are
processed and you have to manipulate stencils, changing the stencil
of a grob doesn't change the extents of this grob, AFAICS.

You are not supposed to change stencils at all.  They are not
entities with identity.

Create a new stencil with different dimensions and use that.

OK, thanks.




I believe you are talking about different things. You shouldn't mutate
the internal expression contained in a stencil, sure. But a grob does
have identity. I understood Werner's question as "how to get grob's
extents recomputed when I do (ly:grob-set-property! grob 'stencil
some-new-stencil)?".

There is no general answer. If they have not been computed yet, no
problem. If they have, it is almost certainly too late to get them
recomputed. True, you can do
(ly:grob-set-property! grob '{X,Y}-extent (ly:stencil-extent the-stencil 
{X,Y})).

However, grob extents and coordinates are cached in C++ members as
soon as they have been computed once, to make their retrieval cheaper
because it's done often. Thus, modifying the {X,Y}-extent properties
will not affect code that gets them via ly:grob-extent or its C++
equivalent.

The solution is to try hard to write your code in a functional way,
with properties computed on-demand via callbacks rather than set
at a specific point of time. The grob-transformer often helps.

Best,
Jean




Re: bug in magnetic snapping lyrics engraver

2022-04-14 Thread Werner LEMBERG

> How did you do that?  Sorry to rain on your parade, but I would not
> want you to put a lot of work in it if it will not be of mergeable
> quality.

Attached.  In the end the necessary modifications were surprisingly
minor.  Please comment, there is certainly room for improvements.


Werner

diff --git a/lily/lyric-hyphen.cc b/lily/lyric-hyphen.cc
index 23cd76bd94..897de7d7f7 100644
--- a/lily/lyric-hyphen.cc
+++ b/lily/lyric-hyphen.cc
@@ -48,6 +48,10 @@ Lyric_hyphen::print (SCM smob)
   && !from_scm (get_property (me, "after-line-breaking"
 return SCM_EOL;
 
+  // Ensure that bounds are displaced first.
+  (void) get_property (bounds[LEFT], "after-line-breaking");
+  (void) get_property (bounds[RIGHT], "after-line-breaking");
+
   Grob *common = bounds[LEFT]->common_refpoint (bounds[RIGHT], X_AXIS);
 
   Interval span_points;
diff --git a/scm/scheme-engravers.scm b/scm/scheme-engravers.scm
index 07e3be3691..5131beef1f 100644
--- a/scm/scheme-engravers.scm
+++ b/scm/scheme-engravers.scm
@@ -943,6 +943,101 @@ Engraver to print a line between two @code{Fingering} grobs.")))
(description . "Create repeat counts within lyrics for modern
 transcriptions of Gregorian chant.")))
 
+(define (Left_hyphen_pointer_engraver context)
+  (let ((hyphen #f)
+(text #f))
+(make-engraver
+ (acknowledgers
+  ((lyric-syllable-interface engraver grob source-engraver)
+   (set! text grob)))
+ (end-acknowledgers
+  ((lyric-hyphen-interface engraver grob source-engraver)
+   (when (not (grob::has-interface grob 'lyric-space-interface))
+ (set! hyphen grob
+ ((stop-translation-timestep engraver)
+  (when (and text hyphen)
+(ly:grob-set-object! text 'left-hyphen hyphen))
+  (set! text #f)
+  (set! hyphen #f)
+
+(define-public (lyric-text::apply-magnetic-offset! grob)
+  "If the space between two syllables is less than the value in
+property @code{LyricText@/.details@/.squash-threshold}, move the right
+syllable to the left so that it gets concatenated with the left
+syllable.
+
+Use this function as a hook for
+@code{LyricText@/.after-@/line-@/breaking} if the
+@code{Left_@/hyphen_@/pointer_@/engraver} is active."
+  (let ((hyphen (ly:grob-object grob 'left-hyphen #f)))
+(when hyphen
+  (let ((left-text (ly:spanner-bound hyphen LEFT)))
+(when (grob::has-interface left-text 'lyric-syllable-interface)
+  (let* ((common (ly:grob-common-refpoint grob left-text X))
+ (this-x-ext (ly:grob-extent grob common X))
+ (left-x-ext
+  (begin
+;; Trigger magnetism for left-text.
+(ly:grob-property left-text 'after-line-breaking)
+(ly:grob-extent left-text common X)))
+ ;; `delta` is the gap width between two syllables.
+ (delta (- (interval-start this-x-ext)
+   (interval-end left-x-ext)))
+ (details (ly:grob-property grob 'details))
+ (threshold (assoc-get 'squash-threshold details 0.2)))
+(when (< delta threshold)
+  (let* (;; We have to manipulate the input text so that
+ ;; ligatures crossing syllable boundaries are not
+ ;; disabled.  For languages based on the Latin
+ ;; script this is essentially a beautification.
+ ;; However, for non-Western scripts it can be a
+ ;; necessity.
+ (lt (ly:grob-property left-text 'text))
+ (rt (ly:grob-property grob 'text))
+ ;; Append new syllable.
+ (ltrt (if (and (string? lt) (string? rt))
+   (string-append lt rt)
+   (make-concat-markup (list lt rt
+ ;; Right-align `ltrt` to the right side.
+ (markup (grob-interpret-markup
+  grob
+  (make-translate-markup
+   (cons (interval-length this-x-ext) 0)
+   (make-right-align-markup ltrt)
+(begin
+  ;; Don't print `left-text`.
+  (ly:grob-set-property! left-text 'stencil #f)
+  ;; Set text and stencil (which holds all collected
+  ;; syllables so far) and shift it to the left.
+  (ly:grob-set-property! grob 'text ltrt)
+  (ly:grob-set-property! grob 'stencil markup)
+  (ly:grob-translate-axis! grob (- delta) X))
+
+(ly:register-translator
+ Left_hyphen_pointer_engraver 'Left_hyphen_pointer_engraver
+ '((grobs-created . ())
+   (events-accepted . ())
+   (properties-read . ())
+   (properties-written . ())
+   (description . "\
+Collect syllable-hyphen-syllable occurrences in lyrics and store them

Re: Custom Spanner with variable length sections

2022-04-14 Thread Jean Abou Samra

Le 14/04/2022 à 16:09, Kieren MacMillan a écrit :

Hi Dimitris,


I need a custom spanner that has x sections with different symbols. This is 
going to be tricky so any help is appreciated.

https://github.com/davidnalesnik/lilypond-text-spanner-inner-texts



Ok, I'm not sure if this solves the problem fully, so I'll post what I had
started writing anyway:


\version "2.22.2"

#(define (define-grob! grob-name grob-entry)
   (set! all-grob-descriptions
 (cons ((@@ (lily) completize-grob-entry)
    (cons grob-name grob-entry))
   all-grob-descriptions)))

#(define (partial-sums lst)
   (cdr (reverse! (fold
   (lambda (new previous)
 (cons (+ new (car previous))
   previous))
   (list 0)
   lst

#(define (symbol-filler::print grob)
   (let* ((widths (ly:grob-property grob 'widths))
  (symbols (ly:grob-property grob 'symbols))
  (orig (ly:grob-original grob))
  (siblings (ly:spanner-broken-into orig))
  (sib-widths
   (map (lambda (sib)
  (let ((sys (ly:grob-system sib))
    (left (ly:spanner-bound sib LEFT))
    (right (ly:spanner-bound sib RIGHT)))
    (- (ly:grob-relative-coordinate right sys X)
   (ly:grob-relative-coordinate left sys X
    siblings))
  (sib-changes (partial-sums sib-widths))
  (total-spanner-width (apply + sib-widths))
  (total-sym-width (apply + widths))
  (normalized-syms (map (lambda (x)
   (* x (/ total-spanner-width 
total-sym-width)))

 widths))
  (sym-changes (partial-sums normalized-syms))
  (sib-stil empty-stencil)
  (len-so-far 0)
  (retval #f))
 ;; Let's do an exception.  This is easier written in imperative style.
 (while (and (pair? sib-changes)
 (pair? sym-changes))
   (let* ((sib (car siblings))
  (next-sym-maybe (car symbols))
  (next-stil-maybe (grob-interpret-markup sib next-sym-maybe))
  (len (interval-length (ly:stencil-extent next-stil-maybe X)))
  (new-len-so-far (+ len len-so-far)))
 (cond
  ((> new-len-so-far (car sib-changes))
   ;; Used full length of this broken piece.  Set
   ;; its stencil and start using the next.
   (if (eq? grob (car siblings))
  (set! retval sib-stil)
  (ly:grob-set-property! (car siblings)
 'stencil
 sib-stil))
   (set! sib-changes (cdr sib-changes))
   (set! siblings (cdr siblings))
   (set! sib-stil empty-stencil))
  ((> new-len-so-far (car sym-changes))
   ;; Done with this symbol, start using the next.
   (set! sym-changes (cdr sym-changes))
   (set! symbols (cdr symbols)))
  (else
   (set! sib-stil (ly:stencil-stack sib-stil X RIGHT 
next-stil-maybe 0))

   (set! len-so-far new-len-so-far)
 retval))

#(define-grob! 'SymbolFiller
   `((direction . ,DOWN)
 (normalized-endpoints . ,ly:spanner::calc-normalized-endpoints)
 (stencil . ,symbol-filler::print)
 (staff-padding . 3.0)
 (symbols . ,(grob::calc-property-by-copy 'symbols))
 (widths . ,(grob::calc-property-by-copy 'widths))
 (Y-offset . ,ly:side-position-interface::y-aligned-side)
 (meta . ((class . Spanner)
  (interfaces . (side-position-interface))

#(define (Symbol_filler_engraver context)
   (let ((filler #f)
 (ev #f))
 (make-engraver
  (listeners
   ((symbol-filler-event engraver event)
    (set! ev event)))
  ((process-music engraver)
   (if ev
   (let ((d (ly:event-property ev 'span-direction)))
 (if (eqv? d LEFT)
 (begin
  (set! filler (ly:engraver-make-grob engraver 
'SymbolFiller ev))

  (ly:spanner-set-bound! filler
 LEFT
 (ly:context-property context 
'currentMusicalColumn)))

 (begin
  (ly:spanner-set-bound! filler
 RIGHT
 (ly:context-property context 
'currentMusicalColumn))

  (ly:engraver-announce-end-grob engraver filler ev))
  ((stop-translation-timestep engraver)
   (set! ev #f)

\layout {
  \context {
    \Global
    \grobdescriptions #all-grob-descriptions
  }
  \context {
    \Voice
    \consists #Symbol_filler_engraver
  }
}

#(define (define-event! type properties)
   (set! properties (assoc-set! properties 'name type))
   (hashq-set! music-name-to-property-table type properties)
   (set! music-descriptions
 

Off-topic: What do you guys think of the upside-down music?

2022-04-14 Thread Kenneth Wolcott
Hi;

  Off-topic: What do you guys think of the upside-down music?

On youtube:

https://www.youtube.com/channel/UCrLBkLxyE7T1cyv_4ykGTrg

Upside-down Scores

Example:
Für Elise Upside-down (new version, with Score)
https://www.youtube.com/watch?v=q2vsAua8FxM

How is this done?  Can this be done with Lilypond?  Just curious..

Amusing...

Ken Wolcott



Re: Off-topic: What do you guys think of the upside-down music?

2022-04-14 Thread Jean Abou Samra




Le 14/04/2022 à 21:58, Kenneth Wolcott a écrit :

Hi;

   Off-topic: What do you guys think of the upside-down music?

On youtube:

https://www.youtube.com/channel/UCrLBkLxyE7T1cyv_4ykGTrg

Upside-down Scores

Example:
Für Elise Upside-down (new version, with Score)
https://www.youtube.com/watch?v=q2vsAua8FxM

How is this done?  Can this be done with Lilypond?  Just curious..

Amusing...

Ken Wolcott


\version "2.22.2"

upsideDown =
#(define-music-function (music) (ly:music?)
   (for-some-music
    (lambda (m)
  (let ((p (ly:music-property m 'pitch #f)))
    (if p
    (let ((n (ly:pitch-transpose #{ cis' #} (ly:pitch-diff #{ 
des' #} p

  (ly:music-set-property! m 'pitch n
  #f)
    music)
   music)

RH = \relative {
  \time 3/8
  \partial 8
  e''16 dis
  e dis e b d c
  a8 r16 c, e a
  b8 r16 e, gis b
  c8 r16
}

LH = \relative {
  \time 3/8
  \partial 8
  s8
  s4.
  a,16 e' a r r8
  e,16 e' gis r r8
  a,16[ e' a]
}


\score {
  \header {
    piece = "Lettre à Élise"
  }
  <<
    \new Staff \RH
    \new Staff { \clef bass \LH }
  >>
}

\score {
  \header {
    piece = \markup \scale #'(1 . -1) "Lettre à Élise"
  }
  \upsideDown <<
    \new Staff { \key bes \major \LH }
    \new Staff { \clef bass \key bes \major \RH }
  >>
}







Tags for contexts without duration

2022-04-14 Thread Dimitris Marinakis
I often find myself in need of offsetting some tempo or rehearsal marks for
certain parts but not the full score but tags won't work in this case since
I can't have two marks at the same location on a single context. It is a
lot of work to duplicate the whole context just to differentiate a few
markings.

Are there any tricks to apply tags on specific marks or markups only? That
would be so useful

Can Lilypond be made aware of which file it outputs to? if file A.ly do
this else if file B.ly do that else do something else. Maybe that doesn't
make sense.

It would be cool if I could specify the offsets based on a file by file
basis.


Cross-staff arpeggios with a grace note

2022-04-14 Thread Knute Snortum
I am having trouble with arpeggios and grace notes again.  In this
situation, I have a cross-staff arpeggio of a chord with a grace note
(see attachment).  LilyPond's default is to put the arpeggio and grace
note on top of each other.  Jean taught me the trick of putting the
arpeggio on the grace note and adjusting the arpeggio's length and
position from there, like this:

%%%
\version "2.22.2"

rightHand = {
  e'2
}

leftHand = \relative {
  \clef bass
  <<
{
  \slashedGrace {
e8
\tweak positions #'(-4.5 . 5)
\tweak extra-spacing-width #'(-1 . 0)
\tweak X-offset -1
\arpeggio
  }
  2
}
\\
{
  2
}
  >>
}

\new PianoStaff <<
  \new Staff \rightHand
  \new Staff \leftHand
>>
%%%

This almost produces what I want.  The problem is I can't get the
arpeggio to cross into the upper staff.  If you make the arpeggio
higher than a certain amount (that is, \tweak positions #'(-4.5 . 5)
with a cdr of more than 5 or so) the upper staff shies away from the
arpeggio.

Any help getting the arpeggio past the lower part of the upper staff
will be appreciated.

--
Knute Snortum


Re: bug in magnetic snapping lyrics engraver

2022-04-14 Thread Alexander Kobel
Hi all,

On 4/6/22 20:17, Jean Abou Samra wrote:
> Le 06/04/2022 à 14:33, Werner LEMBERG a écrit :
>> Is someone taking care of bugs in the magnetic snapping lyrics
>> engraver?  Here is an example where it fails to position lyrics
>> correctly (see last system in the image).
>>
>>
>>  Werner
>>
>>
>> PS: I've attached a version of `magnetic-lyrics.ily` that actually
>>  works with the current development version (using an updated
>>  `add-grob-definition` routine).
> 
> 
> 
> To be honest, I don't know why the snippet is so complicated.
> I'd just have done:

One of the reasons might be that all participants have been 8 years younger and 
less experienced back then, and *some* later touches (at least mine) have been 
made by the trusted techniques of shotgun debugging and interpreter 
error-driven (rather than test-driven) development. And folks like Harm only 
had so much chance to tidy up my mess. ;-)

My literally last exposure to Lilypond was meeting you folks in Jan 2020 in 
Salzburg, and I'll need to dig out my old tests, but I'll give it a shot; 
having this integrated would be such an amazing improvement.


When it comes to LyricHyphen handling, some pieces in this thread might be 
relevant as well:
https://mail.gnu.org/archive/html/lilypond-user/2016-12/msg00361.html

Unfortunately IMHO, Knut's work on automatic LyricExtenders has never reached 
its prime time...


Cheers,
Alex


smime.p7s
Description: S/MIME Cryptographic Signature


Re: Cross-staff arpeggios with a grace note

2022-04-14 Thread Leo Correia de Verdier
I think there might be a more beautiful solutions to your whole situation, but 
I’m too tired to figure it out right now, so:

You can change the arpeggio’s Y-extent to prevent it from pushing away the 
other staff. 

%%%
\version "2.22.2"

rightHand = {
 e'2
}

leftHand = \relative {
 \clef bass
 <<
   {
 \slashedGrace {
   e8
   \tweak positions #'(-4.5 . 7)
   \tweak extra-spacing-width #'(-1 . 0)
   \tweak X-offset -1
   \tweak Y-extent #'(-4.5 . 2)
   \arpeggio
 }
 2
   }
   \\
   {
 2
   }
 >>
}

\new PianoStaff <<
 \new Staff \rightHand
 \new Staff \leftHand
>>
%%%

HTH
/Leo

> 14 apr. 2022 kl. 23:06 skrev Knute Snortum :
> 
> I am having trouble with arpeggios and grace notes again.  In this
> situation, I have a cross-staff arpeggio of a chord with a grace note
> (see attachment).  LilyPond's default is to put the arpeggio and grace
> note on top of each other.  Jean taught me the trick of putting the
> arpeggio on the grace note and adjusting the arpeggio's length and
> position from there, like this:
> 
> %%%
> \version "2.22.2"
> 
> rightHand = {
>  e'2
> }
> 
> leftHand = \relative {
>  \clef bass
>  <<
>{
>  \slashedGrace {
>e8
>\tweak positions #'(-4.5 . 5)
>\tweak extra-spacing-width #'(-1 . 0)
>\tweak X-offset -1
>\arpeggio
>  }
>  2
>}
>\\
>{
>  2
>}
>>> 
> }
> 
> \new PianoStaff <<
>  \new Staff \rightHand
>  \new Staff \leftHand
>>> 
> %%%
> 
> This almost produces what I want.  The problem is I can't get the
> arpeggio to cross into the upper staff.  If you make the arpeggio
> higher than a certain amount (that is, \tweak positions #'(-4.5 . 5)
> with a cdr of more than 5 or so) the upper staff shies away from the
> arpeggio.
> 
> Any help getting the arpeggio past the lower part of the upper staff
> will be appreciated.
> 
> --
> Knute Snortum
> 



Re: Cross-staff arpeggios with a grace note

2022-04-14 Thread Jean Abou Samra




Le 14/04/2022 à 23:06, Knute Snortum a écrit :

I am having trouble with arpeggios and grace notes again.  In this
situation, I have a cross-staff arpeggio of a chord with a grace note
(see attachment).  LilyPond's default is to put the arpeggio and grace
note on top of each other.  Jean taught me the trick of putting the
arpeggio on the grace note and adjusting the arpeggio's length and
position from there, like this:

%%%
\version "2.22.2"

rightHand = {
   e'2
}

leftHand = \relative {
   \clef bass
   <<
 {
   \slashedGrace {
 e8
 \tweak positions #'(-4.5 . 5)
 \tweak extra-spacing-width #'(-1 . 0)
 \tweak X-offset -1
 \arpeggio
   }
   2
 }
 \\
 {
   2
 }
   >>
}

\new PianoStaff <<
   \new Staff \rightHand
   \new Staff \leftHand
%%%

This almost produces what I want.  The problem is I can't get the
arpeggio to cross into the upper staff.  If you make the arpeggio
higher than a certain amount (that is, \tweak positions #'(-4.5 . 5)
with a cdr of more than 5 or so) the upper staff shies away from the
arpeggio.

Any help getting the arpeggio past the lower part of the upper staff
will be appreciated.


The magic incantation would be \tweak vertical-skylines ##f.


\version "2.22.2"

rightHand = {
  e'2
}

leftHand = \relative {
  \clef bass
  <<
    {
  \slashedGrace {
    e8
    \tweak positions #'(-4.5 . 10)
    \tweak extra-spacing-width #'(-1 . 0)
    \tweak X-offset -1
    \tweak vertical-skylines ##f
    \arpeggio
  }
  2
    }
    \\
    {
  2
    }
  >>
}

\new PianoStaff <<
  \new Staff \rightHand
  \new Staff \leftHand
>>


Jean




Re: Cross-staff arpeggios with a grace note

2022-04-14 Thread Knute Snortum
On Thu, Apr 14, 2022 at 2:23 PM Jean Abou Samra  wrote:
>> You can change the arpeggio’s Y-extent to prevent it from pushing away the 
>> other staff.
...
> The magic incantation would be \tweak vertical-skylines ##f.

Thanks Jean and Leo, those work great!

--
Knute Snortum



Re: bug in magnetic snapping lyrics engraver

2022-04-14 Thread Jean Abou Samra

Le 14/04/2022 à 18:18, Werner LEMBERG a écrit :

How did you do that?  Sorry to rain on your parade, but I would not
want you to put a lot of work in it if it will not be of mergeable
quality.

Attached.  In the end the necessary modifications were surprisingly
minor.  Please comment, there is certainly room for improvements.



Thanks. This is a bit what I feared: in this state, there is
potential for things going wrong with other after-line-breaking
callbacks. Those are the kind of thing that can be buggy in obscure
circumstances. I'm a little nervous on having my "off-the-top" /
"first thing that seemed to work" solution in the code base :-)

OTOH, it's *probably* not too difficult to refactor this to use
a separate 'original-text property and a 'text property computed
by a callback, with X-offset computed only after-line-breaking,
X-extent left empty and springs-and-rods doing the magic that
would otherwise be done by Separation_item::set_distance, at the
condition of letting Grob::extent skip the X-offset calculation
in case the extent is found to be empty (which could be a good
idea regardless actually). Or something like that. Too bad that
we don't have pure widths (we could if I finally managed to finish
a big patch that has been pending for about a year), but it should
be possible to do without I think. I think. But right now, I'm a
bit swamped due to a somewhat important exam next Thursday.


[Alex; glad to meet you BTW]

My literally last exposure to Lilypond was meeting you folks in Jan 2020 in 
Salzburg,



Well, not me ;-) (I knew little about LilyPond at that time
and had not started to contribute.)



and I'll need to dig out my old tests, but I'll give it a shot; having this 
integrated would be such an amazing improvement.



If you guys are ready to clean up this thing, that would be a relief
for me given the amount of other contributions that I am trying to
get around to. I know I was a bit elliptic above (too tired ATM),
but I am happy to provide guidance and discuss solutions.


Jean




Re: Tags for contexts without duration

2022-04-14 Thread Jean Abou Samra

Le 14/04/2022 à 22:44, Dimitris Marinakis a écrit :
I often find myself in need of offsetting some tempo or rehearsal 
marks for certain parts but not the full score but tags won't work in 
this case since I can't have two marks at the same location on a 
single context.


Not sure I understand the problem?

\version "2.22.2"

mus = {
  \tag #'part \once \override Score.RehearsalMark.X-offset = 8
  \mark \default
  c'
}

% Conductor
\removeWithTag #'part \mus

% Parts
{ \mus }


Best,
Jean




Re: Off-topic: What do you guys think of the upside-down music?

2022-04-14 Thread Kenneth Wolcott
Thanks, Jean!  This is cool!  Not that I would do anything with it,
but it sure is nice to know that there seems to be no limit to what
Lilypond can do :-)

On Thu, Apr 14, 2022 at 1:18 PM Jean Abou Samra  wrote:
>
>
>
> Le 14/04/2022 à 21:58, Kenneth Wolcott a écrit :
> > Hi;
> >
> >Off-topic: What do you guys think of the upside-down music?
> >
> > On youtube:
> >
> > https://www.youtube.com/channel/UCrLBkLxyE7T1cyv_4ykGTrg
> >
> > Upside-down Scores
> >
> > Example:
> > Für Elise Upside-down (new version, with Score)
> > https://www.youtube.com/watch?v=q2vsAua8FxM
> >
> > How is this done?  Can this be done with Lilypond?  Just curious..
> >
> > Amusing...
> >
> > Ken Wolcott
>
> \version "2.22.2"
>
> upsideDown =
> #(define-music-function (music) (ly:music?)
> (for-some-music
>  (lambda (m)
>(let ((p (ly:music-property m 'pitch #f)))
>  (if p
>  (let ((n (ly:pitch-transpose #{ cis' #} (ly:pitch-diff #{
> des' #} p
>(ly:music-set-property! m 'pitch n
>#f)
>  music)
> music)
>
> RH = \relative {
>\time 3/8
>\partial 8
>e''16 dis
>e dis e b d c
>a8 r16 c, e a
>b8 r16 e, gis b
>c8 r16
> }
>
> LH = \relative {
>\time 3/8
>\partial 8
>s8
>s4.
>a,16 e' a r r8
>e,16 e' gis r r8
>a,16[ e' a]
> }
>
>
> \score {
>\header {
>  piece = "Lettre à Élise"
>}
><<
>  \new Staff \RH
>  \new Staff { \clef bass \LH }
>>>
> }
>
> \score {
>\header {
>  piece = \markup \scale #'(1 . -1) "Lettre à Élise"
>}
>\upsideDown <<
>  \new Staff { \key bes \major \LH }
>  \new Staff { \clef bass \key bes \major \RH }
>>>
> }
>
>
>
>



Re: bug in magnetic snapping lyrics engraver

2022-04-14 Thread Werner LEMBERG

>> Attached.  In the end the necessary modifications were surprisingly
>> minor.  Please comment, there is certainly room for improvements.
> 
> Thanks. This is a bit what I feared: in this state, there is
> potential for things going wrong with other after-line-breaking
> callbacks.  Those are the kind of thing that can be buggy in obscure
> circumstances.  I'm a little nervous on having my "off-the-top" /
> "first thing that seemed to work" solution in the code base :-)

I think your code is very clear and easy to understand.  My extensions
aren't complicated either.  It also works nicely and flawless in
combination with the new `VaticanaLyrics` context.  So please be more
specific about your fears.  You told us that you are working on the
breaking algorithm since a few months, so I guess you are the best
person to voice objections and give counterexamples.

Kieren, can you test this, too?

We should probably continue the discussion on lilypond-devel, since it
seems to get bloody technical. :-)

> OTOH, it's *probably* not too difficult to refactor this to use a
> separate 'original-text property and a 'text property computed by a
> callback, with X-offset computed only after-line-breaking, X-extent
> left empty and springs-and-rods doing the magic that would otherwise
> be done by Separation_item::set_distance, at the condition of
> letting Grob::extent skip the X-offset calculation in case the
> extent is found to be empty (which could be a good idea regardless
> actually).

This is way too complicated for me, sorry.

> Or something like that. Too bad that we don't have pure widths (we
> could if I finally managed to finish a big patch that has been
> pending for about a year), but it should be possible to do without I
> think. I think.

Well, I fear I can't help you with the coding if you think this is the
best route to go.  But as usual: The better is the enemy of the
good :-)

> But right now, I'm a bit swamped due to a somewhat important exam
> next Thursday.

I wish you success!

> If you guys are ready to clean up this thing, that would be a relief
> for me given the amount of other contributions that I am trying to
> get around to.

Define 'clean up'.  AFAICS, what you have outlined above is not a
cleanup but a complete reimplementation based on a different
algorithm...


Werner


Re: bug in magnetic snapping lyrics engraver

2022-04-14 Thread Werner LEMBERG

>> How did you do that?  Sorry to rain on your parade, but I would not
>> want you to put a lot of work in it if it will not be of mergeable
>> quality.
> 
> Attached.  In the end the necessary modifications were surprisingly
> minor.  Please comment, there is certainly room for improvements.

Attached is another version for testing without the need to patch
LilyPond.


Werner
% magnetic-lyrics.ily
%
%   written by
% Jean Abou Samra 
% Werner Lemberg 
%
% Version 2022-Apr-15

\version "2.23.7"

#(define (Left_hyphen_pointer_engraver context)
   "Collect syllable-hyphen-syllable occurrences in lyrics and store
them in properties.  This engraver only looks to the left.  For
example, if the lyrics input is @code{foo -- bar}, it does the
following.

@itemize @bullet
@item
Set the @code{text} property of the @code{LyricHyphen} grob between
@q{foo} and @q{bar} to @code{foo}.

@item
Set the @code{left-hyphen} property of the @code{LyricText} grob with
text @q{foo} to the @code{LyricHyphen} grob between @q{foo} and
@q{bar}.
@end itemize

Use this auxiliary engraver in combination with the
@code{lyric-@/text::@/apply-@/magnetic-@/offset!} hook."
   (let ((hyphen #f)
 (text #f))
 (make-engraver
  (acknowledgers
   ((lyric-syllable-interface engraver grob source-engraver)
(set! text grob)))
  (end-acknowledgers
   ((lyric-hyphen-interface engraver grob source-engraver)
(when (not (grob::has-interface grob 'lyric-space-interface))
  (set! hyphen grob
  ((stop-translation-timestep engraver)
   (when (and text hyphen)
 (ly:grob-set-object! text 'left-hyphen hyphen))
   (set! text #f)
   (set! hyphen #f)

#(define (lyric-text::apply-magnetic-offset! grob)
   "If the space between two syllables is less than the value in
property @code{LyricText@/.details@/.squash-threshold}, move the right
syllable to the left so that it gets concatenated with the left
syllable.

Use this function as a hook for
@code{LyricText@/.after-@/line-@/breaking} if the
@code{Left_@/hyphen_@/pointer_@/engraver} is active."
   (let ((hyphen (ly:grob-object grob 'left-hyphen #f)))
 (when hyphen
   (let ((left-text (ly:spanner-bound hyphen LEFT)))
 (when (grob::has-interface left-text 'lyric-syllable-interface)
   (let* ((common (ly:grob-common-refpoint grob left-text X))
  (this-x-ext (ly:grob-extent grob common X))
  (left-x-ext
   (begin
 ;; Trigger magnetism for left-text.
 (ly:grob-property left-text 'after-line-breaking)
 (ly:grob-extent left-text common X)))
  ;; `delta` is the gap width between two syllables.
  (delta (- (interval-start this-x-ext)
(interval-end left-x-ext)))
  (details (ly:grob-property grob 'details))
  (threshold (assoc-get 'squash-threshold details 0.2)))
 (when (< delta threshold)
   (let* (;; We have to manipulate the input text so that
  ;; ligatures crossing syllable boundaries are not
  ;; disabled.  For languages based on the Latin
  ;; script this is essentially a beautification.
  ;; However, for non-Western scripts it can be a
  ;; necessity.
  (lt (ly:grob-property left-text 'text))
  (rt (ly:grob-property grob 'text))
  ;; Append new syllable.
  (ltrt (if (and (string? lt) (string? rt))
(string-append lt rt)
(make-concat-markup (list lt rt
  ;; Right-align `ltrt` to the right side.
  (markup (grob-interpret-markup
   grob
   (make-translate-markup
(cons (interval-length this-x-ext) 0)
(make-right-align-markup ltrt)
 (begin
   ;; Don't print `left-text`.
   (ly:grob-set-property! left-text 'stencil #f)
   ;; Set text and stencil (which holds all collected
   ;; syllables so far) and shift it to the left.
   (ly:grob-set-property! grob 'text ltrt)
   (ly:grob-set-property! grob 'stencil markup)
   (ly:grob-translate-axis! grob (- delta) X))


#(define (lyric-hyphen::displace-bounds-first grob)
   ;; Make very sure this callback isn't triggered too early.
   (let ((left (ly:spanner-bound grob LEFT))
 (right (ly:spanner-bound grob RIGHT)))
 (ly:grob-property left 'after-line-breaking)
 (ly:grob-property right 'after-line-breaking)
 (ly:lyric-hyphen::print grob)))


\layout {
  \context {
\Lyrics
\consists #Left_h