| [ < ] | [ > ] | [ << ] | [ Subir ] | [ >> ] | [Arriba] | [Índice general] | [Índice] | [ ? ] |
@translationof Markup functions
Los elementos de marcado están implementados como funciones de
Scheme especiales que producen un objeto Stencil dada una
serie de argumentos.
| [ < ] | [ > ] | [ << ] | [ Subir ] | [ >> ] | [Arriba] | [Índice general] | [Índice] | [ ? ] |
@translationof Markup construction in Scheme
Las expresiones de marcado se representan internamente en Scheme
usando el macro markup:
(markup expr) |
Para ver una expresión de marcado en su forma de Scheme, utilice
la instrucción \displayScheme:
\displayScheme
\markup {
\column {
\line { \bold \italic "hola" \raise #0.4 "mundo" }
\larger \line { fulano fulanito menganito }
}
}
|
La compilación del código anterior envía a la consola lo siguiente:
(markup
#:line
(#:column
(#:line
(#:bold (#:italic "hola") #:raise 0.4 "mundo")
#:larger
(#:line
(#:simple "fulano" #:simple "fulanito" #:simple "menganito")))))
|
Para evitar que el marcado se imprima en la página, use
‘\void \displayScheme marcado’. Asimismo, como
ocurre con la instrucción \displayMusic, la salida de
\displayScheme se puede guardar en un archivo externo.
Véase Presentación de las expresiones musicales.
Este ejemplo muestra las principales reglas de traducción entre
la sintaxis del marcado normal de LilyPond y la sintaxis del
marcado de Scheme. La utilización de #{ … #} para
escribir en la sintaxis de LilyPond será con frecuencia lo más
conveniente, pero explicamos cómo usar la macro markup
para obtener una solución sólo con Scheme.
LilyPond Scheme \markup marcado1(markup marcado1)\markup { marcado1 marcado2 … }(markup marcado1 marcado2 … )\instruccion#:instruccion\variablevariable\center-column { … }#:center-column ( … )cadena"cadena"#argumento-de-schemeargumento-de-scheme
Todo el lenguaje Scheme está accesible dentro del macro
markup. Por ejemplo, podemos usar llamadas a funciones
dentro de markup para así manipular cadenas de caracteres.
Esto es útil si se están definiendo instrucciones de marcado
nuevas (véase Definición de una instrucción de marcado nueva).
El argumento markup-list de instrucciones como #:line,
#:center y #:column no puede ser una variable ni el
resultado de la llamada a una función.
(markup #:line (funcion-que-devuelve-marcados)) |
no es válido. Hay que usar las funciones
make-line-markup, make-center-markup o
make-column-markup en su lugar:
(markup (make-line-markup (funcion-que-devuelve-marcados))) |
| [ < ] | [ > ] | [ << ] | [ Subir ] | [ >> ] | [Arriba] | [Índice general] | [Índice] | [ ? ] |
@translationof How markups work internally
En un elemento de marcado como
\raise #0.5 "ejemplo de texto" |
\raise se representa en realidad por medio de la función
raise-markup. La expresión de marcado se almacena como
(list raise-markup 0.5 (list simple-markup "ejemplo de texto")) |
Cuando el marcado se convierte en objetos imprimibles (Stencils o
sellos), se llama la función raise-markup como
(apply raise-markup
\objeto de marcado
lista de listas asociativas de propiedades
0.5
el marcado "ejemplo de texto")
|
Primero la función raise-markup crea el sello para la
cadena ejemplo de texto, y después eleva el sello Stencil
en 0.5 espacios de pentagrama. Este es un ejemplo bastante
simple; en el resto de la sección podrán verse ejemplos más
complejos, así como en ‘scm/define-markup-commands.scm’.
| [ < ] | [ > ] | [ << ] | [ Subir ] | [ >> ] | [Arriba] | [Índice general] | [Índice] | [ ? ] |
@translationof New markup command definition
Esta sección trata sobre la definición de nuevas instrucciones de marcado.
| Sintaxis de la definición de instrucciones de marcado | ||
| Acerca de las propiedades | ||
| Un ejemplo completo | ||
| Adaptación de instrucciones incorporadas |
| [ < ] | [ > ] | [ << ] | [ Subir ] | [ >> ] | [Arriba] | [Índice general] | [Índice] | [ ? ] |
@translationof Markup command definition syntax
Se pueden definir instrucciones de marcado nuevas usando el macro
de Scheme define-markup-command, en el nivel sintáctico
superior.
(define-markup-command (nombre-de-la-instruccion layout props arg1 arg2 …)
(tipo-de-arg1? tipo-de-arg2? …)
[ #:properties ((propiedad1 valor-predeterminado1)
…) ]
…command body…)
|
Los argumentos son
nombre-de-la-instruccionnombre de la instrucción de marcado
layoutla definición de ‘layout’ (disposición).
propsuna lista de listas asociativas, que contienen todas las propiedades activas.
argiargumento i-ésimo de la instrucción
tipo-de-argi?predicado de tipo para el argumento i-ésimo
Si la instrucción utiliza propiedades de los argumentos
props, se puede usar la palabra clave #:properties
para especificar qué propiedades se usan, así como sus valores
predeterminados.
Los argumentos se distinguen según su tipo:
markup?;
markup-list?;
list?, number?, boolean?, etc.
No existe ninguna limitación en el orden de los argumentos
(después de los argumentos estándar layout y
props). Sin embargo, las funciones de marcado que toman
un elemento de marcado como su último argumento son un poco
especiales porque podemos aplicarlas a una lista de marcados y el
resultado es una lista de marcados donde la función de marcado
(con los argumentos antecedentes especificados) se ha aplicado a
todos los elementos de la lista de marcados original.
Dado que la replicación de los argumentos precedentes para aplicar una función de marcado a una lista de marcados es poco costosa principalmente por los argumentos de Scheme, se evitan las caídas de rendimiento simplemente mediante la utilización de argumentos de Scheme para los argumentos antecedentes de las funciones de marcado que toman un marcado como su último argumento.
Las instrucciones de marcado tienen un ciclo de vida más bien
complejo. El cuerpo de la definición de una instrucción de
marcado es responsable de la conversión de los argumentos de la
instrucción de marcado en una expresión de sello que se devuelve.
Muy a menudo esto se lleva a cabo llamando a la función
interpret-markup sobre una expresión de marcado, pasándole
los argumentos layout y props. Por lo general, estos
argumentos se conocen solamente en una fase muy tardía de la
composición tipográfica. Las expresiones de marcado ya tienen
sus componentes ensamblados dentro de expresiones de marcado
cuando se expanden las instrucciones \markup (dentro de
una expresión de LilyPond) o la macro markup (dentro de
Scheme). La evaluación y la comprobación de tipos de los
argumentos de la instrucción de marcado tiene lugar en el momento
en que se interpretan \markup o markup.
Pero la conversión real de expresiones de marcado en expresiones
de sello mediante la ejecución de los cuerpos de función de
marcado solo tienen lugar cuando se llama a
interpret-markup sobre una expresión de marcado.
| [ < ] | [ > ] | [ << ] | [ Subir ] | [ >> ] | [Arriba] | [Índice general] | [Índice] | [ ? ] |
@translationof On properties
Los argumentos layout y props de las instrucciones
de marcado traen a escena un contexto para la interpretación del
marcado: tamaño de la tipografía, grueso de línea, etc.
El argumento layout permite el acceso a las propiedades
definidas en los bloques paper, usando la función
ly:output-def-lookup. Por ejemplo, el grueso de línea (el
mismo que el que se usa en las partituras) se lee usando:
(ly:output-def-lookup layout 'line-width) |
El argumento props hace accesibles algunas propiedades a
las instrucciones de marcado. Por ejemplo, cuando se interpreta
el marcado del título de un libro, todas las variables definidas
dentro del bloque \header se añaden automáticamente a
props, de manera que el marcado del título del libro puede
acceder al título del libro, el autor, etc. También es una forma
de configurar el comportamiento de una instrucción de marcado:
por ejemplo, cuando una instrucción utiliza tamaños de tipografía
durante el procesado, el tamaño se lee de props en vez de
tener un argumento font-size. El que llama a una
instrucción de marcado puede cambiar el valor de la propiedad del
tamaño de la tipografía con el objeto de modificar el
comportamiento. Utilice la palabra clave #:properties de
define-markup-command para especificar qué propiedades se
deben leer a partir de los argumentos de props.
El ejemplo de la sección siguiente ilustra cómo acceder y sobreescribir las propiedades de una instrucción de marcado.
| [ < ] | [ > ] | [ << ] | [ Subir ] | [ >> ] | [Arriba] | [Índice general] | [Índice] | [ ? ] |
@translationof A complete example
El ejemplo siguiente define una instrucción de marcado para trazar un rectángulo doble alrededor de un fragmento de texto.
En primer lugar, necesitamos construir un resultado aproximado
utilizando marcados. Una consulta a
marcado de texto
(notation)Instrucciones de marcado de texto sección ‘Instrucciones de marcado de texto’ en Referencia de la Notación nos muestra que es útil la instrucción
\box:
\markup \box \box HELLO
Ahora, consideramos que es preferible tener más separación entre
el texto y los rectángulos. Según la documentación de
\box, esta instrucción usa una propiedad
box-padding, cuyo valor predeterminado es 0.2. La
documentación también menciona cómo sobreescribir este valor:
\markup \box \override #'(box-padding . 0.6) \box A
Después, el relleno o separación entre los dos rectángulos nos parece muy pequeño, así que lo vamos a sobreescribir también:
\markup \override #'(box-padding . 0.4) \box \override #'(box-padding . 0.6) \box A
Repetir esta extensa instrucción de marcado una y otra vez sería
un quebradero de cabeza. Aquí es donde se necesita una
instrucción de marcado. Así pues, escribimos una instrucción de
marcado double-box, que toma un argumento (el texto).
Dibuja los dos rectángulos y añade una separación.
#(define-markup-command (double-box layout props text) (markup?)
"Trazar un rectángulo doble rodeando el texto."
(interpret-markup layout props
#{\markup \override #'(box-padding . 0.4) \box
\override #'(box-padding . 0.6) \box { #text }#}))
|
o, de forma equivalente,
#(define-markup-command (double-box layout props text) (markup?)
"Trazar un rectángulo doble rodeando el texto."
(interpret-markup layout props
(markup #:override '(box-padding . 0.4) #:box
#:override '(box-padding . 0.6) #:box text)))
|
text es el nombre del argumento de la instrucción, y
markup? es el tipo: lo identifica como un elemento de
marcado. La función interpret-markup se usa en casi todas
las instrucciones de marcado: construye un sello, usando
layout, props, y un elemento de marcado. En el
segundo caso, la marca se construye usando el macro de Scheme
markup, véase Construcción de elementos de marcado en Scheme. La transformación de una expresión \markup en
una expresión de marcado de Scheme es directa.
La instrucción nueva se puede usar como sigue:
\markup \double-box A |
Sería bueno hacer que la instrucción double-box fuera
personalizable: aquí, los valores de relleno box-padding
son fijos, y no se pueden cambiar por parte del usuario. Además,
sería mejor distinguir la separación entre los dos rectángulos,
del relleno entre el rectángulo interno y el texto. Así pues,
introducimos una nueva propiedad, inter-box-padding, para
el relleno entre los rectángulos. El box-padding se usará
para el relleno interno. Ahora el código nuevo es como se ve a
continuación:
#(define-markup-command (double-box layout props text) (markup?)
#:properties ((inter-box-padding 0.4)
(box-padding 0.6))
"Trazar un rectángulo doble rodeando el texto."
(interpret-markup layout props
#{\markup \override #`(box-padding . ,inter-box-padding) \box
\override #`(box-padding . ,box-padding) \box
{ #text } #}))
|
De nuevo, la versión equivalente que utiliza la macro de marcado sería:
#(define-markup-command (double-box layout props text) (markup?)
#:properties ((inter-box-padding 0.4)
(box-padding 0.6))
"Trazar un rectángulo doble rodeando el texto."
(interpret-markup layout props
(markup #:override `(box-padding . ,inter-box-padding) #:box
#:override `(box-padding . ,box-padding) #:box text)))
|
Aquí, la palabra clave #:properties se usa de manera que
las propiedades inter-box-padding y box-padding se
leen a partir del argumento props, y se les proporcionan
unos valores predeterminados si las propiedades no están
definidas.
Después estos valores se usan para sobreescribir las propiedades
box-padding usadas por las dos instrucciones \box.
Observe el apóstrofo invertido y la coma en el argumento de
\override: nos permiten introducir un valor de variable
dentro de una expresión literal.
Ahora, la instrucción se puede usar dentro de un elemento de marcado, y el relleno de los rectángulos se puede personalizar:
#(define-markup-command (double-box layout props text) (markup?) #:properties ((inter-box-padding 0.4) (box-padding 0.6)) "Draw a double box around text." (interpret-markup layout props #{\markup \override #`(box-padding . ,inter-box-padding) \box \override #`(box-padding . ,box-padding) \box { #text } #})) \markup \double-box A \markup \override #'(inter-box-padding . 0.8) \double-box A \markup \override #'(box-padding . 1.0) \double-box A
| [ < ] | [ > ] | [ << ] | [ Subir ] | [ >> ] | [Arriba] | [Índice general] | [Índice] | [ ? ] |
@translationof Adapting builtin commands
Una buena manera de comenzar a escribir una instrucción de marcado nueva, es seguir el ejemplo de otra instrucción ya incorporada. Casi todas las instrucciones de marcado que están incorporadas en LilyPond se pueden encontrar en el archivo ‘scm/define-markup-commands.scm’.
Por ejemplo, querríamos adaptar la instrucción \draw-line,
para que trace una línea doble. La instrucción \draw-line
está definida como sigue (se han suprimido los comentarios de
documentación):
(define-markup-command (draw-line layout props dest)
(number-pair?)
#:category graphic
#:properties ((thickness 1))
"…documentación…"
(let ((th (* (ly:output-def-lookup layout 'line-thickness)
thickness))
(x (car dest))
(y (cdr dest)))
(make-line-stencil th 0 0 x y)))
|
Para definir una instrucción nueva basada en otra existente,
copie la definición y cámbiele el nombre. La palabra clave
#:category se puede eliminar sin miedo, pues sólo se
utiliza para generar documentación de LilyPond, y no tiene
ninguna utilidad para las instrucciones de marcado definidas por
el usuario.
(define-markup-command (draw-double-line layout props dest)
(number-pair?)
#:properties ((thickness 1))
"…documentación…"
(let ((th (* (ly:output-def-lookup layout 'line-thickness)
thickness))
(x (car dest))
(y (cdr dest)))
(make-line-stencil th 0 0 x y)))
|
A continuación se añade una propiedad para establecer la
separación entre las dos líneas, llamada line-gap, con un
valor predeterminado de p.ej. 0.6:
(define-markup-command (draw-double-line layout props dest)
(number-pair?)
#:properties ((thickness 1)
(line-gap 0.6))
"…documentación…"
…
|
Finalmente, se añade el código para trazar las dos líneas. Se
usan dos llamadas a make-line-stencil para trazar las
líneas, y los sellos resultantes se combinan usando
ly:stencil-add:
#(define-markup-command (my-draw-line layout props dest) (number-pair?) #:properties ((thickness 1) (line-gap 0.6)) "..documentation.." (let* ((th (* (ly:output-def-lookup layout 'line-thickness) thickness)) (dx (car dest)) (dy (cdr dest)) (w (/ line-gap 2.0)) (x (cond ((= dx 0) w) ((= dy 0) 0) (else (/ w (sqrt (+ 1 (* (/ dx dy) (/ dx dy)))))))) (y (* (if (< (* dx dy) 0) 1 -1) (cond ((= dy 0) w) ((= dx 0) 0) (else (/ w (sqrt (+ 1 (* (/ dy dx) (/ dy dx)))))))))) (ly:stencil-add (make-line-stencil th x y (+ dx x) (+ dy y)) (make-line-stencil th (- x) (- y) (- dx x) (- dy y))))) \markup \my-draw-line #'(4 . 3) \markup \override #'(line-gap . 1.2) \my-draw-line #'(4 . 3)
| [ < ] | [ > ] | [ << ] | [ Subir ] | [ >> ] | [Arriba] | [Índice general] | [Índice] | [ ? ] |
@translationof New markup list command definition
Las instrucciones de listas de marcado se definen con el macro de
Scheme define-markup-list-command, que es similar al macro
define-markup-command descrito en Definición de una instrucción de marcado nueva, excepto que donde éste devuelve un
sello único, aquél devuelve una lista de sellos.
En el siguiente ejemplo se define una instrucción de lista de
marcado \paragraph, que devuelve una lista de líneas
justificadas, estando la primera de ellas sangrada. La anchura
del sangrado se toma del argumento props.
#(define-markup-list-command (paragraph layout props args) (markup-list?)
#:properties ((par-indent 2))
(interpret-markup-list layout props
#{\markuplist \justified-lines { \hspace #par-indent #args } #}))
|
La versión que usa solamente Scheme es más compleja:
#(define-markup-list-command (paragraph layout props args) (markup-list?)
#:properties ((par-indent 2))
(interpret-markup-list layout props
(make-justified-lines-markup-list (cons (make-hspace-markup par-indent)
args))))
|
Aparte de los argumentos usuales layout y props, la
instrucción de lista de marcados paragraph toma un
argumento de lista de marcados, llamado args. El
predicado para listas de marcados es markup-list?.
En primer lugar, la función toma el ancho del sangrado, una
propiedad llamada aquí par-indent, de la lista de
propiedades props. Si no se encuentra la propiedad, el
valor predeterminado es 2. Después, se hace una lista de
líneas justificadas usando la instrucción incorporada de lista de
marcados \justified-lines, que está relacionada con la
función make-justified-lines-markup-list. Se añade un
espacio horizontal al principio usando \hspace (o la
función make-hspace-markup). Finalmente, la lista de
marcados se interpreta usando la función
interpret-markup-list.
Esta nueva instrucción de lista de marcados se puede usar como sigue:
\markuplist {
\paragraph {
El arte de la tipografía musical se llama \italic {grabado (en plancha).}
El término deriva del proceso tradicional de impresión de música.
hace sólo algunas décadas, las partituras se hacían cortando y estampando
la música en una plancha de zinc o lata en una imagen invertida.
}
\override-lines #'(par-indent . 4) \paragraph {
La plancha se tenía que entintar, y las depresiones causadas por los cortes
y estampados retienen la tinta. Se formaba una imagen presionando el papel
contra la plancha. El estampado y cortado se hacía completamente
a mano.
}
}
|
| [ < ] | [ > ] | [ << ] | [ Subir ] | [ >> ] |
Este documento ha sido generado por gub el el 13 julio 2020 utilizando texi2html 1.82.
Otros idiomas: English, deutsch, français.
Acerca de la selección automática del idioma.