[comp.lang.postscript] Printer state between pages

rokicki@Neon.Stanford.EDU (Tomas G. Rokicki) (01/09/90)

Thanks, Brian, for your comments; I agree.

And now for something completely different.

The structuring conventions separate a document into four sections
(for the purpose of this discussion):  prolog, setup, pages, and
trailer.  A lot of programs rearrange pages to do 2-up and the like
by assuming the state between pages is the same as the state before
the prolog.  I claim this is incorrect, and indeed these programs
should look at not the original state, or the state between pages,
but the changes between the two (there is a matrix divide in PostScript,
right?) to perform there magic.

Consider the following program.

...
%%EndProlog
%%BeginSetup
2 2 scale
%%EndSetup
%%Page 1
... gsave showpage grestore
%%Page 2
... gsave showpage grestore
%%Trailer

The graphics state at the beginning is completely unknown (this file,
or a subset, might be included and scaled, rotated, etc.)  The setup
can completely alter the state, and gsave/grestore can be used to
maintain that state across page boundaries.

Thus, a program that attempts to 2-up this document cannot simply
redefine the `showpage' operator, as there could be any number of
(including zero) gsave/grestore pairs around showpage.  Rather,
the 2-up program needs to store away the initial state somewhere.
Then, after setup, it needs to divide the new state by the initial
state, and save this information away for its later use.  Each
`transformation' it wants to make must then be divided by this
new matrix we created before it is applied.

Why do I bring all this up?  With the large number of PostScript
clones, previewers, and manipulators being released, issues such
as these must be clearly stated and carefully dealt with.  Most
PostScript previewers and manipulators make completely invalid
assumptions that cause problems with correctly-written PostScript.

Comments?

-tom

amanda@mermaid.intercon.com (Amanda Walker) (01/09/90)

In article <1990Jan8.195614.27489@Neon.Stanford.EDU>, rokicki@Neon.Stanford.EDU
(Tomas G. Rokicki) writes:
> A lot of programs rearrange pages to do 2-up and the like
> by assuming the state between pages is the same as the state before
> the prolog.  I claim this is incorrect, and indeed these programs
> should look at not the original state, or the state between pages,
> but the changes between the two (there is a matrix divide in PostScript,
> right?) to perform there magic.

I'd agree, almost.  In particular, I believe that the document setup should
be considered to be effectively part of the prolog (at least, as far as the
state at the beginning of the page is concerned), since by its nature it does
things that affect the global state (paper size, etc.).

However, it is also very much a part of the Document Structuring Conventions
that there can be *no* persistent state from page to page.  Each page should
be thought of as sitting inside a save/restore pair.

> Consider the following program.
> 
> ...
> %%EndProlog
> %%BeginSetup
> 2 2 scale
> %%EndSetup
> %%Page 1
> ... gsave showpage grestore
> %%Page 2
> ... gsave showpage grestore
> %%Trailer

The '...'s are evil :-) if they change the global graphics state at all.

> Thus, a program that attempts to 2-up this document cannot simply
> redefine the `showpage' operator, as there could be any number of
> (including zero) gsave/grestore pairs around showpage.  Rather,
> the 2-up program needs to store away the initial state somewhere.
> Then, after setup, it needs to divide the new state by the initial
> state, and save this information away for its later use.  Each
> `transformation' it wants to make must then be divided by this
> new matrix we created before it is applied.

Well, inclusion of multi-page documents is a problem.  Aside from that,
however, how about doing a 'save' after the setup, and a 'restore save'
before each page?  That way, any transformations the new showpage does
are automatically added to the ones that the setup did.  I have in fact
used this very technique:  I have a version of "showpage" that prints
two-up with cut and fols marks.  The setup code tests to see if 11x17
paper is available, and if not it translates, rotates, and scales so 
that you get both pages (somewhat reduced) on a landscape-oriented letter
size page.  The 'showpage' doesn't care, since all of its transformations
are additive.  Ordering of setup code does become a problem, however,
unless each program that manipulates the PostScript file also produces
a completely conforming file as output (which I think should indeed happen).
Not always easy, though...

Amanda Walker
InterCon Systems Corporation
--

woody@rpp386.cactus.org (Woodrow Baker) (01/09/90)

