[Date Prev][Date Next][Thread Prev][Thread Next][Thread Index]

[XaraXtreme-dev] Advice required: Postscript "upside-down" problem, PostScript OS output

I've finally worked out the reason for the postscript upside-down-ness and
want some advice on how to proceed, particularly with regard to text.

Both Windows and wxWidgets have (0,0) at the top left hand corner of the
page in DC's by default, and with increasing (positive) Y working down
the page. PostScript has an origin at the bottom left hand corner of the
page, with increasing positive Y working up, at least by default.

However, the way these two systems handle the conversion diverges at that
point. In a Windows print job, the PostScript prologue contains a
transformation matrix so that device pixel coordinates have their Y
coordinates inverted. The coordinates in the postscript itself thus
have (0,0) at the top. In wxWidgets, the transformation matrix does not
invert the Y axis, and instead all the coordinates sent to Postscript
by the wxWidgets DC are converted one by one.

The obvious solution here is to fix our own transformation matrix where
it is calculated in PrintView, so that it flips the Y over. This, however,
has two problems:

1. If the transformation matrix is used to get device coordinates to pass
  to wxDC type functions (e.g. if we want to use OS for text output), they
  will be the "wrong way up", because wxWidgets will invert them again.
  Setting wxWidgets up to invert the coordinate space through its own
  axis inversion functions does not work either because this then inverts
  various rectangles required for showpage etc.; it is possible we could
  invert the coordinates merely when OS output is switched on, but see
  below re OS output.

2. Even when this /is/ done (I've tried it, it works with no OS output
  with simple files), complex files tend to die horribly. This appears to
  be because various things in GRenderRegion assume that the Y component
  of the matrix is positive. Having a Y inverted matrix leads to a negative
  scale factor in the render region, and a negative ScaledPixelWidth. This
  leads to negative size rectangles etc. etc. - I don't really fancy
  chasing through all these bugs.

The other solution is to somehow generate a transformation matrix in
the Postscript which looks like the one Windows would use. This seems to
be quite possible. Currently I am using wxPostscriptDC to produce everything
and it is not (it seems) capable of doing this (at least in any clean
way). If I do it the dirty way, I run into problem (1) again, which is
that wxWidgets output will not line up, because it expects the PS
transformation matrix to be something else. However, I avoid problem 2.

The next issue to consider is whether (2) is a real problem. As far as
I can tell, the native postscript DC rendering is only really used in
two scenarios:
a) Text output for text without complex attributes
b) Plotting various bitmaps (primarily from GRenderPrint when printing
  as a bitmap). It doesn't seem to be used from a PS RenderRegion print.

As far as (a) goes, you REALLY don't want to use the wxWidgets postscript
printing code. It handles exactly 3 fonts, and has all sorts of guesses as
to metrics. I am currently converting everything to curves (which works
fine, of course), but we could be more intelligent and use the same
mechanism we do for EPS export. I think we can safely forget this one.

And as far as (b) goes, again we could do with avoiding this piece of code.
It outputs the entire bitmap in hex without compression. We have far better
bitmap output code ourselves which we use for sending bitmaps in native
format. But even if we did use wxWidgets to do this, it doesn't matter
if the coordinates don't line up in PostScript as (as far as I can see)
we never use both our own Postscript and GRenderPrint on the same page
(we plot into a different bitmap using the MaskedRR stuff then send it
with our own bitmap code).

So what I am tempted to do is to mostly ignore the wxWidgets "native"
printer code. I could indeed write my own wxPostScriptDC or just derive
something from it. And persuade the render matrix to look like a windows
render matrix. I can then assume that we won't ever use native output,
and if we do need it, write the relevant routine ourselves. Alternatively
(perhaps better) whenever we use our own output, I can install a
windows-like transformation matrix.