KDE developer Michael Goffioul today announced that he is actively addressing an area in KDE that warrants improvement: printing. He has committed source code to KDE CVS for a new KDE printing system to replace the limited Qt printing framework.
Support for LPR, CUPS and PDQ printing systems is already there.
Special emphasis is put on CUPS (Common Unix Printing System). The API is identical to the Qt API to enable developers to make use of it easily, but is significantly more flexible and configurable. For example, developers can easily add additional configuration pages to the print dialog to configure application-specific printing options, and can add filters to the printing structure to process the output. It also aims to provide a friendly user interface, including a print dialog, a KControl configuration module, a job viewer applet for the panel and a preview feature. People interested in supporting other systems should contact Michael and get involved now. His announcement is included below.

From:

Michael Goffioul

Date:

Wed, 28 Feb 2001 11:39:47 +0100

Organization:

IMEC

To:

KDE Development ,
KDE Core Development

Subject:

New KDE printing system

Hi all,

As some of you have already noticed, a new component appeared very recently
in kdelibs, called "kdeprint". This is actually a new printing library which
should replace the Qt printing mechanism and the current kprint library.
The goals of this library are:

prove an API interface identical to Qt to reduce changes for developers

support several printing systems through a common (as much as possible) the same user interface. It currently supports LPR, CUPS and PDQ.

prove a user-friendly interface for users

flexibility and configurability for developers: for example the possibility to plug additional pages in the print dialog for application specific options,
so developers don't need to redesign a print dialog, just use the standard one and add the pages you need.

The library is currently on the CVS, other parts (like KControl module and smallapps) should appear somewhere very soon. I'm not doing it myself because I
can't access CVS, being behind a firewall (with only HTTP proxy server).
The rest of the message is a short explaination on how to use this library. The
header files of interest are "kprinter.h", "kprintdialogpage.h" and "optionset.h".

API

1.1 KPrinterFactory class

This class is used to create KPrinter object (see below). Developers shouldn't
construct directly KPrinter object, but use "KPrinterFactory::self()->printer()".
The factory takes care of the user settings and construct an object for the
appropriate underlying printing system. DO NOT delete the KPrinter object, as
it will be reused for other calls.

1.2 KPrinter class

There's a class called "KPrinter". This class provides exactly the same interface
as QPrinter class, with some enhancements. So changing QPrinter to KPrinter
should be OK in most cases. For configuring, use "KPrinter::setup(QWidget*)",
don't use old QPrintDialog calls. If you want to print a PS file that you have
created in your application, you can use "KPrinter::printFile(const QString&)".

Flexibility

The developer has the possibility to plug additional pages in the main print dialog
for application specific options. To do that you have to subclass the KPrintDialogPage
class and implement the virtual members. The communication between the print
dialog and these additional pages is made through an "OptionSet' object which
inherits QMap. So your applications specific options should
have the form "key=value". Of course the value can then be interpreted as the
developer wants to (int, float, string, ...). For internal reasons, the key should have
the form "kde-", but this is not mandatory.
The virtual members to implement are:

"void setOptions(const OptionSet&)": your page should then update its content according to the option set given. You can retrieve easily your options as this is actually a map.

"void getOptions(OptionSet&, bool)": your page should then fill the option set with the current settings. The bool flag tells the developer wether default values should be included or not (true == include default).

"QString pageTitle()": pages are shown in a tab widget in the main dialog. This member return the string to use for tab title.

"bool isValid()": tells the main dialog if selected options are valid (sometimes you can have comflicting settings). However it is not used yet.

To plug your page into the dialog, use "KPrinter::addDialogPage(KPrintDialogPage*)". At this moment, you have to provide a page each time you call "setup()" member of KPrinter, as the dialog is deleted when it is closed. However this may change in the future.

Misc

The KPrinter class provides some enhancements and configuration possibility. Forexample the possiblity to tell the printer object if the application can handle
page
selection itself or not (some printing system provide page selection mechanism),the dialo appearance is changed accordingly.

Printing management

The current library will be rewritten soon. I extended the concepts I used to develop
a generic printing managemnet system for KDE: this means a printing management
tool supporting several printing sytsems through a common interface. This interface
will be heavily based on KUPS. As some important components will be written for
this tool, they can be re-used for the kdeprint library. This means the kdeprint library
will be integrated in this tool. However the API shoudn't change significantly,
so
developers shouldn't worry. But this management tool will be more generic: common
driver configuration tool, plugin mechanism (no library dependence anymore), ...While developing this tool, I only develop a CUPS plugin. However I'm looking for
people interested in developing plugin for other print systems (LPR+printtool,
LPR+foomatic, PDQ, LPRng, ...), and more generally people interested in making
things going faster.

You might want to give CUPS a spin even before KPrinter class is available for end users because of its integration into KDE 2.2.

