Hi Han-Wen,

Got it, thanks! I will attach the example file here as your reply didn't 
include it.

________________________________
发件人: Han-Wen Nienhuys <[email protected]>
发送时间: 2020年5月4日 17:21
收件人: Chen Leo <[email protected]>; lilypond-devel <[email protected]>
主题: Re: Request for Big Time Signature

Hi Leo,

thanks for your kind words. I'm focusing my limited time on LilyPond
infrastructure, so I can't help you here, but I hope someone else from
the development community can. I took the liberty of including them on
this reply.

On Mon, May 4, 2020 at 6:37 AM Chen Leo <[email protected]> wrote:
>
> Hi Han-Wen,
>
> I am a new lilypond user and I have been using lilypond for a few months now. 
> I want to say that I love the experience (especially the way lilypond 
> automatically handles all the collisions and alignment problems with great 
> accuracy). I want to thank the development team for creating such amazing 
> software.
>
> One personal suggestion would be that I think lilypond can benefit from 
> implementing more contemporary notations e.g. more symbols and noteheads (I 
> was happy to hear that lilypond is considering adopting the SMuFL font 
> format). For most of the notation problems I have encountered, I was able to 
> solve by copying and modifying different snippets, thanks to the great 
> lilypond community. However, there’s one specific problem that I can’t seem 
> to find a solution to, even with the help of several lilypond users.
>
> The problem is to put large time signatures on top of (or in between) staves, 
> it is commonly used in a lot of contemporary scores which often feature 
> constant changes in time structures. In these situations, using this layout 
> will make the score look a lot clearer and save much horizontal space.
>
> I found
> http://lsr.di.unimi.it/LSR/Snippet?id=272
> which seems like a perfect solution initially. However, soon I was able to 
> find several problems with this snippet. (I will give examples for all of the 
> problems in the attached file)
> 1a. Time signatures get aligned to cue clefs instead of the bar line whenever 
> a clef change is made at the end of the bar.
> 1b. Time signatures appear twice when one staff has a grace note as the first 
> note in a bar while other staves do not.
> 1c. Space is not allotted for the cautionary time signatures before line 
> breaks so they always cross the left margin.
> 1d. shift-right-at-line-begin has a fixed X-offset value of 3.5 units, this 
> means that if the user decides to change the clef font size or to use an 
> alternative font the X-offset value won’t automatically change according to 
> the width of the clef symbol.
>
> I tried another approach afterward, which is to use
> \override TimeSignature.break-align-symbol = #'staff-bar
> This successfully solves problems 1 3 and 4 yet it also starts to cause more 
> problems since other staves are now aware of the time signature’s horizontal 
> space. The problems are:
> 2a. Parts of hairpins and spanners are missing below the time signatures 
> after a line break.
> 2b. Lilypond pushes everything to the left when \textLengthOn commands are 
> used on text script objects below the time signature.
> 2c. Same as problem 1b from the original snippet.
> 2d. Bar numbers are raised to the same height as the time signatures' dummy 
> staff while it should display on the top music staff. This problem can be 
> solved by removing "Bar_number_engraver" from the Score context and consists 
> of it only in the actual top staff’s context. Though this can cause some 
> problems if the user chooses to hide staves that don’t have a part in a 
> section of music and the top staff also happens to be one of the hidden 
> staves.
>
> After a long discussion, a kind lilypond user named Kevin Barry was able to 
> provide me with a solution that he thinks is somewhat “hacky” while it solves 
> problem 2a and 2c quite well. He wrote a custom engraver that replaces all 
> TimeSignature objects with TextScript objects except at the end of lines so 
> that space can be allotted for the cautionary time signatures (I’ve also 
> included his approach in the attached file). Problem 2b and 2d remain 
> unsolvable. Because the only solution to problem 2b is to set TextScript’s 
> extra-spacing-width property to #'(+inf.0 . -inf.0) while that means bars are 
> no longer sensitive to the TextScript objects’ width, it causes collisions 
> when time signatures exceed the barline. I wasn’t able to solve problem 2d as 
> well.
>
> Eventually, I decided to contact someone from the development team and I 
> found you.
> I hope that this can be improved and made into a snippet (or even better if 
> this gets implemented into lilypond in future versions) as using large time 
> signatures is really quite common in contemporary ensemble pieces.
>
> Here are some examples of how this layout can look like in different scores.
>
> Most scores have the time signatures vertically centered. e.g.
> Pierre Boulez - Répons
> https://www.youtube.com/watch?v=9aa8ogiwEV4
> Tristan Murail - La Barque Mystique
> https://www.youtube.com/watch?v=Te-R0eETD0c
>
> While some scores do not. e.g.
> Tōru Takemitsu - Rain Coming
> https://www.youtube.com/watch?v=YnaztoAdgWk
> Toshio Hosokawa �C Vertical Song I
> https://www.youtube.com/watch?v=Ji0gxsRp71M
>
> I hope that both options can be considered.
>
> Any help will be greatly appreciated!
>
> Best wishes,
> Leo
\version "2.20.0"

