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).