For most KDE-people, CUPS still is "white territory". For those able to read German, my CUPS-FAQ might be helpful to overcome the first installation or configuration obstacles (or just provide a theortical overview - for newbies, administrators and programmers alike)

Just don't forget to NATIVELY support non-Latin1 characters! Mozilla developers seem to have forgoteen about it and now they are working on fixing it, but it doesn't look to bright right now. StarOffice5.2 is one app that supports printing the document WYSIWYG.

Wow, .... I'm impressed
I just replaced the old printing system with
cups / kups on our LAN (running KDE 2.1 :)...
This is really good news.
Can't wait to get a first impession...
I guess konqui will be one of the first apps making use of the new KPrinter class... ?

Will this end up using GhostScript at some level? Overall, I am not impressed with the printing system in *nix. It just seems clunky to have a chain of several different programs/filters which all pipe from one to another.

I would think that a common dialog with the complete filtering back end integrated into the KDE library system would be best. (read: dump GhostScript, or integrate the filtering/converting chunks from an older GPL'd GhostScript into the KDE libraries).

The output from the KDE printer class (or whatever its called) should already be in the raw data format which the printer expects to see. Eliminate the middleman!

It would be interesting to know if using these new libraries one finally would be able to print using Truetype fonts. I don't want to get into the fight if type1 or ttf fonts are better. All I care is that Linux still lacks good font support (looking at fonts is one thing, have them in properresolution is another... I guess the coming up anti-aliasing is taking care of one part of
this problem). The other thing is printing support for Truetype fonts. This seems to be a good possibility to kill two birds with one stone.

Will this end up using GhostScript at some level? Overall, I am not impressed with the printing system in *nix. It just seems clunky to have a chain of several different programs/filters which all pipe from one to another. I would think that a common dialog with the complete filtering back end integrated into the KDE library system would be best. (read: dump GhostScript, or integrate the filtering/converting chunks from an older GPL'd GhostScript into the KDE libraries). The output from the KDE printer class (or whatever its called) should already be in the raw data format which the printer expects to see. Eliminate the middleman!

Absolutely not. There needs to be an abstract layer in there that KDE uses to talk to the printer driver, for the following reasons:

The output may simply be too big in that format. Something like the Epson Stylus Photo 870 generates about 50 MB of output for a single letter (or A4) size page that's fairly dense, in a moderately high quality mode (it's basically a pure raster printer). For printing a large document on the fly, the output must be streamed.

Some printers require bidirectional communication just to print (Samsung winprinters, for example). Just to make matters worse, the Samsung printer is timing sensitive; if you allow the wrong amount of time to elapse, you can physically damage the printer. It may not be possible for the raw printer output to even be generated without talking directly to the printer. If the printer's on a remote host, or the sysadmin doesn't want to trust users to be allowed to talk directly to the printer, this architecture just won't work. Period.

Accounting is pretty much impossible if the accounting program has to parse printer output, unless you're going to trust the client to tell you the truth.

If a particular printer goes offline, or busy, a printing system may want to offer the user a choice of printing to a different printer that might not be output-compatible (for example, if a shop has both a Stylus Photo 890 and a Stylus Photo 870, and the 890 goes offline, the user might want to redirect the job to the 870, but it doesn't accept all of the options that the 890 does).

I've had the same argument with the GNOME people for the past 9 months or so, for exactly the same reasons. They have an innovative printing architecture (based on a drawing canvas), but they seem to really want to generate raw printer output at the client level. It really doesn't matter too much if it does use GhostScript, particularly when Mike Sweet finishes his version that can load shared objects and such, but it does need to have some kind of IL to actually transfer the data between layers.

I do agree that there needs to be a bidirectional channel with the driver so that the driver can handle arbitrary options and such, but there needs to be a clear separation between the KDE printer class, the spooler, and the driver.

I haven't had a chance to study the printer class yet; my comments were just in response to the parent of my previous post. However, here are some thoughts I have on the matter.

A driver needs to have two components: a back end that takes input from the spooling system (either directly or through Ghostscript, for example), and a front end that interacts with the printing application (which may be the KDE printing class, lpr, or what have you). The front end describes the printer to the application layer, including its capabilities, options, and such.

The OMNI printing project that IBM's working on is attempting to replace an actual front end with an XML-based printer description. For most purposes this will work; if there are dynamic options depending on printer state (such as whether a given printer has a roll-feed attached) and for status readback, it won't. Whether that matters is a matter of taste. In either case, there's a logical front end.

The application then generates some kind of well-known IL (PostScript is probably the right thing here), which it passes off to the spooling system. The PostScript contains the options selected by the user. The spooler then sends the output to the back end (which may be the printer itself if the printer is a PostScript printer, or else to the driver, which is presumably but not necessarily fronted by GhostScript to do the conversion from PostScript).

When I use the word "application" here I'm talking about the code that calls the front end and generates the IL; that doesn't mean that each KDE app should have its own logic for doing that. That's exactly where the printer class should come in; it should handle those details on behalf of the actual application.

This is, IMHO, the MOST needed change in the current KDE. KDE is wonderful and the KDE developers have done a really, really good job with the KDE 2.1 release (well, with the exception of the missing arts RPMs for RedHat 7 :)). I've been very impressed and VERY happy.

