Home | History | Annotate | Download | only in design
      1 PDF Theory of Operation
      2 =======================
      3 
      4 <!--
      5 PRE-GIT DOCUMENT VERSION HISTORY
      6     2012-06-25 Steve VanDeBogart
      7                * Original version
      8     2015-01-14 Hal Canary.
      9                * Add section "Using the PDF backend"
     10                * Markdown formatting
     11 -->
     12 
     13 
     14 Internally, SkPDFDocument and SkPDFDevice represents PDF documents and
     15 pages.  This document describes how the backend operates, but **these
     16 interfaces are not part of the public API and are subject to perpetual
     17 change.**
     18 
     19 See [Using Skia's PDF Backend](../../user/sample/pdf) to find out how
     20 to use SkPDF as a client calling Skia's public API.
     21 
     22 * * *
     23 
     24 ### Contents ###
     25 
     26 *   [Typical usage of the PDF backend](#Typical_usage_of_the_PDF_backend)
     27 *   [PDF Objects and Document Structure](#PDF_Objects_and_Document_Structure)
     28 *   [PDF drawing](#PDF_drawing)
     29 *   [Interned objects](#Interned_objects)
     30 *   [Graphic States](#Graphic_States)
     31 *   [Clip and Transform](#Clip_and_Transform)
     32 *   [Generating a content stream](#Generating_a_content_stream)
     33 *   [Drawing details](#Drawing_details)
     34     +   [Layers](#Layers)
     35     +   [Fonts](#Fonts)
     36     +   [Shaders](#Shaders)
     37     +   [Xfer modes](#Xfer_modes)
     38 *   [Known issues](#Known_issues)
     39 
     40 
     41 <span id="Typical_usage_of_the_PDF_backend">Typical usage of the PDF backend</span>
     42 -----------------------------------------------------------------------------------
     43 
     44 SkPDFDevice is the main interface to the PDF backend. This child of
     45 SkDevice can be set on an SkPDFCanvas and drawn to.  Once drawing to
     46 the canvas is complete (SkDocument::onEndPage() is called), the
     47 device's content and resouces are added to the SkPDFDocument that owns
     48 the device.  A new SkPDFDevice should be created for each page or
     49 layer desired in the document.  After all the pages have been added to
     50 the document, `SkPDFDocument::onClose()` is called to finish
     51 serializing the PDF file.
     52 
     53 
     54 <span id="PDF_Objects_and_Document_Structure">PDF Objects and Document Structure</span>
     55 ---------------------------------------------------------------------------------------
     56 
     57 ![PDF Logical Document Structure](/dev/design/PdfLogicalDocumentStructure.png)
     58 
     59 **Background**: The PDF file format has a header, a set of objects and
     60 then a footer that contains a table of contents for all of the objects
     61 in the document (the cross-reference table). The table of contents
     62 lists the specific byte position for each object. The objects may have
     63 references to other objects and the ASCII size of those references is
     64 dependent on the object number assigned to the referenced object;
     65 therefore we cant calculate the table of contents until the size of
     66 objects is known, which requires assignment of object numbers.  The
     67 document uses SkWStream::bytesWritten() to query the offsets of each
     68 object and build the cross-reference table.
     69 
     70 Furthermore, PDF files can support a *linearized* mode, where objects
     71 are in a specific order so that pdf-viewers can more easily retrieve
     72 just the objects they need to display a specific page, i.e. by
     73 byte-range requests over the web. Linearization also requires that all
     74 objects used or referenced on the first page of the PDF have object
     75 numbers before the rest of the objects. Consequently, before
     76 generating a linearized PDF, all objects, their sizes, and object
     77 references must be known.  Skia has no plans to implement linearized
     78 PDFs.
     79 
     80     %PDF-1.4
     81     objects...
     82     xref
     83     0 31  % Total number of entries in the table of contents.
     84     0000000000 65535 f
     85     0000210343 00000 n
     86     
     87     0000117055 00000 n
     88     trailer
     89     <</Size 31 /Root 1 0 R>>
     90     startxref
     91     210399  % Byte offset to the start of the table of contents.
     92     %%EOF
     93 
     94 The class SkPDFObjNumMap and the virtual class SkPDFObject are used to
     95 manage the needs of the file format. Any object that will represent a
     96 PDF object must inherit from SkPDFObject and implement the methods to
     97 generate the binary representation and report any other SkPDFObjects
     98 used as resources. SkPDFTypes.h defines most of the basic PDF object
     99 types: bool, int, scalar, string, name, array, dictionary, and stream.
    100 (A stream is a dictionary containing at least a Length entry followed
    101 by the data of the stream.)
    102 
    103 All of these PDF object types except the stream type can be used in
    104 both a direct and an indirect fashion, i.e. an array can have an int
    105 or a dictionary as an inline entry, which does not require an object
    106 number. The stream type, cannot be inlined and must be referred to
    107 with an object reference. Most of the time, other objects types can be
    108 referred to with an object reference, but there are specific rules in
    109 the PDF specification that requires an inline reference in some place
    110 or an indirect reference in other places. All indirect objects must
    111 have an object number assigned.
    112 
    113 *   **bools**: `true` `false`
    114 *   **ints**: `42` `0` `-1`
    115 *   **scalars**: `0.001`
    116 *   **strings**: `(strings are in parentheses or byte encoded)` `<74657374>`
    117 *   **name**: `/Name` `/Name#20with#20spaces`
    118 *   **array**: `[/Foo 42 (arrays can contain multiple types)]`
    119 *   **dictionary**: `<</Key1 (value1) /key2 42>>`
    120 *   **indirect object**:  
    121     `5 0 obj  
    122     (An indirect string. Indirect objects have an object number and a
    123     generation number, Skia always uses generation 0 objects)  
    124     endobj`  
    125 *   **object reference**: `5 0 R`
    126 *   **stream**: `<</Length 56>>  
    127     stream  
    128     ...stream contents can be arbitrary, including binary...  
    129     endstream`
    130 
    131 The PDF backend requires all indirect objects used in a PDF to be
    132 added to the SkPDFObjNumMap of the SkPDFDocument. The catalog is
    133 responsible for assigning object numbers and generating the table of
    134 contents required at the end of PDF files. In some sense, generating a
    135 PDF is a three step process. In the first step all the objects and
    136 references among them are created (mostly done by SkPDFDevice). In the
    137 second step, SkPDFObjNumMap assigns and remembers object numbers.
    138 Finally, in the third
    139 step, the header is printed, each object is printed, and then the
    140 table of contents and trailer are printed. SkPDFDocument takes care of
    141 collecting all the objects from the various SkPDFDevice instances,
    142 adding them to an SkPDFObjNumMap, iterating through the objects once to
    143 set their file positions, and iterating again to generate the final
    144 PDF.
    145 
    146 As an optimization, many leaf nodes in the direct graph of indirect
    147 objects can be assigned object numbers and serialized early.
    148 
    149     %PDF-1.4
    150     2 0 obj <<
    151       /Type /Catalog
    152       /Pages 1 0 R
    153     >>
    154     endobj
    155     3 0 obj <<
    156       /Type /Page
    157       /Parent 1 0 R
    158       /Resources <>
    159       /MediaBox [0 0 612 792]
    160       /Contents 4 0 R
    161     >>
    162     endobj
    163     4 0 obj <> stream
    164     endstream
    165     endobj
    166     1 0 obj <<
    167       /Type /Pages
    168       /Kids [3 0 R]
    169       /Count 1
    170     >>
    171     endobj
    172     xref
    173     0 5
    174     0000000000 65535 f
    175     0000000236 00000 n
    176     0000000009 00000 n
    177     0000000062 00000 n
    178     0000000190 00000 n
    179     trailer
    180     <</Size 5 /Root 2 0 R>>
    181     startxref
    182     299
    183     %%EOF
    184 
    185 
    186 <span id="PDF_drawing">PDF drawing</span>
    187 -----------------------------------------
    188 
    189 Most drawing in PDF is specified by the text of a stream, referred to
    190 as a content stream. The syntax of the content stream is different
    191 than the syntax of the file format described above and is much closer
    192 to PostScript in nature. The commands in the content stream tell the
    193 PDF interpreter to draw things, like a rectangle (`x y w h re`), an
    194 image, or text, or to do meta operations like set the drawing color,
    195 apply a transform to the drawing coordinates, or clip future drawing
    196 operations. The page object that references a content stream has a
    197 list of resources that can be used in the content stream using the
    198 dictionary name to reference the resources. Resources are things like
    199 font objects, images objects, graphic state objects (a set of meta
    200 operations like miter limit, line width, etc). Because of a mismatch
    201 between Skia and PDFs support for transparency (which will be
    202 explained later), SkPDFDevice records each drawing operation into an
    203 internal structure (ContentEntry) and only when the content stream is
    204 needed does it flatten that list of structures into the final content
    205 stream.
    206 
    207     4 0 obj <<
    208       /Type /Page
    209       /Resources <<
    210         /Font <</F1 9 0 R>>
    211         /XObject <</Image1 22 0 R /Image2 73 0 R>>
    212       >>
    213       /Content 5 0 R
    214     >> endobj
    215 
    216     5 0 obj <</Length 227>> stream
    217     % In the font specified in object 9 and a height
    218     % of 12 points, at (72, 96) draw Hello World.
    219     BT
    220       /F1 12 Tf
    221       72 96 Td
    222       (Hello World) Tj
    223     ET
    224     % Draw a filled rectange.
    225     200 96 72 72 re B
    226     ...
    227     endstream
    228     endobj
    229 
    230 <span id="Interned_objects">Interned objects</span>
    231 ---------------------------------------------------
    232 
    233 There are a number of high level PDF objects (like fonts, graphic
    234 states, etc) that are likely to be referenced multiple times in a
    235 single PDF. To ensure that there is only one copy of each object
    236 instance these objects an implemented with an
    237 [interning pattern](http://en.wikipedia.org/wiki/String_interning).
    238 As such, the classes representing these objects (like
    239 SkPDFGraphicState) have private constructors and static methods to
    240 retrieve an instance of the class.
    241 
    242 The SkPDFCanon object owns the interned objects.  For obvious reasons,
    243 the returned instance should not be modified. A mechanism to ensure
    244 that interned classes are immutable is needed.  See [issue
    245 2683](https://bug.skia.org/2683).
    246 
    247 <span id="Graphic_States">Graphic States</span>
    248 -----------------------------------------------
    249 
    250 PDF has a number of parameters that affect how things are drawn. The
    251 ones that correspond to drawing options in Skia are: color, alpha,
    252 line cap, line join type, line width, miter limit, and xfer/blend mode
    253 (see later section for xfer modes). With the exception of color, these
    254 can all be specified in a single pdf object, represented by the
    255 SkPDFGraphicState class. A simple command in the content stream can
    256 then set the drawing parameters to the values specified in that
    257 graphic state object. PDF does not allow specifying color in the
    258 graphic state object, instead it must be specified directly in the
    259 content stream. Similarly the current font and font size are set
    260 directly in the content stream.
    261 
    262     6 0 obj <<
    263       /Type /ExtGState
    264       /CA 1  % Opaque - alpha = 1
    265       /LC 0  % Butt linecap
    266       /LJ 0  % Miter line-join
    267       /LW 2  % Line width of 2
    268       /ML 6  % Miter limit of 6
    269       /BM /Normal  % Blend mode is normal i.e. source over
    270     >>
    271     endobj
    272 
    273 <span id="Clip_and_Transform">Clip and Transform</span>
    274 -------------------------------------------------------
    275 
    276 Similar to Skia, PDF allows drawing to be clipped or
    277 transformed. However, there are a few caveats that affect the design
    278 of the PDF backend. PDF does not support perspective transforms
    279 (perspective transform are treated as identity transforms). Clips,
    280 however, have more issues to cotend with. PDF clips cannot be directly
    281 unapplied or expanded. i.e. once an area has been clipped off, there
    282 is no way to draw to it. However, PDF provides a limited depth stack
    283 for the PDF graphic state (which includes the drawing parameters
    284 mentioned above in the Graphic States section as well as the clip and
    285 transform). Therefore to undo a clip, the PDF graphic state must be
    286 pushed before the clip is applied, then popped to revert to the state
    287 of the graphic state before the clip was applied.
    288 
    289 As the canvas makes drawing calls into SkPDFDevice, the active
    290 transform, clip region, and clip stack are stored in a ContentEntry
    291 structure. Later, when the ContentEntry structures are flattened into
    292 a valid PDF content stream, the transforms and clips are compared to
    293 decide on an efficient set of operations to transition between the
    294 states needed. Currently, a local optimization is used, to figure out
    295 the best transition from one state to the next. A global optimization
    296 could improve things by more effectively using the graphics state
    297 stack provided in the PDF format.
    298 
    299 <span id="Generating_a_content_stream">Generating a content stream</span>
    300 -------------------------------------------------------------------------
    301 
    302 For each draw call on an SkPDFDevice, a new ContentEntry is created,
    303 which stores the matrix, clip region, and clip stack as well as the
    304 paint parameters. Most of the paint parameters are bundled into an
    305 SkPDFGraphicState (interned) with the rest (color, font size, etc)
    306 explicitly stored in the ContentEntry. After populating the
    307 ContentEntry with all the relevant context, it is compared to the the
    308 most recently used ContentEntry. If the context matches, then the
    309 previous one is appended to instead of using the new one. In either
    310 case, with the context populated into the ContentEntry, the
    311 appropriate draw call is allowed to append to the content stream
    312 snippet in the ContentEntry to affect the core of the drawing call,
    313 i.e. drawing a shape, an image, text, etc.
    314 
    315 When all drawing is complete, SkPDFDocument::onEndPage() will call
    316 SkPDFDevice::content() to request the complete content stream for the
    317 page. The first thing done is to apply the initial transform specified
    318 in part in the constructor, this transform takes care of changing the
    319 coordinate space from an origin in the lower left (PDF default) to the
    320 upper left (Skia default) as well as any translation or scaling
    321 requested by the user (i.e. to achieve a margin or scale the
    322 canvas). Next (well almost next, see the next section), a clip is
    323 applied to restrict drawing to the content area (the part of the page
    324 inside the margins) of the page. Then, each ContentEntry is applied to
    325 the content stream with the help of a helper class, GraphicStackState,
    326 which tracks the state of the PDF graphics stack and optimizes the
    327 output. For each ContentEntry, commands are emitted to the final
    328 content entry to update the clip from its current state to the state
    329 specified in the ContentEntry, similarly the Matrix and drawing state
    330 (color, line joins, etc) are updated, then the content entry fragment
    331 (the actual drawing operation) is appended.
    332 
    333 <span id="Drawing_details">Drawing details</span>
    334 -------------------------------------------------
    335 
    336 Certain objects have specific properties that need to be dealt
    337 with. Images, layers (see below), and fonts assume the standard PDF
    338 coordinate system, so we have to undo any flip to the Skia coordinate
    339 system before drawing these entities. We dont currently support
    340 inverted paths, so filling an inverted path will give the wrong result
    341 ([issue 241](https://bug.skia.org/241)). PDF doesnt draw zero length
    342 lines that have butt of square caps, so that is emulated.
    343 
    344 ### <span id="Layers">Layers</span> ###
    345 
    346 PDF has a higher level object called a form x-object (form external
    347 object) that is basically a PDF page, with resources and a content
    348 stream, but can be transformed and drawn on an existing page. This is
    349 used to implement layers. SkPDFDevice has a method,
    350 makeFormXObjectFromDevice(), which uses the SkPDFDevice::content()
    351 method to construct a form x-object from the the
    352 device. SkPDFDevice::drawDevice() works by creating a form x-object of
    353 the passed device and then drawing that form x-object in the root
    354 device. There are a couple things to be aware of in this process. As
    355 noted previously, we have to be aware of any flip to the coordinate
    356 system - flipping it an even number of times will lead to the wrong
    357 result unless it is corrected for. The SkClipStack passed to drawing
    358 commands includes the entire clip stack, including the clipping
    359 operations done on the base layer. Since the form x-object will be
    360 drawn as a single operation onto the base layer, we can assume that
    361 all of those clips are in effect and need not apply them within the
    362 layer.
    363 
    364 ### <span id="Fonts">Fonts</span> ###
    365 
    366 There are many details for dealing with fonts, so this document will
    367 only talk about some of the more important ones. A couple short
    368 details:
    369 
    370 *   We cant assume that an arbitrary font will be available at PDF view
    371     time, so we embed all fonts in accordance with modern PDF
    372     guidelines.
    373 *   Most fonts these days are TrueType fonts, so this is where most of
    374     the effort has been concentrated.
    375 *   Because Skia may only be given a glyph-id encoding of the text to
    376     render and there is no perfect way to reverse the encoding, the
    377     PDF backend always uses the glyph-id encoding of the text.
    378 
    379 #### *Type1/Type3 fonts* ####
    380 
    381 Linux supports Type1 fonts, but Windows and Mac seem to lack the
    382 functionality required to extract the required information from the
    383 font without parsing the font file. When a non TrueType font is used
    384 any any platform (except for Type1 on Linux), it is encoded as a Type3
    385 font. In this context, a Type3 font is an array of form x-objects
    386 (content streams) that draw each glyph of the font. No hinting or
    387 kerning information is included in a Type3 font, just the shape of
    388 each glyph. Any font that has the do-not embed copy protection bit set
    389 will also get embedded as a Type3 font. From what I understand, shapes
    390 are not copyrightable, but programs are, so by stripping all the
    391 programmatic information and only embedding the shape of the glyphs we
    392 are honoring the do-not embed bit as much as required by law.
    393 
    394 PDF only supports an 8-bit encoding for Type1 or Type3 fonts. However,
    395 they can contain more than 256 glyphs. The PDF backend handles this by
    396 segmenting the glyphs into groups of 255 (glyph id 0 is always the
    397 unknown glyph) and presenting the font as multiple fonts, each with up
    398 to 255 glyphs.
    399 
    400 #### *Font subsetting* ####
    401 
    402 Many fonts, especially fonts with CJK support are fairly large, so it
    403 is desirable to subset them. Chrome uses the SFNTLY package to provide
    404 subsetting support to Skia for TrueType fonts.
    405 
    406 ### <span id="Shaders">Shaders</span> ###
    407 
    408 Skia has two types of predefined shaders, image shaders and gradient
    409 shaders. In both cases, shaders are effectively positioned absolutely,
    410 so the initial position and bounds of where they are visible is part
    411 of the immutable state of the shader object. Each of the Skias tile
    412 modes needs to be considered and handled explicitly. The image shader
    413 we generate will be tiled, so tiling is handled by default. To support
    414 mirroring, we draw the image, reversed, on the appropriate axis, or on
    415 both axes plus a fourth in the vacant quadrant. For clamp mode, we
    416 extract the pixels along the appropriate edge and stretch the single
    417 pixel wide/long image to fill the bounds. For both x and y in clamp
    418 mode, we fill the corners with a rectangle of the appropriate
    419 color. The composed shader is then rotated or scaled as appropriate
    420 for the request.
    421 
    422 Gradient shaders are handled purely mathematically. First, the matrix
    423 is transformed so that specific points in the requested gradient are
    424 at pre-defined locations, for example, the linear distance of the
    425 gradient is always normalized to one. Then, a type 4 PDF function is
    426 created that achieves the desired gradient. A type 4 function is a
    427 function defined by a resticted postscript language. The generated
    428 functions clamp at the edges so if the desired tiling mode is tile or
    429 mirror, we hav to add a bit more postscript code to map any input
    430 parameter into the 0-1 range appropriately. The code to generate the
    431 postscript code is somewhat obtuse, since it is trying to generate
    432 optimized (for space) postscript code, but there is a significant
    433 number of comments to explain the intent.
    434 
    435 ### <span id="Xfer_modes">Xfer modes</span> ###
    436 
    437 PDF supports some of the xfer modes used in Skia directly. For those,
    438 it is simply a matter of setting the blend mode in the graphic state
    439 to the appropriate value (Normal/SrcOver, Multiply, Screen, Overlay,
    440 Darken, Lighten, !ColorDOdge, ColorBurn, HardLight, SoftLight,
    441 Difference, Exclusion). Aside from the standard SrcOver mode, PDF does
    442 not directly support the porter-duff xfer modes though. Most of them
    443 (Clear, SrcMode, DstMode, DstOver, SrcIn, DstIn, SrcOut, DstOut) can
    444 be emulated by various means, mostly by creating form x-objects out of
    445 part of the content and drawing it with a another form x-object as a
    446 mask. I have not figured out how to emulate the following modes:
    447 SrcATop, DstATop, Xor, Plus.
    448 
    449 At the time of writing [2012-06-25], I have a [CL outstanding to fix a
    450 misunderstanding I had about the meaning of some of the emulated
    451 modes](https://codereview.appspot.com/4631078/).
    452 I will describe the system with this change applied.
    453 
    454 First, a bit of terminology and definition. When drawing something
    455 with an emulated xfer mode, whats already drawn to the device is
    456 called the destination or Dst, and whats about to be drawn is the
    457 source or Src. Src (and Dst) can have regions where it is transparent
    458 (alpha equals zero), but it also has an inherent shape. For most kinds
    459 of drawn objects, the shape is the same as where alpha is not
    460 zero. However, for things like images and layers, the shape is the
    461 bounds of the item, not where the alpha is non-zero. For example, a
    462 10x10 image, that is transparent except for a 1x1 dot in the center
    463 has a shape that is 10x10. The xfermodes gm test demonstrates the
    464 interaction between shape and alpha in combination with the port-duff
    465 xfer modes.
    466 
    467 The clear xfer mode removes any part of Dst that is within Srcs
    468 shape. This is accomplished by bundling the current content of the
    469 device (Dst) into a single entity and then drawing that with the
    470 inverse of Srcs shape used as a mask (we want Dst where Src
    471 isnt). The implementation of that takes a couple more steps. You may
    472 have to refer back to [the content stream section](#Generating_a_content_stream). For any draw call, a
    473 ContentEntry is created through a method called
    474 SkPDFDevice::setUpContentEntry(). This method examines the xfer modes
    475 in effect for that drawing operation and if it is an xfer mode that
    476 needs emulation, it creates a form x-object from the device,
    477 i.e. creates Dst, and stores it away for later use. This also clears
    478 all of that existing ContentEntry's on that device. The drawing
    479 operation is then allowed to proceed as normal (in most cases, see
    480 note about shape below), but into the now empty device. Then, when the
    481 drawing operation in done, a complementary method is
    482 called,SkPDFDevice::finishContentEntry(), which takes action if the
    483 current xfer mode is emulated. In the case of Clear, it packages what
    484 was just drawn into another form x-object, and then uses the Src form
    485 x-object, an invert function, and the Dst form x-object to draw Dst
    486 with the inverse shape of Src as a mask. This works well when the
    487 shape of Src is the same as the opaque part of the drawing, since PDF
    488 uses the alpha channel of the mask form x-object to do masking. When
    489 shape doesnt match the alpha channel, additional action is
    490 required. The drawing routines where shape and alpha dont match, set
    491 state to indicate the shape (always rectangular), which
    492 finishContentEntry uses. The clear xfer mode is a special case; if
    493 shape is needed, then Src isnt used, so there is code to not bother
    494 drawing Src if shape is required and the xfer mode is clear.
    495 
    496 SrcMode is clear plus Src being drawn afterward. DstMode simply omits
    497 drawing Src. DstOver is the same as SrcOver with Src and Dst swapped -
    498 this is accomplished by inserting the new ContentEntry at the
    499 beginning of the list of ContentEntrys in setUpContentEntry instead
    500 of at the end. SrcIn, SrcOut, DstIn, DstOut are similar to each, the
    501 difference being an inverted or non-inverted mask and swapping Src and
    502 Dst (or not). SrcIn is SrcMode with Src drawn with Dst as a
    503 mask. SrcOut is like SrcMode, but with Src drawn with an inverted Dst
    504 as a mask. DstIn is SrcMode with Dst drawn with Src as a
    505 mask. Finally, DstOut is SrcMode with Dst draw with an inverted Src as
    506 a mask.
    507 
    508 <span id="Known_issues">Known issues</span>
    509 -------------------------------------------
    510 
    511 *   [issue 237](https://bug.skia.org/237)
    512     SkMaskFilter is not supported.
    513 *   [issue 238](https://bug.skia.org/238)
    514     SkColorFilter is not supported.
    515 *   [issue 249](https://bug.skia.org/249)
    516     SrcAtop Xor, and Plus xfer modes are not supported.
    517 *   [issue 240](https://bug.skia.org/240)
    518     drawVerticies is not implemented.
    519 *   [issue 244](https://bug.skia.org/244)
    520     Mostly, only TTF fonts are *directly* supported.
    521     (User metrics show that almost all fonts are truetype.)
    522 *   [issue 260](https://bug.skia.org/260)
    523     Page rotation is accomplished by specifying a different
    524     size page instead of including the appropriate rotation
    525     annotation.
    526 
    527 * * *
    528 
    529