Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(18)

Side by Side Diff: site/dev/design/pdftheory.md

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

Powered by Google App Engine
This is Rietveld 408576698