% custom engraver by Kevin Barry
#(define (Time_signature_markup_engraver context)
   (let ((time-sig '())
         (time-sig-copy #f)
         (previous-was-grace #f)) ; to avoid printing twice at grace notes
     (make-engraver
      (acknowledgers
       ((time-signature-interface engraver grob source-engraver)
        (let* ((current-moment (ly:context-current-moment context))
               (grace-nom (ly:moment-grace-numerator current-moment)))
          (if (not (eqv? 0 grace-nom))
              (begin
               (set! previous-was-grace #t)
               (set! time-sig grob))
              (if (and (eqv? 0 grace-nom) previous-was-grace)
                  (begin
                   (set! previous-was-grace #f)
                   (set! time-sig '()))
                  (set! time-sig grob))))))
      ((process-acknowledged engraver)
       (and (not (null? time-sig))
            (let* ((time-sig-copy (ly:engraver-make-grob
                                   engraver
                                   'TextScript
                                   time-sig))
                   (copy-prop (lambda (prop)
                                (ly:grob-set-property!
                                 time-sig-copy
                                 prop
                                 (ly:grob-property time-sig prop))))
                   (timing-context (ly:context-find context 'Timing))
                   (timing-time-sig
                    (ly:context-grob-definition timing-context 'TimeSignature))
                   (timing-time-sig-stencil
                    (ly:assoc-get 'stencil timing-time-sig '()))
                   (prop-list '(fraction
                                style
                                font-size
                                extra-spacing-width
                                cause)))
              (map copy-prop prop-list)
              (ly:grob-set-property! time-sig-copy 'stencil
                timing-time-sig-stencil)
              (ly:grob-set-parent! time-sig-copy Y time-sig)
              (ly:grob-set-parent! time-sig-copy X time-sig)
              (set! time-sig '())
              )))
      ((stop-translation-timestep engraver)
       (set! time-sig-copy #f)))))

#(define (remove-except-at-line-end grob)
   (if (not (equal? (ly:item-break-dir grob) LEFT))
       (ly:grob-set-property! grob 'stencil #f)))

#(define (remove-at-end grob)
   (if (equal? (ly:item-break-dir grob) LEFT)
       (ly:grob-set-property! grob 'stencil #f)))

#(define (center-over-barline grob)
   (if (equal? (ly:item-break-dir grob) 0)
       (let* ((x-extent (ly:grob-property grob 'X-extent))
              (width (interval-length x-extent)))
         (ly:grob-set-property! grob 'X-offset (* -1 (/ width 2))))))

#(define (center-over-barline-and-remove-at-end grob)
   (begin
    (remove-at-end grob)
    (center-over-barline grob)))

#(define (left-align-at-end grob)
   (and (and (ly:item? grob)
             (equal? (ly:item-break-dir grob) LEFT))
        (ly:grob-set-property! grob 'self-alignment-X 1)))

% definition of shift-right-at-line-begin
#(define (shift-right-at-line-begin g)
  "Shift an item to the right, but only at the start of the line."
  (if (and (ly:item? g)
           (equal? (ly:item-break-dir g) RIGHT))
      (ly:grob-translate-axis! g 3.5 X)))

timeSignatures = {
  \tempo 4 = 80
  \time 4/4 s1
  \time 3/8 s4.
  \time 3/4 s2.
  \time 4/4 s1
  \time 2/4 \acciaccatura s8 s2
  \compoundMeter #'((3 8) (1 16) (1 16) (1 16))
  s4. s16 s16 s16
  \time 4/4 s1
}

\paper {
    top-margin = #15
    bottom-margin = #15
    left-margin = #15
    right-margin = #15
    system-system-spacing =
    #`((basic-distance . 10)
       (minimum-distance . 6)
       (padding . 2)
      )
}

\markup \column \fontsize #4 {
  "Approach #1"
  "(http://lsr.di.unimi.it/LSR/Snippet?id=272)"
}

\score {
  \layout {
    \context {
      \Score
      \override MetronomeMark.break-align-symbols = #'(staff-bar time-signature)
    }
    \context {
      \Staff
      \override MultiMeasureRest.spacing-pair = #'(break-alignment . staff-bar)
      \override Clef.font-size = #5
      \remove "Time_signature_engraver"
    }
    \context {
      \Score
    }
  }
  <<
    \new Dynamics \with {          
    \consists "Time_signature_engraver"
    \consists "Axis_group_engraver"
    \override TimeSignature.font-size = #8
    \override TimeSignature.break-align-symbol = ##f
    \override TimeSignature.X-offset =
      #ly:self-alignment-interface::x-aligned-on-self
    \override TimeSignature.self-alignment-X = #LEFT
    \override TimeSignature.after-line-breaking =
      #shift-right-at-line-begin
    \numericTimeSignature
    }
    {
      \timeSignatures
    }
    
    \new StaffGroup <<
      \relative c' {
        \time 4/4
        c4 ( ^"↑ Problem 1d"
        d4 e4 f4 ) |
        
        \time 3/8
        a'4 ( g8 ) |
        
        \time 3/4
        R2. 
        ^\markup {
          \column {
            "← Problem 1a"
            "Problem 1c →"
            " "
            " "
          }
        } |
        
        \time 4/4
        c1 |
        
        \time 2/4
        a8 ^"↑ Problem 1b"
        g8 f8 e8 |
        
        \compoundMeter #'((3 8) (1 16) (1 16) (1 16))
        a2 g16 |
        
        \time 4/4
        c4 c c c |
      }
      
      \relative c' {
        \time 4/4
        R1 |
        
        \time 3/8
        R4. |
        
        \clef bass
        \time 3/4
        a,2. \> \startTextSpan |
        \break
        
        \time 4/4
        c2 e2 \! \stopTextSpan |

        \time 2/4
        \acciaccatura f8 a8 
        g8 f8 e8 |
        
        \compoundMeter #'((3 8) (1 16) (1 16) (1 16))
        a2 g16 |
        
        \time 4/4
        c4 c c c |
      }
    >>
  >>
} \pageBreak

\markup \column \fontsize #4 {
  "Approach #2"
  "(\override TimeSignature.break-align-symbol = #'staff-bar)"
}

\score {
  \layout {
    \context {
      \Score
      \override MetronomeMark.break-align-symbols = #'(staff-bar time-signature)
    }
    \context {
      \Staff
      \override MultiMeasureRest.spacing-pair = #'(break-alignment . staff-bar)
      \override Clef.font-size = #5
      \remove "Time_signature_engraver"
    }
    \context {
      \Score
    }
  }
  <<
    \new Dynamics \with {          
    \consists "Time_signature_engraver"
    \consists "Axis_group_engraver"
    \override TimeSignature.font-size = #8
    \override TimeSignature.break-align-symbol = #'staff-bar
    \override TimeSignature.X-offset =
      #ly:self-alignment-interface::x-aligned-on-self
    \override TimeSignature.self-alignment-X = #LEFT
    \numericTimeSignature
    }
    {
      \timeSignatures
    }
    
    \new StaffGroup <<
      \relative c' {
        \time 4/4
        \textLengthOn
        c4 ( ^"← Problem 2b"
        \textLengthOff
        d4 e4 f4 ) |
        
        \time 3/8
        a'4 ( g8 ) |
        
        \time 3/4
        R2. |
        
        \time 4/4
        \override Score.RehearsalMark.X-offset = #-1.5
        \mark "↓ Problem 2d"
        c1 |
        
        \time 2/4
        a8 ^"↑ Problem 2c"
        g8 f8 e8 |
        
        \compoundMeter #'((3 8) (1 16) (1 16) (1 16))
        a2 g16 |
        
        \time 4/4
        c4 c c c |
      }
      
      \relative c' {
        \time 4/4
        R1 |
        
        \time 3/8
        R4. |
        
        \clef bass
        \time 3/4
        a,2. \> \startTextSpan |
        \break
        
        \time 4/4
        c2 ^"↓ Problem 2a" _"↑" e2 \! \stopTextSpan |

        \time 2/4
        \acciaccatura f8 a8 
        g8 f8 e8 |
        
        \compoundMeter #'((3 8) (1 16) (1 16) (1 16))
        a2 g16 |
        
        \time 4/4
        c4 c c c |
      }
    >>
  >>
} \pageBreak

\markup \column \fontsize #4 {
  "Approach #3"
  "(custom engraver by Kevin Barry)"
}

\score {
  \layout {
    \context {
      \Score
      \override MetronomeMark.break-align-symbols = #'(staff-bar time-signature)
    }
    \context {
      \Staff
      \override MultiMeasureRest.spacing-pair = #'(break-alignment . staff-bar)
      \override Clef.font-size = #5
      \remove "Time_signature_engraver"
    }
    \context {
      \Score
    }
  }
  <<
    \new Dynamics \with {          
      \consists "Time_signature_engraver"
      \consists \Time_signature_markup_engraver
      \override TimeSignature.font-size = #8
      \override TimeSignature.before-line-breaking = #remove-except-at-line-end
      \override TimeSignature.break-align-symbol = #'staff-bar
      \override TextScript.before-line-breaking = #remove-at-end
      %↓ The only solution to problem 2b but it causes collisions
      %\override TextScript.extra-spacing-width = #'(+inf.0 . -inf.0)
      \override TextScript.extra-spacing-width = #'(0 . 0.8)
      \override TextScript.direction = #UP
      \override TextScript.Y-offset = #0
      \numericTimeSignature
    }
    {
      \timeSignatures
    }
    
    \new StaffGroup <<
      \relative c' {
        \time 4/4
        \textLengthOn
        c4 ( ^"← Problem 2b"
        \textLengthOff
        d4 e4 f4 ) |
        
        \time 3/8
        a'4 ( g8 ) |
        
        \time 3/4
        R2. |
        
        \time 4/4
        \override Score.RehearsalMark.X-offset = #-1.5
        \mark "↓ Problem 2d"
        c1 |
        
        \time 2/4
        a8 g8 f8 e8 |
        
        \compoundMeter #'((3 8) (1 16) (1 16) (1 16))
        a2 g16 |
        
        \time 4/4
        c4 c c c |
      }
      
      \relative c' {
        \time 4/4
        R1 |
        
        \time 3/8
        R4. |
        
        \clef bass
        \time 3/4
        a,2. \> \startTextSpan |
        \break
        
        \time 4/4
        c2 e2 \! \stopTextSpan |

        \time 2/4
        \acciaccatura f8 a8 
        g8 f8 e8 |
        
        \compoundMeter #'((3 8) (1 16) (1 16) (1 16))
        a2 g16 |
        
        \time 4/4
        c4 c c c |
      }
    >>
  >>
} \pageBreak

Reply via email to