Printing under KDE has always left alot to be desired, and it is VERY refreshing to see this finally getting its due attention. With the great work done with QTCUPS, KUPS, etc. it's been a shame that the KDE applications haven't been taking advantage of it.

I'm really, really glad to see that someone has picked up the ball and run with it. This piece of KDE should get a huge amount of attention from all KDE developers. I would even go as far as to say that ALL apps that ship with the next release of KDE should be required to use this printing architecture. I would like to see the core KDE developers officially bless all of this and encourage all KDE-based application developers to embrace this way of handling printing.

Great work and good luck! I am definitely behind you 100%. I'm willing to do testing/QA work on it if needed.

Will this support printing multiple document pages on one physical page, and vice versa? That would be very useful in printing large banners, even on printers that don't have support for banner printing. (Paper cutter and glue stick, anyone?)

IMO the biggest problem is that Linux does not
offer a general way to handle the mapping between printer (ghostscript) and display (X11) fonts. In short, Linux's left hand does not know what it's right hand is doing. This issue needs to be addressed in printing systems, preferably below the toolkit level.

The greatest new feature in the 2.3 release is support for Xft, which
gives anti-aliased text on X11. Xft is supported by XFree86 version 4.0.2 and
later. See the more detailed description below.

A lot of work has also been done to enhance the printing support on Unix/X11.

QPSPrinter True type and Postscript fonts used will now be embedded into the generated document. This will make fonts on the
printer look exactly like the output on the screen if the
application uses true type or postscript fonts.
Added better support for printing of asian languages.
Added a font replacement algorithm to get better looking
results in the cases where font embedding is not possible.

Xft support on X11 Qt now has full support for antialiased fonts on X11 via the Xft
extension.
The only XServer supporting this feature is currently
XFree86 (> 4.0.2). Applications running on other XServers
will not see a difference and continue using the old font
system.
A new option -xft has been added to the configure script
to enable or disable xft support at compile time.
Xft support can be enabled or disabled at application startup
time by setting the environment variable QT_XFT to 'true'.
Antaliased fonts are not enabled by default, as most XServers
still don't support it.
Enabling/disabling Xft support is completely transparent to the
application itself.

I think this is great I am a Gnome user myself but printing is one area that is really lacking in Unix and as long as there is some common standard for the printing eg CUPS and LPDng then this will improve everybodys life. But I do wonder if all the people from gimp-print gnome-print, ghostscript and now kdeprint and xprint and openoffice be working towarard a more common interface. By all means have a diffirent API but the user should be seeing a similar interface no matter where they print from. Ie I should be able to set my default print engine to gimp-print or what ever and this will allways look the same no matter where I print from ie gnumeric kmail or openoffice.

First, I would like to thank you all for your support. It's always nice to see that other people do care about your work. I would to give here some explainations about the kdeprint library.

For your informations, I'm the author of QtCUPS and KUPS (co-author only for the latter), and you can see the kdeprint library as an integration of those tools into KDE. But the main idea is to provide general tools that can support several printing systems, like CUPS or LPR, while keeping the same interface for users and developers.

The goal of the kdeprint library is not to provide a low level printing system, it means that the library doesn't communicate directly with the printer. The main idea is to provide a interface between KDE/Qt applications and the underlying print system through a common interface (API and GUI). So it won't replace ghostscript, CUPS, LPR or whatever, but it will use them in a transparent way to the developer and the user. Even if the example may not be well suited, I would say that the kdeprint library is (or should be) for printing what the kio library is for file access.
Another concept is that the kdeprint library is not meant to be an intersection of the possible underlying print systems, but an union. I mean that the user should still have a full control on the printer, as if he would be using directly the underlying print system. For example in the case of CUPS, the user will still have a full control on all options of the PPD file.

So there will still be a need for a real print spooler like CUPS or LPR. They are doing a great job, and kdeprint won't replace them. As one of you said, it's better to separate the API interface from the print spooler. Moreover the use of successive filters for print processing is a good mechanism as it is completely modular.

To answer some other questions, a filter mechanism is currently on its way. Those filters will convert the data before sending them to the print spooler. You can then imagine filters like "psnup" or "enscript" to be attached to a given printer, to format you data as you want.

The work is currently being extended to a complete printing managament tool. This mean that you will be able the stop, start, add, remove, configure printers through a common graphical interface wether you're using CUPS, LPR, PDQ, rhs print filters, or what else you can imagine.