30.4 Adjusting horizontal spacing for specific layout objects

In addition to the general-purpose parameters of the default spacing algorithm that apply to all elements of the score or spacing section, several properties serve to operate adjustments on a per-object-type-basis. Examples include adjusting the distance from clefs to time signatures, but not from clefs to notes when there is no time signature, or stretching notes further apart in the presence of a printed text so that it does not overlap with the next note. Tweaking these first requires identifying the type of spacing at play.


30.4.1 Overview of object-specific horizontal spacing tweaks

Layout objects that have a horizontally fixed position are called items (as opposed to spanners) and, for the purpose of horizontal spacing, are grouped into columns. Note heads and rests, forming the main musical material, together with those objects that are logically linked to them – accidentals, articulations, stems, dots, etc. – are all part of ‘musical columns’ (represented by NoteColumn grobs). Prefatory matter, such as clefs, time signatures and bar lines, is grouped into ‘non-musical columns’ (represented by NonMusicalPaperColumn grobs). In the following example, musical items are colored red, while non-musical items are blue.

[image of music]

This example shows that there is an alternation between musical and non-musical columns. The first non-musical column contains a clef and a time signature. The first musical column has a note head with its stem and articulation. The second non-musical column is empty and thus removed during the layout process. The second musical column has a note again. The third non-musical column contains a clef, a bar line and a rehearsal mark, etc.

Within one column, spacing is fixed. On the other hand, the amount of space between consecutive columns is flexible. As we shall see, the methods to adjust spacing within a column and between columns are different.


30.4.2 Spacing between adjacent non-musical items

Within a non-musical column, items are laid out in a specific order. For instance, with the set of items in the picture below, the default order places the breathing sign first, then the clef, then the bar line, the key cancellation and key signature, and finally the time signature (this is controlled by the BreakAlignment.break-align-orders property).

\relative {
  \key g \minor
  g'1
  \breathe
  \clef alto
  \time 6/8
  \key a \major
  aes4.
}
[image of music]

The distance between two adjacent items from the same non-musical column is controlled by the value of the space-alist property of the leftmost one of the two. space-alist has the form of an associative list mapping break-align symbols to (spacing-style . value) pairs. A breakable item’s break-align symbol is given by the value of its break-align-symbol property; standard choices are listed in break-alignment-interface. Spacing styles are listed in break-aligned-interface. Among the available options, only extra-space and minimum-space are relevant for tweaking the space between non-musical items. The difference is that extra-space measures the padding from the right of the first object to the left of the second object while minimum-space counts from the left of the first object. Thus, a way to move the bar line farther from the clef is:

\relative {
  \key g \minor
  g'1
  \override Staff.Clef.space-alist.staff-bar = #'(extra-space . 4)
  \breathe
  \clef alto
  \time 6/8
  \key a \major
  aes4.
}
[image of music]

space-alist settings, not limited to the two spacing styles described above, are also possible to override the spacing between different columns. However, this kind of spacing is flexible, and does not merely depend on the types of object involved but also their shapes. Methods specific to it are documented in the next section.

Selected Snippets

Separating key cancellations from key signature changes

By default, the accidentals used for key cancellations are placed adjacent to those for key signature changes. This behavior can be changed by overriding the break-align-orders property of the BreakAlignment grob.

The value of break-align-orders is a vector of length 3, with quoted lists of breakable items as elements. Each list describes the default order of prefatory matter at the end, in the middle, and at the beginning of a line, respectively. We are only interested in changing the behaviour in the middle of a line.

If you look up the definition of break-align-orders in LilyPond’s Internal Reference (see the BreakAlignment grob), you get the following order in the second element:

...
staff-bar
key-cancellation
key-signature
...

We want to change that, moving key-cancellation before staff-bar. To make this happen we use the grob-transformer function, which gives us access to the original vector as the second argument of the lambda function, here called orig (we don’t need the first argument, grob). We return a new vector, with unchanged first and last elements. For the middle element, we first remove key-cancellation from the list, then adding it again before staff-bar.

#(define (insert-before where what lst)
   (cond
    ((null? lst)           ; If the list is empty,
     (list what))          ; return a single-element list.
    ((eq? where (car lst)) ; If we find symbol `where`,
     (cons what lst))      ; insert `what` before curr. position.
    (else                  ; Otherwise keep building the list by
     (cons (car lst)       ; adding the current element and
                           ; recursing with the next element.
           (insert-before where what (cdr lst))))))

