2.8 Conteneurs requalifiants

Note : Bien que cette rubrique reflète la situation actuelle, l’exemple qui suit est discutable et ne met rien en évidence.

Les conteneurs requalifiants permettent de faciliter le calcul des espacements en cas de modification du Y-axis – plus particulièrement les composantes Y-offset et Y-extent – à l’aide d’une fonction Scheme en lieu et place de valeurs.

L’envergure verticale (Y-extent) de certains objets dépend de la propriété stencil ; jouer sur leur stencil requiert alors une intervention supplémentaire au niveau du Y-extent à l’aide d’un conteneur transitoire. Lorsqu’une fonction affecte un Y-offset ou un Y-extent, cela déclenche la détermination des sauts de ligne de manière anticipée dans la séquence des traitements. Il en résulte que cette opération n’est en fait pas exécutée ; elle renvoie habituellement ‘0’ ou ‘'(0 . 0)’, ce qui peut engendrer des collisions. Une fonction « pure » évitera d’avorter la construction des propriétés ou objets, qui de ce fait verront leurs arguments liés à la verticalité (Y-axis) correctement évalués.

Il existe actuellement une trentaine de fonctions que l’on peut qualifier de « pures ». Le recours à un conteneur transitoire permet de requalifier une fonction de telle sorte qu’elle soit reconnue comme « pure » et soit donc évaluée avant détermination des sauts de ligne – l’espacement horizontal sera de fait ajusté en temps et en heure. La fonction « impure » sera ensuite évaluée après le positionnement des sauts de ligne.

Note : Il n’est pas toujours facile d’avoir l’assurance qu’une fonction soit qualifiée de « pure » ; aussi nous vous recommandons d’éviter d’utiliser les objets Beam ou VerticalAlignment lorsque vous désirez en créer une.

Un conteneur requalifiant se construit selon la syntaxe

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

f0 est une fonction prenant n arguments (n_>=_1), le premier devant être l’objet en question ; il s’agit de la fonction dont le résultat sera réutilisé. f1 est la fonction qui sera qualifiée de « pure ». Elle prend n_+_2 arguments, le premier devant être lui aussi l’objet en question, et les second et troisième étant respectivement les « point de départ » (start) et « point d’arrivée » (end).

start et end sont dans tous les cas des valeurs fictives qui trouveront leur utilité dans le cas d’objets de type Spanner, tels les soufflets (Hairpin) ou barres de ligature (Beam), en retournant les différentes estimations de hauteur basées sur leurs début et fin d’extension.

Viennent ensuite les autres arguments de la fonction initiale f0 – autrement dit aucun si n_=_1.

Les résultats de la deuxième fonction (f1) permettent une approximation des valeurs qui seront ensuite utilisées par la fonction initiale aux fins d’ajustement lors des phases ultérieures d’espacement.

#(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]

La première mesure de l’exemple ci-dessus ne fait pas appel à un conteneur requalifiant ; le moteur d’espacement n’a donc aucune connaissance de la largeur des têtes de note et ne peut empêcher qu’elles chevauchent les altérations. Dans la deuxième mesure, par contre, le recours à un conteneur requalifiant informe le moteur d’espacement de la largeur des têtes de note ; les collisions sont alors évitées du fait de l’espace réservé à chacune des têtes.

Lorsqu’il s’agit de calculs simples, les fonctions, tant pour la partie « pure » que pour la partie « impure », peuvent être identiques au détail près du nombre d’arguments utilisés ou du domaine d’intervention. Ce cas de figure étant relativement répandu, ly:make-unpure-pure-container construira d’elle même cette deuxième lorsqu’il ne sera fait appel qu’à une seule fonction en argument.

Note : Le fait de qualifier une fonction de « pure » alors qu’elle ne l’est pas peut générer des résultats imprévisibles.


LilyPond — Extension des fonctionnalités v2.23.82 (branche de développement).