A.3.1 Una primera aproximación (ejemplo)
- El problema
Usando la entrada siguiente, el signo de ‘espressivo’ (es decir, los dos reguladores pequeños) deberían hacerse más anchos, pero no más altos.
{ f'\espressivo }
- Soluciones posibles
- crear un sello nuevo
- escalar el sello por omisión en la dirección del eje X
- Comentarios sobre esta solución
La solución A es factible. Sin embargo, dará como resultado un esfuerzo de codificación mayor. Por otro lado, la solución B es más económica, aunque tiene la desventaja de que no imprime resultados aceptables en todos los casos (si bien usted podría no saberlo hasta después de haberlo intentado).
⇒ elija la solución B.
- Codificación
- Si quiere manipular el sello por omisión tendrá que encontrar
información sobre él.
El signo de espressivo es un grob del tipo
Script
. Si buscamos esto en el IR (Script), encontramos‘stencil’ (stencil): ‘ly:script-interface::print’
Vamos a comprobar si es correcto. PAra asegurarnos de que afectamos al grob correcto, vamos a emplear colores. Existe una función predefinida para ello, véase Scheme functions.
-- Function: stencil-with-color stencil color Return a modified version of the given stencil that is colored with the given color. See ‘normalize-color’ for possible color formats.
-- Function: normalize-color color Convert a color given in any of the supported formats into a list of 4 numbers: R, G, B, A. Possible formats are: such a list of 4 numbers; a list of 3 numbers (transparency defaults to 1.0); a CSS string (named color, or “#RRGGBB”, or “#RRGGBBAA”, or “#RGB”, or “#RGBA”).
Usando un color con nombre (‘red’, rojo), ello da como resultado el siguiente código.
colorDefaultStencil = \once \override Script.stencil = % `lambda` starts a procedure; its argument is `grob`. #(lambda (grob) ;; With `let`, local variables are defined. (let ((stil (ly:script-interface::print grob))) ;; The procedure returns the colored default stencil. (stencil-with-color stil red))) { \colorDefaultStencil f'\espressivo }
Estupendo, funciona.
- Esta clase de operación ( tomar un sello o propiedad por omisión y
devolver una versión modificada del mismo) es muy común, y
LilyPond aporta una función especial para ello:
grob-transformer
.-- Function: grob-transformer property func Create an override value good for applying FUNC to either pure or unpure values. FUNC is called with the respective grob as first argument and the default value (after resolving all callbacks) as the second.
Vamos a probarla (el concepto de ‘pure’ frente a ‘unpure’ se explica más tarde, see Contenedores Unpure-pure; podemos ignorarlo por el momento).
colorDefaultStencil = \once \override Script.stencil = #(grob-transformer 'stencil (lambda (grob orig) (stencil-with-color orig red))) { \colorDefaultStencil f'\espressivo }
¡Éxito total!
- Para obtener un sello a diferente escala tenemos que usar
-- Function: ly:stencil-scale stil x y Scale stencil STIL using the horizontal and vertical scaling factors X and optional Y (defaulting to X). Negative values flip or mirror STIL without changing its origin; this may result in collisions unless it is repositioned.
tomado del mismo capítulo en el manual de Referencia del Funcionamiento Interno.
Resultado:
scaleColorDefaultStencil = \once \override Script.stencil = #(grob-transformer 'stencil (lambda (grob orig) (stencil-with-color (ly:stencil-scale orig ;; 1 is the neutral element with ly:stencil-scale, ;; i.e., scaling with '1 1' (for x- and y-axis) ;; returns a visibly unchanged stencil. 2 1) red))) { \scaleColorDefaultStencil f'\espressivo }
Aparte del color, parece ser la salida deseada.
- Sin embargo existen algunos problemas, como se puede ver en el
ejemplo siguiente:
{ \scaleColorDefaultStencil f'_\espressivo ^\fermata }
- − El calderón está a escala también.
- − Es fastidioso tener que teclear la instrucción antes de la nota o
notas y el
\espressivo
después de la nota.
La solución para ambos: ¡use
\tweak
!{ f'-\tweak stencil #(grob-transformer 'stencil (lambda (grob orig) (stencil-with-color (ly:stencil-scale orig 2 1) red))) _\espressivo ^\fermata }
Esto hace lo que queríamos aunque no es agradable teclear tanto; vamos a definir una variable y usarla para el trucaje. Con algo de copiar y pegar obtenemos lo siguiente.
#(define longer-script (grob-transformer 'stencil (lambda (grob orig) (stencil-with-color (ly:stencil-scale orig 2 1) red)))) { f'-\tweak stencil #longer-script _\espressivo ^\fermata }
FUnciona correctamente, aunque los valores de escalado están codificados de forma rígida, y escribir repetidamente
-\tweak stencil #longer-script
aún resulta incómodo.Para corregirlo, vamos a introducir primero una serie de variables dentro de la función
longer-script
para los valores de escalado en x e y.#(define (longer-script x y) (grob-transformer 'stencil (lambda (grob orig) (stencil-with-color (ly:stencil-scale orig x y) red))))
En segundo lugar, para reducir la cantidad de tecleo, definimos una función de evento, see Funciones de eventos. Los elementos dentro del primer grupo de paréntesis (‘(x-val y-val)’) son las variables de función, los elementos dentro del segundo paréntesis agrupan los respectivos tipos de variables (comprobamos para número dos veces; consulte Predefined type predicates para ver todas las comprobaciones posibles).
scaleEspr = #(define-event-function (x-val y-val) (number? number?) #{ \tweak stencil #(longer-script x-val y-val) \espressivo #}) { f'_\scaleEspr 2 1 ^\fermata }
Correcto, ¡funciona como se esperaba! Observe el uso de
#{ … #}
: dentro de esta construcción de Scheme, podemos usar sintaxis de LilyPond, y los argumentos de la función (como x-val) se expanden adecuadamente. See Bloques de código de LilyPond.
- Si quiere manipular el sello por omisión tendrá que encontrar
información sobre él.
- El código terminado
Para terminar, vamos a poner algo de orden.
- − Solo queremos realizar un escalado en la dirección del eje X, por lo que codificamos de forma rígida el escalado en el eje Y dentro de la función de evento.
- − Eliminar el color.
Al final, todo esto conduce al siguiente código.
#(define (longer-script x y) (grob-transformer 'stencil (lambda (grob orig) (ly:stencil-scale orig x y)))) longEspressivo = #(define-event-function (x-val) (number?) #{ \tweak stencil #(longer-script x-val 1) \espressivo #}) { f'^\longEspressivo #2 _\fermata }
Voilà!
La principal ventaja de usar
grob-transformer
es que ya no nos tenemos que preocupar por el nombre concreto de la función de sello. En el siguiente ejemplo rotamos 90 grados el sello de una ligadura de expresión y una barra; el hecho de que las funciones de sello se llamen respectivamentely:slur::print
yly:beam::print
, no nos preocupa.#(define rotate-90 (grob-transformer 'stencil (lambda (grob orig) (ly:stencil-rotate orig 90 0 0)))) { f'8( g') f'8-\tweak stencil #rotate-90 ( g') f'8[ g'] f'8-\tweak stencil #rotate-90 [ g'] }