In article <1990Jan8.195614.27489@Neon.Stanford.EDU>, rokicki@Neon.Stanford.EDU (Tomas G. Rokicki) writes:
> I claim this is incorrect, and indeed these programs
> should look at not the original state, or the state between pages,
> but the changes between the two...... 
I would agree with this, but the state is fairly complex, and not easily
gotten to. 
> 
> the 2-up program needs to store away the initial state somewhere.
> Then, after setup, it needs to divide the new state by the initial
> state, and save this information away for its later use.  Each
> `transformation' it wants to make must then be divided by this
> new matrix we created before it is applied.

The gsave /grestore context saves a lot more that just the CTM.  It also
saves the current path, positions, etc,etc.  There is no composite "state"
object that one could assign.  It would be really handy to have one.  It
should be added, and gsave should place a composite object somewhere that you
could then define a variable to contain.  It, however cannot be "divided".
Only the matrix can be divided.  It makes little sense to think about
dividing the path.....
cheers
Woody

amanda@mermaid.intercon.com (Amanda Walker) (01/10/90)

I'm usually not too annoyed at the strict stack behavior of gsave & grestore,
but among the things that I would love to see in some future version of
PostScript is the path as a first class data type.  In most of the cases that
I end up using gsave & grestore, it's to get around the fact that I can't save
a path away in a variable and then bring it back later to stroke or fill it.
This is one of the things that I love about Metafont, that PostScript does
clumsily at best, and I really feel this lack when trying to describe complex
glyphs in a font.  It would also be very useful for doing step-and-repeat
work for things that aren't straightforward linear tilings.  For some tilings
(i.e. those that parallelogram-shaped tiles), you can get by pretty well
by defining a font of tiles, much the way Adobe Illustrator does pattern
fills.  However, for anything less text-like, the only approach seems to
be to build an exectuable array with pathforall and execute it later.
Unless of course you want to draw strings as part of the tile...

Even if path objects were occasionally opaque in the same ways the current
path is (such as when character outlines are in the path), they'd still be 
very useful.

Tough to implement, though, especially without a better storage allocator
(the old persistent variable-size data structure problem again).

Amanda Walker
Speaker To PostScript
InterCon Systems Corporation
--

gelphman@adobe.COM (David Gelphman) (01/10/90)

In article <1699@intercon.com> amanda@mermaid.intercon.com (Amanda Walker) writes:
>I'm usually not too annoyed at the strict stack behavior of gsave & grestore,
>but among the things that I would love to see in some future version of
>PostScript is the path as a first class data type.  In most of the cases that
...
   Two things in the PostScript language extensions contained in the
Display PostScript system help this particular situation. One is the
user path facility. Basically a user path is a procedure which contains
pure path construction (with optional caching) and can be passed directly
to operators like 'ustroke' and 'ufill' to stroke and fill a user path.
You can keep these objects around like normal procedure bodies and repeatedly
fill and/or stroke them. 
   A second facility is the gstate object. These are essentially an object
which is equivalent to the PostScript graphics state that can be used
to arbitrarily switch between graphics states (without concern about
the graphics state stack). It could be used to recover an already
constructed path had you saved away the gstate. Clearly the user path
machinery is more likely what you want since the graphics state contains
more state than what you wish to recover.
   These facilities are documented in the document "Extensions for the
Display PostScript System", available as part of a package from Adobe
of documentation on the Display PostScript system. 

>Amanda Walker
David Gelphman 
Adobe Systems Incorporated

amanda@mermaid.intercon.com (Amanda Walker) (01/10/90)

In article <1596@adobe.UUCP>, gelphman@adobe.COM (David Gelphman) writes:
> Basically a user path is a procedure which contains
> pure path construction (with optional caching) and can be passed directly
> to operators like 'ustroke' and 'ufill' to stroke and fill a user path.
> You can keep these objects around like normal procedure bodies and repeatedly
> fill and/or stroke them.

Now, this is what I was hoping to hear :-).  Any plans to retrofit this
into "hardcopy PostScript"?  I like the caching part particularly.  Looks
like it's time for to read up on Display PostScript.

Now if only I could buy it for a Macintosh :-)...

Amanda Walker
InterCon Systems Corporation
--

gelphman@adobe.COM (David Gelphman) (01/11/90)

In article <1708@intercon.com> amanda@mermaid.intercon.com (Amanda Walker) writes:
>In article <1596@adobe.UUCP>, gelphman@adobe.COM (David Gelphman) writes:
>> Basically a user path is a procedure which contains
>
>Now, this is what I was hoping to hear :-).  Any plans to retrofit this
>into "hardcopy PostScript"?  I like the caching part particularly.  Looks
>like it's time for to read up on Display PostScript.
>Now if only I could buy it for a Macintosh :-)...
>Amanda Walker
    The extensions in the Display PostScript system are part of the language 
as it is evolving. When we introduced the Display PostScript system it
was made clear that extensions which are appropriate for
printers would be incorporated into printers in the future. I can't comment
further. 

David Gelphman
Adobe Systems Incorporated