cancellationFirst =
\override Score.BreakAlignment.break-align-orders =
#(grob-transformer
  'break-align-orders
  (lambda (grob orig)
    (let* ((middle (vector-ref orig 1))
           (middle (delq 'key-cancellation middle))
           (middle (insert-before
                    'staff-bar 'key-cancellation middle)))
      (vector
       ;; end of line
       (vector-ref orig 0)
       ;; middle of line
       middle
       ;; beginning of line
       (vector-ref orig 2)))))

music = { \key es \major d'1 \bar "||"
          \key a \major d'1 }

{ <>^\markup "default"
  \music }

{ <>^\markup "cancellation first"
  \cancellationFirst
  \music }

\paper { tagline = ##f }
[image of music]

See also

Notation Reference: Using the break-alignable-interface.

Extending LilyPond: Association lists (alists).

Internals Reference: Break_align_engraver, BreakAlignGroup, BreakAlignment, break-alignable-interface, break-aligned-interface, break-alignment-interface.


30.4.3 Spacing between adjacent columns

Contrary to spacing within one column, spacing between adjacent columns is flexible and stretches or compresses according to the density of music on the line. By default, columns may even overlap in some situations. The following example shows three cases. The second accidental slides behind the bar line, while the third one overlaps with the clef. Also, the tempo marking Presto spans several columns. Observe how the first accidental, which remains within the vertical extent of the bar line on its left, is placed further apart.

[image of music]

These spacing rules can be overridden. This is done by modifying the width and height that an object takes in horizontal spacing. The relevant properties are extra-spacing-width and extra-spacing-height. When unset, an object takes as much space in horizontal spacing as its X-extent and Y-extent properties allow. These are accurate values of its dimensions. The extra-spacing-width and extra-spacing-height properties make an object larger or smaller for computation of horizontal spacing between columns only, but preserve its dimensions for other spacing types.

{
  \textMark "Default"
  c'2 2 cis'2 2
}

{
  \textMark "Modified X-extent"
  \override NoteHead.X-extent = #'(-2 . 2)
  c'2 2 cis'2 2
}

{
  \textMark "Modified extra-spacing-width"
  \override NoteHead.extra-spacing-width = #'(-2 . 2)
  c'2 2 cis'2 2
}
[image of music]

extra-spacing-width and extra-spacing-height are pairs of numbers, which are added to the dimensions on each axis. For instance, setting extra-spacing-height to '(-2 . 3) makes the object three units larger on the top, and two units larger on the bottom (limit lowered by 2). The following example shows how to use extra-spacing-height to change the limit after which accidentals no longer overlap with bar lines.

music = \relative {
  \time 1/4
  cis8 8 | dis8 8 | eis8 8 | fis8 8 |
  gis8 8 | ais8 8 | bis8 8 | cis8 8 |
}

{
  \music
}

{
  \override Accidental.extra-spacing-height = #'(0 . 1.0)
  \music
}
[image of music]

The value '(+inf.0 . -inf.0) for extra-spacing-width or extra-spacing-height removes the object’s presence.

music = \relative {
  \time 1/4
  cis8 8 | dis8 8 | eis8 8 | fis8 8 |
  gis8 8 | ais8 8 | bis8 8 | cis8 8 |
}

{
  \override Accidental.extra-spacing-height = #'(+inf.0 . -inf.0)
  \music
}
[image of music]

Conversely, an extra-spacing-height of '(-inf.0 . +inf.0) makes the object infinitely high, preventing overlap with another column completely. The below example demonstrates this technique on Accidental and MetronomeMark. In the case of MetronomeMark, it is necessary to set extra-spacing-width to '(0 . 0) because the default is '(+inf.0 . -inf.0), and even an infinitely high object does not take space if it has no width.

{
  \override Score.MetronomeMark.extra-spacing-width =
    #'(0 . 0)
  \override Score.MetronomeMark.extra-spacing-height =
    #'(-inf.0 . +inf.0)
  \override Accidental.extra-spacing-height =
    #'(-inf.0 . +inf.0)
  cis'4 r2.
  \tempo Presto
  fis16 8 16 4 \clef alto cis4 fis4
}
[image of music]

See also

Internals Reference: item-interface, separation-item-interface.


LilyPond Notation Reference v2.25.27 (development-branch).