Mac OS X Porting - Native Printing
This page is dedicated to the native printing implementation in OpenOffice.org for Mac OS X
- 1 What we want to do ?
- 2 OpenOffice.org side
- 3 Mac OS X API side
- 4 Screenshots - Status
- 5 Links
What we want to do ?
The final goal of this project is to have the native printing support on Mac OS X.
What we have now and what we don't ?
Currently we simply have a generic printing support which works with X11. There is also printing support implemented for Windows. This means that we have already a way to implement our printing support for Aqua without breaking OpenOffice.org as we have already environment plug-ins.
However, we have only one Print Dialog and one Printer Setup dialog for all environments.
Tu sum up : we have a starting point to implement low-level printing support using the native API. We only have to implement the native code. But we have nothing for the dialogs.
What the users want ?
The user wants to be able to print with OpenOffice.org the same way he does with its other natives applications.
For us, this means using a native printing dialog. Then, we will also need to implement low-level printing using OS API because, without that the user might not be able to use every setting available in the native dialog.
What will be even better ?
Using UNO. This will allow other platform developpers to use the same code to implement their native dialogs.
This part describes what can be found in the OOo APIs, how it is implemented and how it will be changed.
OOo print process
I will try to share the few thing I understood about the way Writer prints document.
First I need to locate the print menu item in the sw module (sw stands for Star Writer). For this, I need to know where in sw the menubar is built. I did found the menubar, but not how the menu item was linked to the print operation. Instead, I have found a method PrintPages implemented in sw module. The stack may look like that :
- OutputDevice:: ...
TODO : Complete the stack trace
There is many holes in the stack but we get the idea. The OuputDevice is in fact our Printer.
1. The user Application creates a print dialog or a print setup dialog. For this, it needs to call svtools. To be a bit more precise, it creates a new instance of PrintDialog or of PrintDialogSetup, it associates a Printer instance to it, then, it calls the Execute method from PrintDialog or PrintSetupDialog. This operation shows the dialog (using the Execute method from ModalDialog, which is in vcl) and sets the Printer Data correctly with the method setPrinterProps. Do do the real display of the dialog, it uses SalFrame's Show() method, which can be X11SalFrame, AquaSalFrame, etc.
2. Svtools is responsible for asking to the user the requested information about printing options. Then, it returns them ot the user application.
3. The user application has now everything needed to print the document. So, it asks VCL to draw pixels, lines, characters, etc on an OutputDevice.
At this point, I don't know exactly where the OutputDevice is instancied (who decides that it would be a screen, an Aqua printer or a PostScript printer. This is not really important since we understand the main idea of how printing works.
4. After that VCL relies on its Graphic Context to really draws (i.e. make the OS really draws) the lines and pixels on the screen or on the print device.
Concerned OOo modules
What we know about vcl.
SalPrinter is a virtual class intended for managing print jobs. It is composed of virtual fonctions, and a dummy constructor. This class is inherited by PspSalPrinter, WinSalPrinter, and of course by AquaSalPrinter (see AquaSalPrinter class).
Its header is located in vcl/inc/salprn.hxx It has no implementation file.
PspSalPrinter means PostScript Print System Abstraction Layer Printer. Its implementation is located in vcl/unx/source/gdi/salprnpsp.cxx. As the name suggests it relies on features psprint module.
TODO : Discuss about PspSalPrinter implementation.
This is an abstraction class of a printer driver. You can entirely set up the printer there and start print jobs. What we need here is to make our native dialog access to this Printer. The we will need to make this class access to OS API rather than psprint.
AquaSalPrinter class is located in vcl/aqua/source/gdi/print.cxx
This class inherits of OutputDevice and is derivated in ImplQPrinter.
- QueueInfo class - This class is related to the Printer class. It is used to store information about printers (name, driver, location, comment as strings, and number of Jobs, and a status code).
This class allows applications such as Writer to draw graphics elements (pixels, lines, rects, characters, strings, etc...).
This class is located in vcl/source/gdi/outdev.cxx, vcl/source/gdi/outdev[2-6].cxx
At this time, we don't need to know the details of this class. We will focus on it when we will use the Carbon Printing API.
This class is responsible to translate the abstract drawing calls to concrete OS calls.
The class I need to reimplement using Aqua printing primitives... It will probably called AquaPrintGraphics...
AquaSalPrinter class is located in vcl/aqua/source/gdi/salprn.cxx
Headers are in :
vcl/inc/salinst.hxx vcl/inc/salgdi.hxx vcl/inc/salprn.hxx
Aqua implementation : vcl/aqua/inc/salprn.h (AquaSalPrinter class implementation, inherits from SalPrinter)
What we know about psprint.
What we need to know about svtools. Mostly it provides us the Print Dialog, and some other Print related dialogs.
This class is responsible for drawing the print dialog we usually view when we choose the Print option of the File menu. The current implementation uses this class to draw the print dialog. In our Aqua native implementation, we want to use the on provided by Carbon API. To achieve this, we want to know the functionality of this class, and let carbon manage the functionality maybe at this level or maybe in a other lever (higher or lower). We also need to know how this class provides information to the Printer instance.
- The header of this class is located in svtools/inc/svtools/printdlg.hxx
- The implementation of this class is located in svtools/source/dialogs/printdlg.cxx
This class is a child of ModalDialog class.
It contains all the UI elements used by the dialog which are either :
- FixedInfo : it is a child of FixedText and is defined in svtools/inc/stdctrl.hxx. It is nothing more than a FixedText with the info style applied (same behavior). It is used to store variables string since fixed text is for constant strings.
- ListBox : maLbName - List-box used to store the available printers.
- Edit : a text box
Useless in our case :
- FixedImage : draws an image on dialog
- FixedLine : draws a line on dialog
These controls are used to allow the user to interact with the dialog. We only need to know the user-provided information. What is involved to display them, and how the look & feel is implemented is not interesting at this point, since we only want to know what the dialog actually does. So as FixedImage, FixedLine provide no useful information, we don't need them.
There is also a timer intended to regulary update the current Printer status (ready, printing, paused, pending, waiting, offline, error…)
- AutoTimer maStatusTimer
TODO : List of all user-related information stored by this class and sent to the Printer and determine what work is involved when using Carbon equivalent.
|PrinterDialog propery||Work needed||Current status|
|maCbxFilePrint||Nothing, Aqua does PDF printing||Done|
|maEdtFaxNo||Nothing, Aqua does it||Done|
|maBtnBrowse_nomore||appears to be unused in current implementation||Done|
|maRbtAll||Fetch this information from Aqua dialog See below|
|maEbtPages||Fetch this with Carbon using PMGetFirstPage and PMGetLastPage fields (Warning: custom panel needed or equivalent to have the same level of functionality)|
|maRbtSelection||Not natively provided, to do it we will need to override the default copies and pages panel using kPMCopiesAndPagesPDEKindID|
|maNumCopies||Fetch from Aqua using PMGetCopies|
|maCbxCollate||Fetch from Aqua using PMGetCollate|
|maBtnOptions||Detail in other dialog (some is provided by Aqua, some may need a custom panel)... See Extending Printing Dialogs|
|maBtnHelp||Nothing, Aqua do this||Done|
The class contains also fields used to store the real information provided by the controls (Mostly USHORT and BOOL). There is also a XubString instance and a PrintDialogRange instance used to store range information.
Of course, this class contains an Printer instance and a SvtPrinterImpl instance in order to set the printer functionality.
There is also internal methods, and links to the Option handler and the OK handler. You can find more information in the following file tools/inc/tools/link.hxx
The public methods are mostly getters and setters, I won't detail it since I have already provided information about the private attributes, and they do nothing to the Printer instance.
TODO : details the implementation of this class (interesting methods : ImplGetFileName, IMPL_LINK(PrintDialog, ImplModifyControlHdl, void*, p)
For Aqua port, we need to re-implement this class in order to make it displays the native Aqua Print Dialog that will be provided by the Carbon API, and save information that was previously provided by children of Control class. We should also disable the Printing options provided by the Aqua dialog that are not provided by the Printer class (the information we cannot currently store). Update : Since we won't use the current printing system and directly use CoreGraphics, we won't have this problem (CoreGraphics will print correctly).
Print Setup file
Utility functions :
- ImplFillPrnDlgListBox(const Printer *, ListBox *, PushButton *)
This method fills the Printer list-box with the QueueInfo provided by the Printer instance provided in argument. It then enables the OK button if the list is not empty.
Mac OS X API side
This part describes what can be used and how we intend to use it.
The strategy is to first use the Carbon API to get Print Information and to provide an Aqua User Inerface for printing. Then, we will try to replace the current printing API to the native one, allowing to reduce dependencies, and the total package size.
Carbon provides multiple way for us to print. We might consider every of different approaches :
- Printing using psprint. We only get settings from the Carbon Print Dialog and the Carbon Print Setup Dialog with the function PMGetPrintSettingsExtendedData (for example) and then we send the obtained parameters to our SalPrinter.
- Using the PMPrintToFile function (OpenOffice.org provides a postcript version of the document, and then, Carbon handles the print operation)
- Printing using a QuickDraw graphic context See this link for an example (As this is a legacy API, we are not enthusiast about using it in OpenOffice.org)
- Printing using a Quartz 2D graphic context More information about Quartz 2D
We may want to add some features to the Printing dialog provided by Carbon. This is documented here
Todo : implement missing methods, using Carbon API
Using Aqua Printing Dialogs
In a first a approach, we want to use Aqua dialogs and set the SalPrinter instance with the data provided by the dialog.
Then, we want to get rid of the OpenOffice.org print dialog, for this, we need to add a custom print dialog addition to allow user to choose options not provided by Apple Print Dialog, however the behaviour might not be as the user except since we still use CUPS instead of Quartz.
After this step, we should have a great native interface, now we want to print using Quartz instead of CUPS. To do this, we need to fill the Carbon Print object using the data provided by our Printer instance.
We need then to hook Sal Graphic context primitives to the Quartz ones.
Using Quartz Graphic Context to Print
Screenshots - Status
Link for Mac OS X API documentation
Starting point for documentation
http://developer.apple.com/documentation/Carbon/Printing-date.html#//apple_ref/doc/uid/TP30000440-TP30000420-TP30000455 http://developer.apple.com/documentation/Carbon/Conceptual/CPM_Concepts/cpm_chap4/chapter_4_section_1.html http://developer.apple.com/samplecode/Carbon/idxPrinting-date.html http://developer.apple.com/referencelibrary/Carbon/idxPrinting-date.html
This work is part of http://wiki.services.openoffice.org/wiki/Mac_OS_X_Porting_-_Work_Areas/Todo%27s
Created: Ericb 19:33, 4 June 2006 (CEST)
Last modification: ybart 0:00, 16 October 2006 (CEST)