3

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

juFo
  • 17,849
  • 10
  • 105
  • 142
  • Use proper PostScript reference manual http://www.adobe.com/products/postscript/pdfs/PLRM.pdf not a third party tutorial – piokuc Apr 26 '13 at 09:43
  • "The top-most graphics state is always the current graphics state." confusing information http://stackoverflow.com/a/11139870/187650 – juFo Apr 26 '13 at 10:09
  • If it's useful to you, I've got a mostly-complete Level-1 interpreter in C available [here](http://code.google.com/p/xpost/downloads/detail?name=xpost2g.zip) (It's missing a few of the really hard operators like `definefont`.) – luser droog Apr 27 '13 at 13:22

1 Answers1

0

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

luser droog
  • 18,988
  • 3
  • 53
  • 105
  • 1
    is this correct: if you start your interpreter you have a Graphics State Stack which has one default Graphics State. The Current Graphics State does not look directly at the stack with .Peek() but has a copy of the topmost item at the Graphics State Stack. So the interpreter has a default GSStack with one GS and a copy of that GS in the Current Graphics State. ? – juFo Apr 28 '13 at 07:22
  • That seems fine to make a copy for the *active* gstate. But using .Peek() should also work. For my interpreter, I used Cairo for the graphics which has its own internal gstate stack. So it was difficult to make save/restore work with gsave/grestore. – luser droog Apr 28 '13 at 07:33
  • but Peek() looks and works with the last item you placed on the stack. that doesn't sound good? :s – juFo Apr 28 '13 at 07:36
  • The current graphics state is the top state on the stack. Using Peek() seems like the simplest way to do it. But there might be a performance gain by making a copy and accessing it more directly. I recommend you use Peek() to begin with; but if profiling tells you that Peek() is a performance bottleneck, then you may want to consider having a CurrentGState object and update it in `gsave` and `grestore`. – luser droog Apr 28 '13 at 20:56