5.5.5 Reine und unreine Container

Unreine und reine Container (engl. unpure/pure containers) sind nützlich, wenn man die Berechnungen der Platzierungen für die Y-Achse verändern will, insbesondere für Y-offset und Y-extent. Mit diesen Containern kann die Veränderung durch eine Scheme-Funktion anstelle einer direkten Zahl oder eines Paares vorgenommen werden.

Für bestimmte Grobs basiert die Eigenschaft Y-extent auf der stencil-Eigenschaft. Wenn diese mit \override verändert werden soll, braucht man eine zusätzliche Veränderung von Y-extent mit einem unreinen-reinen Container. Wenn eine Funktion Y-offset und/oder Y-extent verändert, wird angenommen, dass dadurch Zeilenumbruchsberechnungen zu früh während der Kompilation aufgerufen werden. Die Funktion wird also überhaupt nicht ausgewertet (und gibt also normalerweise den Wert ‘0’ oder ‘'(0 . 0)’ zurück), wodurch sich Zusammenstöße ergeben können. Eine „saubere“ Funktion beeinflusst keine Eigeschaften, Objekte oder Grob-Suizide, weshalb ihre Werte, die sich auf Y-axis beziehen, richtig berechnet werden.

Es gibt zuzeit etwa 30 Funktionen, die schon als „sauber“ erachtet werden, und unsaubere-saubere Container sind eine Möglichkeit, auch Funktionen, die sich nicht auf dieser Liste befinden, als „sauber“ zu markieren. Die „saubere“ Funktion wird ausgewertet, bevor Seitenumbruch stattfindet, sodass die horizontale Platzierung „rechtzeitig“ stattfindet. Die „unsaubere“ Funktion wird dann nach dem Seitenumbruch ausgewertet.

Achtung: Da es schwierig ist, immer sicher zu sein, welche Funktionen sich auf dieser Liste befinden, wird empfohlen, dass die selbsterstellten „sauberen“ Funktionen nicht die Grobs Beam oder VerticalAlignment einsetzen.

Ein unsauberer-sauberer Container wird wie folgend erstellt:

(ly:make-unpure-pure-container f0 f1)

wobei f0 eine Fuktion ist, die n Arguments braucht (n >= 1) und deren erstes Argument immer der Grob sein muss. Das ist die Funktion, die das eigentliche Resultat ausgibt. f1 ist die Funktion, die als „sauber“ bezeichnet wird, und braucht n + 2 Argumente. Wiederum muss das erste Argument immer der Grob sein, aber das erste und zweite Argument sind „Beginn-“ und „Endeargumente“.

start (Beginn) und end (Ende) sind absichtlich nur Platzhalter, die nur für die Strecker gelten (etwa Hairpin oder Beam), die unterschiedliche Höhenberechnungen je nach beginnender und endender Note ausgeben können.

Der Rest sind andere Argumente für die erste Funktion (es können auch Null sein, wenn n = 1).

Die Ergebnisse der zweiten Funktion werden als Näherungswert des benötigten Wertes benutzt, welche dann von der ersten Funktion eingesetzt wird, um den wirklichen Wert auszugeben, mit dem dann sehr viel später im Layoutprozess die Platzierung justiert werden soll.

#(define (square-line-circle-space grob)
(let* ((pitch (ly:event-property (ly:grob-property grob 'cause) 'pitch))
      (notename (ly:pitch-notename pitch)))
 (if (= 0 (modulo notename 2))
     (make-circle-stencil 0.5 0.0 #t)
     (make-filled-box-stencil '(0 . 1.0)
                              '(-0.5 . 0.5)))))

squareLineCircleSpace = {
  \override NoteHead.stencil = #square-line-circle-space
}

smartSquareLineCircleSpace = {
  \squareLineCircleSpace
  \override NoteHead.Y-extent =
   #(ly:make-unpure-pure-container
      ly:grob::stencil-height
      (lambda (grob start end) (ly:grob::stencil-height grob)))
}

\new Voice \with { \remove Stem_engraver }
\relative c'' {
  \squareLineCircleSpace
  cis4 ces disis d
  \smartSquareLineCircleSpace
  cis4 ces disis d
}

[image of music]

Im ersten Takt weiß die Layoutmaschine ohne den unsauberen-sauberen Container nicht die Breite des Notenkopfes und lässt ihn deshalb mit den Versetzungszeichen zusammenstoßen. Im zweiten Takt, mit unreinen-reinen Containern, weiß die Layoutmaschine die Breite des Notenkopfes und vermeidet den Zusammenstoß, indem die Zeile entsprechend verlängert wird.

Normalerweise können für eine einfache Berechnungen fast identische Funktionen für den „unsauberen“ und „sauberen“ Teil benutzt werden, indem nur die Zahl der Argumente und die Reichweite der Funktion verändert wird.

Achtung: Wenn eine Funktion als „sauber“ bezeichnet ist und das aber nicht ist, können unerwartete Ergebnisse auftreten.


LilyPond Benutzerhandbuch v2.25.22 (development-branch).