Introducción
Éste es el primero de una serie de artículos sobre PostScript.
La idea principal no es enseñar todos y cada uno de los detalles
de este software, sino dar suficiente material para las personas que encuentran
en el PostScript un lenguaje de programación para la preparación
de documentos interesante y divertido. A pesar de que no pretendemos escribir
un documento técnico ni un libro de texto ni una biblia sobre este
tema, intentaremos presentar la información necesaria y suficiente sobre
PostScript.
Las ideas principales sobre las que está hecho el PostScript fueron
creadas hace veinte años por John Gaffney en la Evans & Sutherland
Computer Corporation. Al principio se llamaba "Design System" pero
más tarde fue desarrollado bajo el nombre de PostScript por Adobe
Systems Incorporated como una herramienta independiente de la plataforma y del
dispositivo para la descripción de páginas. Adobe Systems
Incorporated fue formado por Chuck Geschke and John Warnock en 1982.
C. Geschke y J. Warnock emprendieron un nuevo diseño e
implementación del lenguaje, al que Doug Brotz, Billi Paxton,
y Ed Taft hicieron grandes contribuciones.
Actualmente es una de las herramientas de preparación de documentos
más importantes, aunque no es utilizada directamente
por la mayoría de usuarios. Sus capacidades están
completamente a alto nivel, sin embargo muchos usuarios que no quieren
entrar en los detalles de este potente lenguaje prefieren usar las otras
herramientas de usuario final, que están basadas principalmente
en la filosofía "What You See Is What You Get". Para
decir la verdad, muchas herramientas WYSIWYG usan formatos de fichero
PostScript para mantener la documentación de los productos o para
usarlos como interface con otros trabajos como la impresión.
Por ello, podemos decir que aún sobrevive como un viejo amigo que
sirve como una potente asistencia para muchos trabajos del ordenador relativos
a dibujar, colorear, procesar imágenes, separación de colores,
simulación y animación incluso si no se nos muestra
explícitamente durante el proceso. Por otro lado, si quieres aprender su
estructura para programarlo, encontrarás que no es muy
difícil.
Los comandos de PostScript se ejecutan a través de algún
intérprete. Entre los que existen, un software muy conocido está
disponible gratuitamente en el dominio público de Internet. Se llama
"ghostscript" por Aladdin Enterprise. Existe también un
útil interfase gráfico, "ghostview", distribuido por
la misma organización. El proyecto GNU tiene también sus
propias versiones de ghostscript. Estas están disponibles en todas
las plataformas Linux y todas las distribuciones principales las contienen
en su instalación estándar. Aquí usaremos ghostscript
y ciertas de sus estructuras y propiedades específicas, aunque los
programas de ejemplo se pueden ejecutar a través de otros
intérpretes. Asumimos que tenemos activado el servidor de X Window
y abierta una ventana xterm. Si queremos usar ghostscript entonces cada
comando y grupo de comandos se dará en el prompt de comandos que aparece
después de lanzar el comando
Initializing... done. Ghostscript 2.6.2 (4/19/95) Copyright (C)
1990-1995 Aladdin Enterprises, Menlo Park, CA. All rights reserved. Ghostscript
comes with NO WARRANTY: see the file COPYING for details.
GS>
Una ventana blanca propia se abrirá al mismo tiempo que aparece
este prompt.
Si queremos cerrar la sesión ghostscript, lo único que tenemos
que hacer es ejecutar el comando quit en el prompt GS>.
También podemos salir con EOF (Ctrl-D).
Ghostscipt también puede ejecutar los comandos obteniéndolos
de un fichero. En este caso abrimos un fichero llamado, por ejemplo,
sample.ps . Todos los comandos que queremos que ghostscript ejecute
están escritos en este fichero. Entonces podemos llamar al contenido
de este fichero un programa PostScript. El contenido completo de este
programa o sus comandos individuales será consecutivamente ejecutado
por ghostscript si ejecutamos el siguiente comando en el prompt de la shell
de la ventana de xterm de linux
gs sample.ps
y el display (si el programa pide la creación de un display, claro.
De hecho, PostScript se puede usar para otras cosas, como cálculos
matemáticos, operaciones de pilas, etc. Las mencionaremos en futuros
artículos de esta serie) aparecerá en la ventana de
ghostscript. Si el programa produce más de una página entonces
la ventana de ghostscript muestra la primera y el prompt
showpage aparece en la línea de comandos de ghostscript
solicitando enter key pressing para ver la siguiente
página.
PostScript usa Reverse Polish Notation (RPN - como las calculadoras de
bolsillo de HP). En otras palabras, los parámetros de un comando se
dan antes que el comando. Los comandos se separan con espacios en blanco.
Usa operaciones de pila para procesar datos y ejecutar comandos. Hay cuatro
pilas disponibles en PostScript: la pila de operandos, la de diccionario, la
de ejecución y la de estado gráfico. La pila de operandos contiene
objetos PostScript arbitrarios que son los operandos y resultados de los
operadores PostScript que se están ejecutando. Podemos dar algunos
ejemplos de operaciones aritméticas. Por ejemplo,
20 30 add 10 sub
produce 40, ya que 20 30 add crea 50 y sub
produce 40 al usar 50 junto con 10. mul (multiplicación)
y div (división) funcionan de la misma manera. El nombre '='
esta asociado con un procedimiento que saca un objeto de la pila de operadores
y escribe una representación textual de su valor al fichero
estándar de salida, seguido de una nueva línea. == tiene un
efecto similar, pero escribe una representación sintáctica de su
operando el fichero estándar de salida. El comando pop
extrae el elemento superior de la pila de operandos y lo elimina. Hablaremos
de las pilas más detalladamente en posteriores artículos de esta
serie.
¿Cómo se usa PostScript para dibujar figuras?
Podemos empezar dibujando figuras con PostScript considerando la
estructura geométrica de la página que será diseñada.
Las posiciones de los puntos de una página se denotan mediante
pixels, que son 1/72 de pulgada en el lenguaje PostScript. La esquina
inferior derecha de la página es el punto con coordenadas (0,0) y el
tamaño horizontal y vertical de la página son de 612 y 792
respectivamente. Estos tamaños son para la hoja tipo letter. Hay otras
posibilidades de tamaños para otros tipos de papel, como
note con 540 y 720 o
legal con 612 y 1008 o
a4 con 595 y 842 .
Estos son comandos normales de gs. El comando 'a4' modificará el
tamaño de tu hoja de dibujo al tamaño adecuado.
La definición del tamaño del papel se puede encontrar en
el fichero de inicialización cuyo nombre es gs_statd.ps. Se puede
encontrar en /usr/lib/ghostscript para Slackware. Puedes definir cualquier
tamaño de papel no estándar haciendo los añadidos y
modificaciones convenientes en este fichero como mencionaremos más
adelante en esta serie de artículos. Aquí asumimos que usamos
el tamaño de papel por defecto letter en esta
presentación.
El segundo paso después de poner el papel al tamaño deseado
al dibujar una figura es situar el cursor el principio del dibujo. Esto se
puede conseguir con el comando
x y moveto
donde x e y denotan respectivamente las coordenadas
horizontal y vertical del punto donde se situará el cursor. x
e y son números puros y considerados en unidades de
píxel. Como puedes ver, la estructura funcional de PostScript es
ligeramente diferente de otros lenguajes de programación como C,
Fortran. moveto es el comando que realiza la acción, en
otras palabras, es el que mueve el cursor al sitio cuyas coordenadas vienen
dadas por x e y. Como PostScript usa una pila, primero se meten los
parámetros consecutivamente en la pila. Entonces se da el comando.
Cuando entra en la pila, acepta los dos objetos anteriores como sus
parámetros. La sintaxis es diferente para el usuario
que está familiarizado con otros lenguajes como C, Fortran. Por eso
hemos insistido en este tema aquí. Como conclusión diremos
que todo comando que necesite parámetros se dará después
de sus parámetros.
Ahora estamos preparados para empezar a dibujar la figura. Empecemos con una
figura sencilla, un segmento recto. Para dibujarlo, lo único que tenemos
que hacer es ejecutar el comando
xx yy lineto
donde xx e yy denotan la situación del punto final
del segmento. Su punto inicial es la posición actual del cursor,
x e y . Así pues, este comando construye un segmento
recto entre x y y xx yy . El dibujo necesita los comandos
de definición de camino newpath y stroke.
Escribamos un programa PostScript para dibujar un rectángulo. Se puede
hacer usando la información anterior. El programa que suponemos que
se grabará en el fichero sample1.ps puede ser así
newpath
100 100 moveto
300 100 lineto
300 250 lineto
100 250 lineto
100 100 lineto
stroke
A pesar de que hemos dado cada comando en una línea separada,
esto no es realmente necesario. Los podríamos dar todos en la
misma línea insertando un espacio en blanco entre comandos
consecutivos, como ya dijimos antes.
PostScript permite la introducción de comentarios, como otros
lenguajes de programación. Todo lo que sigue a un signo de porcentaje
hasta el final de la línea se interpreta como un comentario.
newpath
% Inicialización del cursor
100 100 moveto
% Dibujo del rectángulo
300 100 lineto
300 250 lineto
100 250 lineto
100 100 lineto
stroke
Si ejecutamos el comando gs sample1.ps en el prompt de una
ventana de xterm, entonces aparece la conocida ventana de ghostscript
conteniendo el dibujo del rectángulo. No necesitamos invocar el
intérprete cada vez. De hecho, el comando (sample1.ps) run
hace lo mismo desde el prompt GS>.
El comando stroke le dice al intérprete que dibuje la
figura. En el programa anterior la ventana de ghostscript muestra el
rectángulo con lados de 200 y 150 puntos en las direcciones horizontal
y vertical.
Las líneas rectas no necesitan ser verticales o horizontales. Se
pueden construir en cualquier dirección.
Como podrás ver cuando mostremos el resultado mediante ghostscript,
este programa crea un triángulo. Puedes crear cualquier clase de figura
que esté compuesta de segmentos usando los comandos moveto y
lineto.
Hay dos comandos más que se pueden usar en las construcciones
anteriores. Son los comandos rmoveto y rlineto . Necesitan
dos parámetros y se usan así
x y rmoveto
x y rlineto
donde x e y son las distancias horizontal y vertical
entre el punto inicial y final de cada acción. 'r' en rmove y rlineto
significa 'relativo'. En otras palabras, el primer comando mueve el cursor
x unidades horizontalmente a la derecha e y unidades
hacia arriba desde su posición actual. El segundo comando actúa
de manera similar, pero dibuja una línea y mueve el cursor al punto final
en lugar de solo mover el cursor. Estos son comandos de referencia y los
parámetros se dan tomando la posición inicial como el punto
de referencia.
Todos los ejemplos anteriores usan una anchura de línea por
defecto para dibujar. Este valor es de 1 píxel. Sin embargo, el usuario
puede definir el ancho de línea del dibujo en cualquier punto del
programa. Esto se puede hacer con el comando
x setlinewidth
donde x denota el anchura de la línea en píxels. El efecto de
este comando continúa hasta que se modifique de nuevo la anchura de la
línea en el programa. No hay limitación para el número
de anchos de línea en un programa.
Naturalmente, dibujar en PostScript no está limitado a líneas
rectas. Se pueden dibujar también arcos circulares. Para ello podemos
usar el siguiente comando
x y r a b arc
donde x, y, r, a y b son las coordenadas horizontal y
vertical del centro del arco circular, el radio del arco y el ángulo
entre la parte positiva del eje horizontal y los rayos centrales que pasan
a través del punto inicial y final del arco. Los ángulos se miden
en sentido contrario a las agujas del reloj. Si el punto inicial del arco
no es la posición actual del cursor, entonces se dibuja también
una línea recta entre la posición actual del cursor y el inicio
del arco. Para entender todo esto, puedes echarle un vistazo el siguiente
programa PostScript.
3 setlinewidth
200 200 moveto
100 200 100 0 75 arc
stroke
300 300 moveto
400 500 200 20 50 arc
stroke
Así pues, debemos tener cuidado y poner el cursor al principio
del arco si no queremos la línea extra mencionada más arriba.
Sin embargo, hay otra manera de solucionar el problema. De hecho, al punto
actual se le puede dar un valor vacío. En otras palabras, al
principio del camino no hay ningún valor para los parámetros.
No hay ninguna asignación para la posición del cursor. Una vez
se inicia el dibujo, el punto final del camino se convierte en el punto actual.
Si ejecutamos el comando newpath entonces PostScript borra la
asignación para el punto del cursor y actúa como si el dibujo
comenzara desde el principio. Así pues, el programa anterior se puede
modificar sustituyendo la quinta línea con una línea que contenga
solo el comando newpath. Si lo hacemos y lo ejecutamos veremos que
obtenemos el mismo dibujo, excepto la línea recta extra.
Un camino se inicia ejecutando el operador newpath. Esto inicializa
el camino actual al camino vacía. El camino se construye entonces
ejecutando comandos que añadan segmentos al camino actual.
El comando arc se puede usar para dibujar un círculo
completo. Es suficiente dar como ángulo inicial y final 0 y 360
respectivamente. Si se hace bajo un newpath se obtiene un círculo completo.
El comando arc también se puede usar para producir elipses.
Usaremos para ello las propiedades de escalado de PostScript. El usuario puede
reescalar las unidades horizontales y verticales de manera separada mediante
el siguiente comando
x y scale
donde x e y denotan respectivamente los factores de escalado
horizontal y vertical. Esto significa que cuando estos factores son igual a 1
no afecta en nada al dibujo. El efecto de escalado se mantiene hasta que se
ejecuta el siguiente comando de escalado. El siguiente comando de escalado que
se ejecuta no anula el efecto del anterior, sino que combina su propio efecto
con el anterior. Supongamos que los parámetros del comando de escalado
anterior fueron x1, y1 y los parámetros del siguiente comando
son x2, y2 , entonces el efecto combinado de ambos tiene los factores
de escalado x1*x2, y1*y2 . Este efecto se debe tener presente para
evitar efectos indeseados en el display, como que algunos caminos se salgan de
la superficie del papel. PostScript asume la no existencia de escalado por
defecto. El siguiente programa PostScript, que suponemos que está grabado
en el fichero sample4.ps , es un ejemplo para explicar el escalado.
3 setlinewidth
200 200 100 0 360 arc
stroke
newpath
2 1 scale
200 300 50 0 360 arc
stroke
newpath
1 4 scale
100 150 40 0 360 arc
stroke
Como se puede ver, la escala afecta a todos los tamaños, incluyendo
el ancho de línea. El ancho de línea de las elipses y el
círculo creado por el programa anterior son diferentes debido a esta
razón.
PostScript tiene dos comandos más para dibujar arcos. Uno de ellos,
arcn , es casi lo mismo que arc excepto en la dirección
de dibujo. arcn dibuja el arco en el sentido de las agujas del reloj.
El tercer comando de dibujo de arcos dibuja un arco circular que es tangente
a dos líneas dadas en sus puntos finales. Se puede ejecutar así
x1 y1 x2 y2 r arcto xt1 yt1 xt2 yt2
donde xt1, yt1, xt2, yt2 denotan los coordenadas horizontales y
verticales del arco, mientras que los puntos finales de las líneas
tangentes tienen los valores x0, y0, x1, y1 y x1, y1, x2, y2
respectivamente y r es el radio del arco. Si el camino no es nuevo o
el punto actual no coincide con el inicio del arco entonces se añade al
camino una línea que une el punto actual con el inicio del arco. Al
final del dibujo el punto actual es xt2, yt2 .
PostScript tiene también un comando basado en el algoritmo de Bezier
que se puede usar de manera efectiva en la interpolación o
extrapolación de unos datos dados para dibujar. Esto comando se llama
curveto y se puede usar para formar el dibujo basado en la
interpolación o extrapolación de un conjunto de datos dado. El
comando se usa así
x1 y1 x2 y2 x3 y3 curveto
donde la curva empieza en el punto actual, cuyas coordenadas son
x0, y0 . Es tangente a la línea entre los puntos x0, y0
y x1, y1 en el punto inicial. La curva acaba en el punto x3, y3
y es tangente a la línea entre x2, y2 y x3, y3 . Por
defecto estos cuatro puntos se supone que son diferentes y determinan la
forma de la figura.
Herramientas de escritura en PostScript
PostScript tiene varias fuentes que se usan como fuentes estándares
para autoedición. Tiene también herramientas de creación
de fuentes a las que se puede acceder definiendo pilas de diccionario donde
las fuentes están disponibles. El siguiente programa en PostScript puede
ser un ejemplo.
/Times-Roman findfont
15 scalefont
setfont
100 500 moveto
(I love PostScript!) show
/Times-Italic findfont
20 scalefont
setfont
100 450 moveto
(I love PostScript!) show
/Times-Bold findfont
25 scalefont
setfont
100 400 moveto
(I love PostScript!) show
/Helvetica findfont
30 scalefont
setfont
100 350 moveto
(I love PostScript!) show
/Courier findfont
35 scalefont
setfont
100 300 moveto
(I love PostScript!) show
/Helvetica-Bold findfont
40 scalefont
setfont
100 250 moveto
(I love PostScript!) show
showpage
Como se puede deducir del programa, el comando findfont se usa
para obtener un acceso a la estructura de la fuente deseada. El nombre de la
fuente comienza por / y se le da al comando como un parámetro (donde /
le dice al intérprete que meta este valor en la pila tal como está.
Cuando entremos más tarde en detalle en las operaciones de pila este
punto quedará más claro). Después de la selección
del comando, la escala se define mediante el comando scalefont .
El factor de escala se da como un número precediendo al comando.
Después del escalado de la fuente, el comando setfont deja
la fuente disponible para usarla en el programa. Después de situar
el cursor con el comando moveto con los parámetros adecuados,
el texto entre paréntesis se pasa como parámetro al comando
show . El comando showpage finaliza el display del material
escrito. El programa anterior utiliza diferentes tipos y tamaños de
fuentes con el mismo texto en diferentes posiciones. El número de fuentes
disponibles para PostScript se puede encontrar buscando las situaciones de
las fuentes en la estructura de directorios del sistema linux que utilices.
El texto se puede ajustar con líneas, curvas y otras herramientas.
Así pues cualquier tipo de escritura, en principio, es posible.
Es solo una cuestión de diseño.
Cómo pintamos y usamos los colores en PostScript
El lenguaje PostScript está equipado con muchas facilidades para
pintar figuras o crear dibujos con colores. Empezaremos primero mencionando
los comandos de color. PostScript usa el negro como color por defecto, a no
ser que se ejecute un comando de especificación de color. Por ello la
salida de todos los programas anteriores eran dibujos en blanco y negro.
Para usar colores en la salida de PostScript podemos usar tres comandos de
coloreado diferentes. El primero se basa en el formato de color rgb .
En este formato, cada color se supone compuesto de tres colores principales:
rojo, verde y azul. A las componentes del color se les pueden dar
parámetros de intensidad individuales, que pueden tomar valores entre 0
y 256. Los parámetros de intensidad pueden aceptar valores decimales
de hasta tres dígitos de precisión, como 111.223. El comando
esperado por PostScript debe ser dado de la siguiente manera.
x y z setrgbcolor
donde x,y,z son los parámetros de intensidad para las
componentes rojo, verde y azul y setrgbcolor es el comando.
En esta convención, 1 0 0 setrgbcolor crea el color rojo,
mientras que 0 1 0 setrgbcolorcrea el verde. El negro corresponde
al caso donde todos los parámetros de intensidad valen 1. Los comandos
de color continúan afectando a todos los dibujos hasta que se ejecute
el siguiente comando de color. Cuando esto pasa, el efecto del comando anterior
se anula totalmente, y el nuevo valor vale para todo. El número de veces
que se puede utilizar es ilimitado. Usando adecuadamente los valores del color
puedes crear tus dibujos como quieras. Es una cuestión de arte y
depende de ti.
La segunda utilidad de control del color se basa en un formato de cuatro
componentes del color. Se llama el formato de color cmyk . Las cuatro
componentes básicas del color son cyan, magenta, amarillo y
negro respectivamente. Cada componente de color contribuye al
color final según una intensidad que puede variar entre 0 y 1. El
comando de PostScript correspondiente es
w x y z setcmykcolor
donde w, x, y, z son los parámetros de intensidad para las
componentes de color cyan, magenta, amarillo y negro, respectivamente.
Los valores fraccionarios decimales se pueden usar también para los
valores de intensidad. Este comando continúa su efecto sobre todo hasta
que el siguiente comando se ejecuta. Cuando esto ocurre, los nuevos valores
dominan sobre los anteriores. No hay limitación sobre el número
de veces que se puede usar en un programa.
El tercer comando es el siguiente
x y z sethsbcolor
donde x, y, z son los valores de los parámetros de intensidad
de tres diferentes propiedades del color. El primero corresponde a
color (hue), que determina la localización del color en el
espectro de la luz. El segundo, saturación y el tercero
brillo corresponden a la saturación y brillo del color.
Este formato se prefiere cuando las propiedades a controlar son la
localización del color en el espectro mediante un bucle, o el brillo y/o
la saturación. El lector que no esté familiarizado con hsbcolor
puede comprobar el uso de xfig bajo linux.
El comando más importante de PostScript para pintar es fill
y closepath . El siguiente programa de ejemplo, que se supone grabado
en el fichero sample6.ps , clarifica importantes aspectos al pintar
y colorear con PostScript.
1 1 0 0 setcmykcolor
100 100 moveto
300 100 lineto
300 250 lineto
100 250 lineto
100 100 lineto
stroke
1 0.5 0.8 0 setcmykcolor
5 setlinewidth
200 200 moveto
400 300 lineto
300 300 lineto
closepath fill
stroke
1 0 0 setrgbcolor
3 setlinewidth
200 200 moveto
100 200 100 0 75 arc
stroke
newpath
400 500 200 20 50 arc
stroke
0 0 1 0.2 setcmykcolor
3 setlinewidth
200 200 100 0 360 arc
stroke
1 0 0 setrgbcolor
newpath
2 1 scale
200 300 50 0 360 arc
gsave fill grestore stroke
stroke
0 1 0 setrgbcolor
newpath
1 4 scale
100 150 40 0 360 arc
gsave fill grestore stroke
donde el comando closepath cierra un camino abierto uniendo dos
puntos finales con una línea recta, mientras que fill
sirve para llenar el interior del camino cerrado con el color actual.
PostScript puede también crear tonos de gris. Esto se puede hacer
con el siguiente comando
x setgray
donde x es la intensidad del color gris y su valor puede variar
desde 0, que corresponde a negro, hasta 1, que corresponde a blanco.
El siguiente programa grabado bajo el nombre de sample7.ps
está hecho de manera que se explique a sí mismo.
0.2 setgray
10 setlinewidth
100 700 moveto
200 0 rlineto
stroke
newpath
0.3 setgray
100 600 moveto
200 0 rlineto
stroke
newpath
0.4 setgray
100 500 moveto
200 0 rlineto
stroke
newpath
0.5 setgray
100 400 moveto
200 0 rlineto
stroke
newpath
0.6 setgray
100 300 moveto
200 0 rlineto
stroke
newpath
0.7 setgray
100 200 moveto
200 0 rlineto
stroke
newpath
0.8 setgray
100 100 moveto
200 0 rlineto
stroke
Antes de finalizar esta presentación, podemos recomendar escribir
programas más complicados para los usuarios que encuentran en PostScript
una interesante herramienta. En los siguientes artículos de esta serie
daremos más detalles sobre el lenguaje PostScript. Todas las preguntas
y recomendaciones serán bienvenidas.
El autor agradece a Oliver Thilmann por sus útiles comentarios
sobre la organización y presentación de este artículo.
|