Next: Chapter 18 Contributing to the RichDoc Framework Up: Part II Expert's Guide Previous: Chapter 16 Introduction to the Data Model
The RichDoc contains a facility for printing documents into intermediate format, that can be used later for print preview or sending to a real printer. The intermediate files are useful to avoid repetitive print layouts, which may be very lengthy for big documents.
The RichDoc Print format has similar role like PostScript and PDF formats, and also has similar architecture. There are several reasons why we decided to create a new format and not to reuse existing standard formats. The main reason is that there is no cross-platform, patent free, Java™ compatible library for writing and reading PostScript, PDF or similar standard format. Implementing such library would be difficult, as the formats are very complex, and many of their features could not be even utilized by our framework. Another reason is that these formats do not have good support for Unicode, while Java™ Printing APIs fully support Unicode.
Moreover, our format has one more extra feature: it supports incremental printing, which allows modification of existing print file by reprinting only those pages that have been modified since last printing. This feature is useful for keeping print files of large documents up-to-date, if the documents are often modified.
The RichDoc Print format is merely a serialization of commands issued through the interface of the java.awt.Graphics2D
class. That is, the “printer” component implements the Graphics2D
interface by serializing the commands and storing them to a binary file. The “playback” component reads the serialized commands, and sends them to supplied object compatible with Graphics2D
, which may be either real printer or a print-preview component.
The print file is actually a ZIP file, consisting of page definition files, embedded bitmaps, document source title, and an index to support the incremental printing function. Each page definition file obeys a format described in Section 17.2.
This section defines the format of a single file within the overall print file, which is a definition of objects on a single page. The page-definition format is binary, i.e. it is a stream of bytes. Therefore, we need to define data types that are used to define object properties, and how they are serialized into streams of bytes. The data types are defined in Section 17.2.1.
Table 17.1 defines the top-level structure of the page definition file. First, the description of the printing media is written, see Section 17.2.2. Then follows a list of printing instructions, as they were recorded by the printer component. Each instruction starts with a code byte, which defines the type of the instruction, see Section 17.2.3. The sequence of instructions is terminated by a END_OF_FILE
value is encountered.
Table 17.1 Overall Page Definition Structure |
|
The data types are listed in Table 17.2. All integer data types are signed using the common, i.e. “two's complement”, encoding of negative numbers (e.g. unsigned 0xFF represents –1 byte value, 0xFE –2 value, etc.) All integers are stored in big endian, that is, more significant values are stored first.
Real numbers are encoded by first converting them to integers using java.lang.Double.doubleToLongBits()
or java.lang.Float.floatToIntBits()
, and then encoding them in big endian as integers. This encoding corresponds to the IEEE 754 standard for encoding numbers.
The string value is encoded the same way as if saved using java.io.RandomAccessFile.writeUTF()
. That is, the length of the string is first encoded as a 16-bit integer, and then the string characters are appended, each encoded using the UTF-8 encoding.
Table 17.2 Data Types |
|
Besides primitive data types, there are also more complex types needed to encode some parameters of the Graphics2D
interface. The serialization of java.awt.Shape
is described in Table 17.3.
Table 17.3 Serialization of |
|
Table 17.4 Serialization of |
|
Table 17.5 Serialization of |
|
Table 17.6 Serialization of |
|
Table 17.7 Serialization of |
|
The printing media definition section of the file defines the size and orientation of the paper to which the material is printed, see Table 17.8. First, the orientation of the paper is written, then its total size, imageable size (total size without margins), and imageable area offset from the total area. See Figure 17.1 for the meaning of fields in Table 17.8. Note that the fields describing the paper size refer to the portrait orientation of the paper. For instance, the A4 paper will always have the width of 210mm and the height of 297mm, regardless the paper orientation.
Table 17.8 |
|
Figure 17.1 Meaning of |
We call a single call to the Graphics2D
interface a printing instruction. To encode the printing instruction, we must encode its type, and all its parameters. All supported printing instructions and their parameters are summarized in Table 17.9. Since the parameters closely correspond to the parameters of Graphics2D
methods, we comment them very sparsely. See documentation of Graphics2D
for more information.
Table 17.9 |
|
In this section, we would like to mention some limitations and other technical notes regarding using the RichDoc Print interface from a Java™ application.
First, note that some features of the java.awt.Graphics2D
may not be implemented. For example, painting using general Paint
component is not supported. Also note that like Java Serialization format, this format is fragile, and is subject to change without notice. You should use it only for intermediate storage of print files, not for long-term storage. No support is provided for maintaining compatibility of various versions of this format. If you detect that a print file has different format version than you expect, you should consider the file invalid, and should not attempt to parse it.
Be aware that recorded printing commands may be played back in a different context that they were captured. It is therefore illegal to use any commands that set the global state of the java.awt.Graphics2D
class, such as by calling setTransform()
or setClip()
. You should use their relative equivalents, i.e. transform()
and clip()
. It is, however, legal to save the state of the class, e.g. by calling getTransorm
, and restore it later, e.g. by setTransform()
. The printing component automatically converts these commands to SAVE_TRANSFORM
and RESTORE_TRANSFORM
instructions, respectively.
Next: Chapter 18 Contributing to the RichDoc Framework Up: Part II Expert's Guide Previous: Chapter 16 Introduction to the Data Model