[lazarus] Printers unit

andrew johnson acjgenius at earthlink.net
Tue Nov 5 15:06:58 EST 2002

On Tue, 2002-11-05 at 13:37, Tony Maro wrote:
> First, Andrew, I asked about how to make TPrinter print to file in
> Delphi - not how to make the document print when I'm done.  How do you
> select a filename as output in Delphi printing, rather than a printer
> driver?

Sorry misunderstood.. but essentially the same answer applies YOU don't.
It is all automated by Delphi via standard means. If you want too print
to a File it has to be set by some sort of print dialog which calls to
win32 etc. And Even then I have never actually seen it done, or for that
matter be of any use because in Win32 it is almost impossible to DO
anything with the file it produces. So in this case I say, simply add
new properties to the printer, something like

TPrinterOutputType = (otStdOut, otFile, otPrinter);

Property OutputType : TPrinterOutputType read.. write..
Property OutputName : String read.. write...

where the output name is the printer name or the file name, or nothing
if stdout.

> Also, I've already changed a bit on the path definition so it's not one
> path per page, I know exactly what you mean.  Last night I added
> rectangle routines.
> On Tue, 2002-11-05 at 08:56, Michael Van Canneyt wrote:
> > > > I've tried to make it as ready for real printer support as possible.
> > > > What I've done is added a TPostScriptCanvas object that handles most of
> > > > the Postscript work - not that there's a lot to do.  Unfortunately part
> > > > of it must be handled at the Printer object level (page separation, etc)
> > > > so I can't encapsulate all of the postscript generation in that object.
> > >
> > > Are you certain? I was fairly sure that Postscript supported multiple
> > > pages from the same file... with %%Page
> > 
> > AFAIK the showpage command takes care of this.
> > %%PAGE is for structured documents, so Ghostview and other PSUtils
> > can 'see' the different pages.
> Right, and I'm using both, but my point is that a canvas in a TPrinter
> object which I based this on is a single page.  So to separate between
> the pages, it had to be handled outside the canvas.  Or am I wrong in
> thinking that a TPrinter.Canvas object is only covering the current
> page?

Well basically here is on place where the Postscript object comes in,
the Printer can own the Postscript object, and the printer can use that.

Aka instead of sending the printer to the canvas, send the postcript

> > > It's a start. Portions of this would be much easier on the interface
> > > side of things, but that would make things harder for Cross-Platform
> > > support. My Suggestion would be to write a third object. A TPostscript
> > > object encapsulating the Postscript calls. Not a translation, not
> > > anything. Pure Postscript calls. This way it would be easier later on to
> > > separate the Postscript code from your canvas and move it to the
> > > back-end of things.
> > 
> > I also think this is the way to go; I would put this object in the
> > FCL instead of the LCL, since it is OS-independent, and has nothing
> > visual about it.
> > 
> > If you can output the postscript to a stream, then everything should run
> > on any platform we support.
> Well I plan to just leave the Postscript in a TStringList, and keeping
> it platform independent should be easy.  I can easily put that in a
> TPostScript object  with all the appropriate canvas-like drawing
> functions.  I still like the TCanvas inheritance because I'm learning
> EPS right now and it seems to me I can give the users access to graphic
> routines to copy in bitmaps that will go to the graphic underneath the
> postscript, then when you read out the postscript code you would get the
> postscript drawing routines AND the encapsulated graphics of whatever
> wouldn't draw in postscript code directly.  It also would make it easy
> to add a print method to a form by taking the forms canvas and dumping
> it into EPS.  Perhaps it would be better though when someone does a call
> like that to create a new bitmap when they call those drawing routines,
> allow them to write their graphic into it, crop it back to just the size
> of what was edited, and encapsulate it right then into postscript.
> What I'm not clear on is how the TPrinter object is supposed to interact
> with the printer driver.  It seems like what I'm developing for
> postscript here is basically a different kind of canvas - this would be
> more akin to a printer driver in Delphi then it is a TPrinter object -
> or even a TCanvas object.  But with the design of the TPrinter being the
> way it is, and the differences between Linux and Windows printing I'm
> still a little foggy on how best to link this.
> The way I see it, a TPrinter is independent from the printer drivers. 
> The TCanvas gets it's properties from the printer driver to decide it's
> size, resolution, etc.  When you perform operations on the
> Printer.Canvas, you're really talking to the printer driver THROUGH the
> TCanvas.  So, really in effect what I'm proposing writing for postscript
> support is a virtual printer driver...?
> The other thing is that there are huge differences in the way the
> printing systems are accessed between Windows and *nix.  In Windows I'm
> going to need a handle to the printer driver, etc... in Linux that
> doesn't apply.  I'm stressing over how to differentiate in Linux to
> specify a printer from the list, etc. without breaking compatibility.

Well here I think you are misunderstanding and WAY over complicating
things.. What you are talking about is Postscript versus interface
specific printing or really against everything else. And that isn't what
we need to begin with. See here is how it should lay out, in the long
run (envision italics around that):

TPrinter -
  StdOut Mode(aka like Delphi's assign file) -

  File mode(what you are starting to do) -

  Printer Mode(what your stressing over..) -
        -metfiles & printer handles      
        -postscript & lpr
What you are talking about requires WAY more time and energy devoted all
at once than I would expect anyone to do. Start with the Postscript.
just the postscript. For now we can encapsulate this Printer object
around lpr via TProcess. Don't worry about everything else yet.

Basically it's like this, as Michael pointed out, done properly the
TPostscript part will be Cross-Platform. Wrapping a TCanvas around it
won't be that hard to begin with, and as we go it would be simple to
behind the scenes to take the code and add it to interface specific
printer canvas handle, aka the printer would file output mode, and the
actual calling to the lpr could be added to the backend as well. BUT for
now don't stress it. anything is better than nothing. And I can see
several ways to do this later on.

Anyway. As I said we only need a special Canvas for now. eventually that
can become a non-lcl based canvas for use with the postscript object,
and the interface specific routines encapsulating it. Until then keep
going the way you are going. The LCL started out only working for GTK+,
and it's only been recently that it started supporting Win32. So I see
nothing wrong with starting out only supporting Postscript printing.
After all even Windows supports Postscript printing, so we may still be
able to use the same code there. In fact, AFAIK AbiWord does something
along these lines. I might take a look myself later.


More information about the Lazarus mailing list