Center text above measure, forcing its width (first shot)

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

Center text above measure, forcing its width (first shot)

Urs Liska-3

Hi,

working towards a solution of at least one problem with measure-aligned stuff I wrote a function that centers one or two markups above and/or below a measure and forces the measure to be *at least* as wide as the wider of the two markups. The function does *not* center anything within the measure but allows the content of the measure to be arbitrary music.

Before refining the code and the user interface I'd like to have some general feedback and maybe some hints regarding the remaining problems.

The approach I took is the following:

  • Create a temporary polyphonic section using the \new Voice approach
  • Print the given "regular" music as the first (continued) Voice
  • Print a hidden MultiMeasureRest in the temporary Voice and attach the markup(s) to that
  • *First* override before-line-breaking, create stencils from the markups and force MultiMeasureRest.minimum-length accordingly
  • *Then* insert the MultiMeasureRest with the attached markups

As you can see from the attached image this works surprisingly well. The code includes many comments, including descriptions of the remaining problems:

  • It seems when there's a time signature involved to the left or right of the measure, setting minimum-length doesn't quite do what it does in normal measures.
  • When the markup is not a single-line markup the setting of staff-padding doesn't seem to have an effect.

Apart from fine-tuning the configurability of the layout mechanism I will want to complement the function with another one that centers the measures *content* as well. I hope the techniques I learned yesterday will work smoothly together with the current stuff (replacing the MMR's stencil with a centered markup stencil). Eventually I'll add the functions to the "oll-misc" openLilyLib package, in a new module below https://github.com/openlilylib/oll-misc/tree/master/text.

Thanks for any suggestions for improvement
Urs

%%%%%

\version "2.19.82"

% Paper settings to make the effects visible
\paper {
  ragged-last = ##t
  indent = 0\cm
  system-system-spacing.basic-distance = 20
}

% Center text above and/or below a measure,
% forcing the measure to be wide enough
% Arguments:
% - duration (optional, default 1/1)
%   length of the measure
% - markup-above
% - markup-below
%   Markup expressions to be printed above/below the measure.
%   If only one is given it is printed above,
%   if only a markup is intended below both should be given 
%   where the first is an empty string
% - padding (optional, default 1)
%   amount by which the measure must be wider than the
%   (wider of two) markup(s) on each side
% - music
%   The music to be printed,
%   must include exactly one measure (i.e. the length of the duration argument)
measureCenteredMarkup =
#(define-music-function (duration markup-above markup-below padding music)
   ((ly:duration? (ly:make-duration 0)) markup? (markup? (markup "")) (number? 1) ly:music?)
   #{
     <<
       {
         #music
       }
       \new Voice {
         \override MultiMeasureRest.before-line-breaking =
         % First determine the width of the (wider) markup
         % and force the MultiMeasureRest's minimum-length
         #(lambda (grob)
            (let*
             ((markup-stencil-above (grob-interpret-markup grob markup-above))
              (markup-stencil-below (grob-interpret-markup grob markup-below))
              (markup-width
               (max
                (interval-length (ly:stencil-extent markup-stencil-above X))
                (interval-length (ly:stencil-extent markup-stencil-below X))
                )))
             (ly:grob-set-property! grob 'minimum-length (+ (* padding 2) markup-width))))
         % Hide the MultiMeasureRest and attach the markup(s) to it
         \hide MultiMeasureRest
         #(make-music
           'MultiMeasureRestMusic
           'duration
           duration ;(ly:make-duration duration)
           'articulations
           (list
            (make-music
             'MultiMeasureTextEvent
             'direction 1
             'text markup-above)
            (make-music
             'MultiMeasureTextEvent
             'direction -1 'text
             markup-below)))
       }
     >>
   #})


\relative {
  % Doesn't work with the very first element (probably no Voice to continue)
  <>
  \override Staff.MultiMeasureRestText.staff-padding = 3

  % The ! is centered above the measure, doesn't affect the width
  \measureCenteredMarkup "!" c''1
  
  % Center text below measure (first argument is an empty string)
  % and widen the measure
  \measureCenteredMarkup "" "Widen the measure" R1
  
  \time 3/4
  R2.
  
  % With the optional duration argument arbitrary time signatures are supported
  \measureCenteredMarkup 2. 
  % pass both above and below text
  "Hey that is a really wide centered markup"
  "Also works with polyphonic music" {
    % Arbitrary music can be printed in the measure,
    % doesn't interfere with the hidden rest.
    <<
      {
        c4 b8 a g f
      } \\ {
        a4 g8 f e d
      }
    >>
  }
  e2.
  \break
  \time 4/4
  e2 d
  \measureCenteredMarkup 
  % Arbitrary markup constructs may be used.
  % NOTE: MultiMeasureRestText.staff-padding
  %       doesn't seem to have an effect here
  \markup \override #'(baseline-skip . 2.4) \center-column {
    "This is a" "centered" "column that pushes"
  } c1
  R1
  \time 2/4
  % With a printed time signature the spacing doesn't work properly ...
  \measureCenteredMarkup 2 "Time Signature fails" R2
  R2
  % which is particularly visible if there's no time sig on the left:
  % the text protrudes over both barlines.
  \measureCenteredMarkup 2 "especially on the right side" R2
  \break
  \time 3/4
  % Also here: There shouldn't be any reason that the text goes beyond
  % 	       the right barline
  \measureCenteredMarkup 2. "or at the beginning of a line" R2.
  
  R2.
  
  % Basically any markup construct may be used here
  \measureCenteredMarkup 2.
  ""
  \markup 
  \override #'(line-width . 27) 
  \override #'(baseline-skip . 2.4)
  \justify { 
    Diese Pause gilt allezeit einen Tact, es sey
    im glei= chen oder ungleichen Zeit= ma├če.
  } 2 R2.
  \bar "|."

}

%%%%%

_______________________________________________
lilypond-user mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/lilypond-user

document.png (60K) Download Attachment