Preparing the white page
The graphics of PostScript are a simple painting model. There is a white page at the beginning, the interpreter builds a path of points. The points are connected either by straight lines or by curves. Once the path is finished, it can be either painted as line (stroke) or it can be painted as surface, if the path is closed, the path being closed when the last point is the same as the starting point.
You can paint in any color. PostScript 1 had only grayscale values between white and black and we start with that. Later, PostScript added the RGB and CMYK color space, but never supported transparency. We will see later wether it makes sense to support transparency, too. You cannot remove anything, either, there is no eraser. However, you can paint in white.
The white page is a rectangle with coordinates. We will use a paper that is 590 pixels wide and 330 pixel height, because this fits well into this webpage. PostScript uses the coordinates like you learned it in school. Bottom left is 0 0.
To enable our PostScript interpreter to write on a paper, we must give it an output. We will use the Canvas element of HTML. The Canvas has an ImageData interface we can write to. The ImageData has the data property which is a Uint8ClampedArray, which is a long word for an array of Bytes. You can manipulate the array and the changes are reflected on the canvas.
The Uint8ClampedArray has a linear structure. All pixels are in a single dimension, we will have to deal with width and height ourselves. Each pixel is 4 bytes and represent red, green, blue, and alpha, therefore named RGBA. Each byte can have a value from 0 to 255. If you ever have done graphics, you will immediately understand that 0 0 0 is black, 255 0 0 red, 0 255 0 green, 0 0 255 blue and 255 255 255 white. What is the convention about the alpha channel? 0 is transparent and 255 is opaque. By default the ImageData is filled with all 0, so it is black and transparent. Sounds funny, black and transparent.
We make minimal changements on the rpn function. The context now includes also the data, width and height property. We now check for each element of context, if it exists and create default values, if it does not exist.
This done, we add a canvas to our postScriptEditor. For our webpage, we start with fixed width 590 and height 330.
The canvas is added as the new node8. We create an data Uint8ClampedArray for the pixel values of width * height * 4 length and set them all to 255 to have opaque white. The data array is added to the context of rpn. After running the interpreter, the data is recovered from the context, converted to a ImageData object which is put into the canvas.
This gives us the white canvas.
Lets just create som operators to draw black pixels and black horizontal lines. These are not real postscript operators, we just test the workflow
There is a catch: For canvas, the 0 0 pixel is top left, so you must revert the vertical values.
Now we can draw pixels and horizontal lines.
You should see a horizontal lines and three dots. If you do not see the dots, consider cleaning you screen.
This is everything we need for the framework. In the following chapters we will explore all path operators that create complex paths, we will learn how to fill the paths and how to approximate paths, but at the end, it will all be about drawing pixels and horizontal lines on the canvas.
The codebase has now 962 lines ps20240712.js. We did not include the pixel and the line operators, because they do not exist. We just used them to test the canvas.