@node Conteneurs requalifiants @subsection Conteneurs requalifiants @translationof Unpure-pure containers @cindex Scheme, pure containers @cindex Scheme, unpure containers @cindex pure containers, Scheme @cindex unpure containers, Scheme @cindex horizontal spacing, overriding Les conteneurs requalifiants permettent de faciliter le calcul des espacements en cas de modification du @emph{Y-axis} -- plus particulièrement les composantes @code{Y-offset} et @code{Y-extent} -- à l'aide d'une fonction scheme en lieu et place de valeurs. Unpure-pure containers are useful for overriding @emph{Y-axis} spacing calculations - specifically @code{Y-offset} and @code{Y-extent} - with a Scheme function instead of a literal (i.e. a number or pair). L'envergure verticale (@code{Y-extent}) de certains objets dépend de la propriété @address@hidden; jouer sur leur stencil requiert alors une intervention supplémentaire au niveau du @code{Y-extent} à l'aide d'un conteneur transitoire. Lorsq'une fonction affecte un @code{Y-offset} ou un @code{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 address@hidden; elle renvoie habituellement @samp{0} ou @samp{'(0 . 0)}, ce qui peut engendrer des collisions. Une fonction @qq{pure} évitera d'avorter la construction des propriétés ou objets, qui de ce fait verront leurs arguments liés à la verticalité (@code{Y-axis}) correctement évalués. For certain grobs, the @code{Y-extent} is based on the @code{stencil} property, overriding the stencil property of one of these will require an additional @code{Y-extent} override with an unpure-pure container. When a function overrides a @code{Y-offset} and/or @code{Y-extent} it is assumed that this will trigger line breaking calculations too early during compilation. So the function is not evaluated at all (usually returning a value of @samp{0} or @samp{'(0 . 0)}) which can result in collisions. A @q{pure} function will not affect properties, objects or grob suicides and therefore will always have its Y-axis-related evaluated correctly. Il existe actuellement une trentaine de fonctions que l'on peut qualifier de @qq{pures}. Le recours à un conteneur transitoire permet de requalifier une fonction de telle sorte qu'elle soit reconnue comme @qq{pure} et soit donc évaluée @strong{avant} détermination des sauts de ligne -- l'espacement horizontal sera de fait ajusté en temps et en heure. La fonction @qq{impure} sera ensuite évaluée @strong{après} le positionnement des sauts de ligne. Currently, there are about thirty functions that are already considered @q{pure} and Unpure-pure containers are a way to set functions not on this list as @q{pure}. The @q{pure} function is evaluated @emph{before} any line-breaking and so the horizontal spacing can be adjusted @q{in time}. The @q{unpure} function is then evaluated @emph{after} line breaking. @warning{Il n'est pas toujours facile d'avoir l'assurance qu'une fonction soit qualifiée de @address@hidden; aussi nous vous recommandons d'éviter d'utiliser les objets @code{Beam} or @code{VerticalAlignment} lorsque vous désirez en créer une.} @warning{As it is difficult to always know which functions are on this list we recommend that any @q{pure} functions you create do not use @code{Beam} or @code{VerticalAlignment} grobs.} Un conteneur requalifiant se construit selon la syntaxe An unpure-pure container is constructed as follows; @code{(ly:make-unpure-pure-container f0 f1)} où @code{f0} est une fonction prenant @var{n} arguments (@var{n >= 1}), le premier devant être l'objet en address@hidden; il s'agit de la fonction dont le résultat sera réutilisé. @var{f1} est la fonction qui sera qualifée de @qq{pure}. Elle prend @var{n + 2} arguments, le premier devant être lui aussi l'objet en question, et les second et troisième étant respectivement les @qq{point de départ} (@var{start}) et @qq{point d'arrivée} (@var{end}). where @code{f0} is a function taking @var{n} arguments (@var{n >= 1}) and the first argument must always be the grob. This is the function that gives the actual result. @var{f1} is the function being labeled as @q{pure} that takes @var{n + 2} arguments. Again, the first argument must always still be the grob but the second and third are @q{start} and @q{end} arguments. @var{start} et @var{end} sont dans tous les cas des valeurs fictives qui trouveront leur utilité dans le cas d'obets de type @code{Spanners}, tels les soufflets (@code{Hairpin}) ou barres de ligature (@code{Beam}), en retournant les différentes estimations de hauteur basées sur leurs début et fin d'extension. @var{start} and @var{end} are, for all intents and purposes, dummy values that only matter for @code{Spanners} (i.e @code{Hairpin} or @code{Beam}), that can return different height estimations based on a starting and ending column. Viennent ensuite les autres arguments de la fonction initiale @code{f0} -- autrement dit aucun si @var{n = 1}. The rest are the other arguments to the first function (which may be none if @var{n = 1}). Les résultats de la deuxième fonction (@code{f1}) permettent une valeur approximative qui sera ensuite utilisée par la fonction initiale aux fins d'ajustement lors des phases ultérieures d'espacement. The results of the second function are used as an approximation of the value needed which is then used by the first function to get the real value which is then used for fine-tuning much later during the spacing process. @lilypond[verbatim,quote,ragged-right] #(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 cisis c \smartSquareLineCircleSpace cis4 ces cisis c } @end lilypond 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 ne 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 address@hidden; les collisions sont alors évitées du fait de l'espace réservé à chacune des têtes. In the first measure, without the unpure-pure container, the spacing engine does not know the width of the note head and lets it collide with the accidentals. In the second measure, with unpure-pure containers, the spacing engine knows the width of the note heads and avoids the collision by lengthening the line accordingly. Lorsqu'il s'agit de calculs simples, les fonctions, tant pour la partie @qq{pure} que pour la partie @qq{impure}, peuvent être identiques au détail près du nombre d'arguments utilisés ou du domaiane d'intervention. Usually for simple calculations nearly-identical functions for both the @q{unpure} and @q{pure} parts can be used, by only changing the number of arguments passed to, and the scope of, the function. @warning{Le fait de qualifier une fonction de @qq{pure} alors qu'elle ne l'est pas peut générer des résultats imprévisibles.} @warning{If a function is labeled as @q{pure} and it turns out not to be, the results can be unexpected.}