Ir al contenido

PGD | Técnicas de diseño PostScript

Como ejemplo de aplicación[1], diseñaremos un programa PostScript para crear una tira de control en escala de gris, formada por cuadrados llenos con porcentajes de negro desde el 100% hasta el 0% en pasos de 10%, como la escala mostrada abajo:

Podemos considerar que cada parche consiste básicamente de la misma operación, es decir, dibujar cuadrados de iguales dimensiones; sólo cambian en cada caso sus coordenadas y el color de relleno. Supongamos parches de 15mm de lado, dispuestos horizontalmente a partir de la esquina inferior izquierda de la página. Haremos uso del operador rectfill, cuya definición es:

x y ancho alto rectfill —

y cuyo efecto es marcar un rectángulo lleno del ancho y alto especificados, con su vértice inferior izquierdo en las coordenadas x, y, empleando el color actual, definido previamente mediante setrgbcolor, setgray o setcmykcolor.

Una primera estrategia es escribir directamente las instrucciones para cada parche. El resultado podría ser el siguiente:

%!
/mm { 25.4 div 72 mul } def
/parche { setgray 15 mm 15 mm rectfill } def
0 mm 0 mm 0 parche
15 mm 0 mm 0.1 parche
30 mm 0 mm 0.2 parche
45 mm 0 mm 0.3 parche
60 mm 0 mm 0.4 parche
75 mm 0 mm 0.5 parche
90 mm 0 mm 0.6 parche
105 mm 0 mm 0.7 parche
120 mm 0 mm 0.8 parche
135 mm 0 mm 0.9 parche
150 mm 0 mm 1 parche
showpage

Código PostScript para tira de control (primer intento).

Esto hará correctamente la tarea, pero hemos repetido 11 veces parámetros que no cambian, como el ancho y el alto de cada parche. Sería mejor enseñar a PostScript cómo dibujar un parche cualquiera, para simplificar el código. Para ello, observemos por ejemplo las instrucciones que generan el parche del 40%:

0.6 setgray
75 mm 0 mm 15 mm 15 mm rectfill

El mismo resultado podría obtenerse así, recordando el funcionamiento de la pila:

75 mm 0 mm 0.6 setgray 15 mm 15 mm rectfill

La ventaja de este reordenamiento es que nos deja una instrucción que comienza con tres parámetros (x, y, nivel de gris), que son los valores que cambian en cada parche, seguido de operadores y operandos que no cambian. Definiendo un procedimiento “parche” como sigue:

/parche {setgray 15 mm 15 mm rectfill} def

el parche anterior se escribe

75 mm 0 mm 0.5 parche

A partir de ahora, podemos contar con un operador PostScript parche que espera tres parámetros en la pila (x, y, nivel de gris) y dibuja el parche correspondiente. Así llegamos a una segunda versión, más compacta:

%!
/mm { 25.4 div 72 mul } def
/parche { setgray 15 mm 15 mm rectfill } def
0 mm 0 mm 0 parche
15 mm 0 mm 0.1 parche
30 mm 0 mm 0.2 parche
45 mm 0 mm 0.3 parche
60 mm 0 mm 0.4 parche
75 mm 0 mm 0.5 parche
90 mm 0 mm 0.6 parche
105 mm 0 mm 0.7 parche
120 mm 0 mm 0.8 parche
135 mm 0 mm 0.9 parche
150 mm 0 mm 1 parche
showpage

Código PostScript para tira de control (segundo intento).

Este segundo programa es suficiente en este caso porque se trata de pocos parches, pero si hubiera que crear cien sería engorroso; crear mil sería ya prohibitivo.

Existe la posibilidad de condensar aún más este código, e incluso adaptarlo para un número arbitrario de parches. En efecto, todavía repetimos instrucciones para crear cada parche; sin embargo todos ellos se pueden producir según una misma regla: el parche número n (con n entre 0 y 10) requiere la siguiente instrucción:

(n x 15 mm) 0 mm (n/10) parche

Un operador especial, for, nos permite repetir un mismo procedimiento con un valor distinto cada vez. La sintaxis de for es:

inicio incremento límite procedimiento for 

Su significado es el siguiente: colocar en la pila un número al principio igual a inicio, ejecutar procedimiento, agregar incrementoal número, ejecutar otra vez procedimiento, y así sucesivamente hasta que se supere límite.

Imaginemos ahora que escribimos un nuevo procedimiento, parchenumero, que haga lo mismo que parche pero que requiera en la pila sólo el número de parche y no las coordenadas y el nivel de gris: por ejemplo, para crear el parche de 50%, en lugar de escribir

75 mm 0 mm 0.5 parche

escribiríamos

5 parchenumero

Si suponemos este procedimiento ya escrito, podríamos crear los 11 parches con esta sencilla instrucción:

0 1 10 { parchenumero } for

Resta escribir el procedimiento parchenumero para completar el programa. Dejamos al lector la tarea de comprobar que el siguiente procedimiento realiza esa función:

/parchenumero { dup 15 mm mul 0 mm 3 2 roll 10 div parche } def

Hemos hecho uso de dos nuevos operadores PostScript. Uno de ellos, dup, tiene por objeto duplicar el último elemento de la pila, mientras que el otro, roll, tiene como función rotar elementos de la pila. Más precisamente, la instrucción

n i roll

desplaza cíclicamente los últimos n elementos de la pila i lugares hacia adelante. El programa PostScript para nuestra tira de control queda así finalmente:

%!
/mm { 25.4 div 72 mul } def
/parche { setgray 15 mm 15 mm rectfill } def
/parchenumero {
    dup 15 mm mul 0 mm 3 2 roll 10 div parche
} def
0 1 10 { parchenumero } for
showpage

Código PostScript para tira de control (tercer intento).


1 Debe quedar claro que, en la vida real, son los drivers los que crearán código PostScript de manera automática. La idea de escribir manualmente código PostScript es, básicamente, conocer la filosofía detrás del lenguaje, sus alcances y limitaciones.