2.8 Conteneurs requalifiants (GNU LilyPond – Extension des fonctionnalités)

### 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)

où `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
>     }

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.

#### GNU LilyPond – Extension des fonctionnalités v2.26.0 (stable-branch).

- 1 Tutoriel Scheme
  - 1.1 Introduction à Scheme
    - 1.1.1 Le bac à sable de Scheme
    - 1.1.2 Scheme et les variables
    - 1.1.3 Types de données Scheme simples
    - 1.1.4 Types de données Scheme composites
      - Paires
      - Listes
      - Listes associatives (alists)
      - Tables de hachage
    - 1.1.5 Scheme et les calculs
    - 1.1.6 Scheme et les procédures
      - Définition de procédures
      - Prédicats
      - Valeurs de retour
    - 1.1.7 Scheme et les conditions
      - if
      - cond
  - 1.2 Scheme et LilyPond
    - 1.2.1 Syntaxe Scheme dans LilyPond
    - 1.2.2 Variables LilyPond
    - 1.2.3 Débogage de code Scheme
    - 1.2.4 Saisie de variables et Scheme
    - 1.2.5 Import de code Scheme dans LilyPond
    - 1.2.6 Propriétés des objets
    - 1.2.7 Variables LilyPond composites
      - Décalages (offsets)
      - Fractions
      - Étendues (extents)
      - Propriété en alist
      - Chaînes d’alist
    - 1.2.8 Le modèle de boîte de LilyPond
    - 1.2.9 Représentation interne de la musique
  - 1.3 Construction de fonctions complexes
    - 1.3.1 Première approche (exemple)
    - 1.3.2 Affichage d’expressions musicales
    - 1.3.3 Propriétés musicales
    - 1.3.4 Doublement d’une note avec liaison (exemple)
    - 1.3.5 Ajout d’articulation à des notes (exemple)
- 2 Interfaces pour programmeurs
  - 2.1 Blocs de code LilyPond
  - 2.2 Fonctions Scheme
    - 2.2.1 Définition de fonctions Scheme
    - 2.2.2 Utilisation de fonctions Scheme
    - 2.2.3 Fonctions Scheme fantômes
  - 2.3 Fonctions musicales
    - 2.3.1 Définition de fonctions musicales
    - 2.3.2 Utilisation de fonctions musicales
    - 2.3.3 Fonctions de substitution simple
    - 2.3.4 Fonctions de substitution intermédiaires
    - 2.3.5 De l’usage des mathématiques dans les fonctions
    - 2.3.6 Fonctions dépourvues d’argument
    - 2.3.7 Fonctions musicales fantômes
  - 2.4 Fonctions événementielles
  - 2.5 Fonctions pour markups
    - 2.5.1 Construction d’un markup en Scheme
    - 2.5.2 Fonctionnement interne des markups
    - 2.5.3 Définition d’une nouvelle commande de markup
      - Syntaxe d’une commande markup
      - Attribution de propriétés
      - Exemple commenté
      - Adaptation d’une commande incorporée
      - Conversion de markups en chaînes
    - 2.5.4 Définition d’une nouvelle commande de liste de markups
  - 2.6 Contextes pour programmeurs
    - 2.6.1 Évaluation d’un contexte
    - 2.6.2 Application d’une fonction à tous les objets de mise en forme
  - 2.7 Fonctions de rappel
  - 2.8 Conteneurs requalifiants
  - 2.9 Retouches complexes
- 3 Interfaces LilyPond Scheme
- Appendix A GNU Free Documentation License
- Appendix B Index