stackinterpreterpostscript

PostScript current graphics state implementation


I have a question concerning the current graphics state and the Graphics State Stack in PostScript.

In my code I now have a Stack which represents the current graphics state. When I initialise my interpreter it creates a new GraphicsState object and adds it to the 'gsstack'.

My Current Graphics State is implemented as: 'gsstack'.Peek() which always returns the topmost graphics state.

with the gsave operator I create a clone of the current graphics state and push that on the 'gsstack', so I have a new topmost graphics state on the stack (and this means I have a new Current Graphics State object).

Now with the grestore I read this from http://www.tailrecursive.org/postscript/operators.html#grestore

"Sets the current graphics state to the topmost graphics state on graphics state stack and pops that state off the stack. "

How does that grestore work, because my current graphics state is already the topmost graphics state... should I just pop it off the stack?

Or is my implementation wrong? When I initialise my interpreter should I create a new Current Graphics State object, but not add it to the 'gsstack' and only push it to the 'gsstack' when the gsave operator is called?

Thanks in advance


Solution

  • Yes, grestore simply pops the graphics stack.

    Just like the dictionary stack should always have systemdict and userdict (at least) at the bottom, there should always be at least one graphics state on the graphics stack. So grestore should throw an error if it finds only one state on the stack (just like end should throw an error if it finds only the permanent dictionaries (systemdict and userdict for Level-1, adding statusdict and globaldict for Level-2)).

    But you may want to implement the graphics stack differently from the other stacks, because it's also affected by save and restore. grestore should pop all states more recent than the last save. If the graphics stack is implemented as a linked-list of arrays or dictionaries, then restore will do its part without any extra hassle.

    from the PLRM, 3ed:

    –   grestore   –

    resets the current graphics state from the one on the top of the graphics state stack and pops the graphics state stack, restoring the graphics state in effect at the time of the matching gsave operation. This operator provides a simple way to undo complicated transformations and other graphics state modifications without having to reestablish all graphics state parameters individually.

    If the topmost graphics state on the stack was saved with save rather than gsave (that is, if there has been no gsave operation since the most recent unmatched save), grestore restores that topmost graphics state without popping it from the stack. If there is no unmatched save (which can happen only during an unencapsulated job) and the graphics state stack is empty, grestore has no effect.

    You may want to ignore save and restore at first, and just focus on gsave and grestore (and the rest of the graphics functionality). save and restore get very complicated. I've redesigned my interpreter several times to try to get them to work right.