OLD | NEW |
---|---|
1 PDF Theory of Operation | 1 PDF Theory of Operation |
2 ======================= | 2 ======================= |
3 | 3 |
4 <!-- | 4 <!-- |
5 PRE-GIT DOCUMENT VERSION HISTORY | 5 PRE-GIT DOCUMENT VERSION HISTORY |
6 2012-06-25 Steve VanDeBogart | 6 2012-06-25 Steve VanDeBogart |
7 * Original version | 7 * Original version |
8 2015-01-14 Hal Canary. | 8 2015-01-14 Hal Canary. |
9 * Add section "Using the PDF backend" | 9 * Add section "Using the PDF backend" |
10 * Markdown formatting | 10 * Markdown formatting |
(...skipping 12 matching lines...) Expand all Loading... | |
23 | 23 |
24 ### Contents ### | 24 ### Contents ### |
25 | 25 |
26 * [Typical usage of the PDF backend](#Typical_usage_of_the_PDF_backend) | 26 * [Typical usage of the PDF backend](#Typical_usage_of_the_PDF_backend) |
27 * [PDF Objects and Document Structure](#PDF_Objects_and_Document_Structure) | 27 * [PDF Objects and Document Structure](#PDF_Objects_and_Document_Structure) |
28 * [PDF drawing](#PDF_drawing) | 28 * [PDF drawing](#PDF_drawing) |
29 * [Interned objects](#Interned_objects) | 29 * [Interned objects](#Interned_objects) |
30 * [Graphic States](#Graphic_States) | 30 * [Graphic States](#Graphic_States) |
31 * [Clip and Transform](#Clip_and_Transform) | 31 * [Clip and Transform](#Clip_and_Transform) |
32 * [Generating a content stream](#Generating_a_content_stream) | 32 * [Generating a content stream](#Generating_a_content_stream) |
33 * [Margins and content area](#Margins_and_content_area) | |
34 * [Drawing details](#Drawing_details) | 33 * [Drawing details](#Drawing_details) |
35 + [Layers](#Layers) | 34 + [Layers](#Layers) |
36 + [Fonts](#Fonts) | 35 + [Fonts](#Fonts) |
37 + [Shaders](#Shaders) | 36 + [Shaders](#Shaders) |
38 + [Xfer modes](#Xfer_modes) | 37 + [Xfer modes](#Xfer_modes) |
39 * [Known issues](#Known_issues) | 38 * [Known issues](#Known_issues) |
40 | 39 |
41 <a name="Typical_usage_of_the_PDF_backend"></a> | 40 <a name="Typical_usage_of_the_PDF_backend"></a> |
42 Typical usage of the PDF backend | 41 Typical usage of the PDF backend |
43 -------------------------------- | 42 -------------------------------- |
44 | 43 |
45 SkPDFDevice is the main interface to the PDF backend. This child of | 44 SkPDFDevice is the main interface to the PDF backend. This child of |
46 SkDevice can be set on an SkCanvas and drawn to. It requires no more | 45 SkDevice can be set on an SkPDFCanvas and drawn to. Once drawing is |
47 care and feeding than SkDevice. Once drawing is complete, the device | 46 complete, the device's content and resouces are added to the |
48 should be added to an SkPDFDocument as a page of the desired PDF. A | 47 SkPDFDocument that owns the device. A new SkPDFDevice should be |
49 new SkPDFDevice should be created for each page desired in the | 48 created for each page or layer desired in the document. After all the |
50 document. After all the pages have been added to the document, | 49 pages have been added to the document, `SkPDFDocument::onClose()` is |
51 `SkPDFDocument::emitPDF()` can be called to get a PDF file. One of the | 50 called to finish the PDF file. |
52 special features of the PDF backend is that the same device can be | |
53 added to multiple documents. This for example, would let you generate | |
54 a PDF with the single page you just drew as well as adding it to a | |
55 longer document with a bunch of other pages. | |
56 | |
57 <!--?prettify lang=cc?--> | |
58 | |
59 SkPDFCanon canon; | |
60 SkAutoUnref<SkPDFDevice> pdfDevice( | |
61 SkPDFDevice::Create(SkISize::Make(width, height), 72.0f, &canon)); | |
62 | |
63 SkCanvas canvas(pdfDevice); | |
64 draw_content(&canvas); | |
65 | |
66 SkPDFDocument doc; | |
67 doc.appendPage(dev); | |
68 doc.emitPDF(&pdf_stream); | |
69 | 51 |
70 <a name="PDF_Objects_and_Document_Structure"></a> | 52 <a name="PDF_Objects_and_Document_Structure"></a> |
71 PDF Objects and Document Structure | 53 PDF Objects and Document Structure |
72 ---------------------------------- | 54 ---------------------------------- |
73 | 55 |
74  | 56  |
75 | 57 |
76 **Background**: The PDF file format has a header, a set of objects and | 58 **Background**: The PDF file format has a header, a set of objects and |
77 then a footer that contains a table of contents for all of the objects | 59 then a footer that contains a table of contents for all of the objects |
78 in the document (the cross-reference table). The table of contents | 60 in the document (the cross-reference table). The table of contents |
79 lists the specific byte position for each object. The objects may have | 61 lists the specific byte position for each object. The objects may have |
80 references to other objects and the ASCII size of those references is | 62 references to other objects and the ASCII size of those references is |
81 dependent on the object number assigned to the referenced object; | 63 dependent on the object number assigned to the referenced object; |
82 therefore we can’t calculate the table of contents until the size of | 64 therefore we can’t calculate the table of contents until the size of |
83 objects is known, which requires assignment of object | 65 objects is known, which requires assignment of object numbers. The |
84 numbers. | 66 document uses SkWStream::bytesWritten() to query the offsets of each |
67 object and build the cross-reference table. | |
85 | 68 |
86 Furthermore, PDF files can support a *linearized* mode, where objects | 69 Furthermore, PDF files can support a *linearized* mode, where objects |
87 are in a specific order so that pdf-viewers can more easily retrieve | 70 are in a specific order so that pdf-viewers can more easily retrieve |
88 just the objects they need to display a specific page, i.e. by | 71 just the objects they need to display a specific page, i.e. by |
89 byte-range requests over the web. Linearization also requires that all | 72 byte-range requests over the web. Linearization also requires that all |
90 objects used or referenced on the first page of the PDF have object | 73 objects used or referenced on the first page of the PDF have object |
91 numbers before the rest of the objects. Consequently, before | 74 numbers before the rest of the objects. Consequently, before |
92 generating a linearized PDF, all objects, their sizes, and object | 75 generating a linearized PDF, all objects, their sizes, and object |
93 references must be known. Skia has no plans to implement linearized | 76 references must be known. Skia has no plans to implement linearized |
94 PDFs. | 77 PDFs. |
95 | 78 |
96 <!-- <del>At this point, linearized PDFs are not generated. The | |
97 framework to generate them is in place, but the final bits of code | |
98 have not been written.</del> --> | |
99 | |
100 %PDF-1.4 | 79 %PDF-1.4 |
101 …objects... | 80 …objects... |
102 xref | 81 xref |
103 0 31 % Total number of entries in the table of contents. | 82 0 31 % Total number of entries in the table of contents. |
104 0000000000 65535 f | 83 0000000000 65535 f |
105 0000210343 00000 n | 84 0000210343 00000 n |
106 … | 85 … |
107 0000117055 00000 n | 86 0000117055 00000 n |
108 trailer | 87 trailer |
109 <</Size 31 /Root 1 0 R>> | 88 <</Size 31 /Root 1 0 R>> |
110 startxref | 89 startxref |
111 210399 % Byte offset to the start of the table of contents. | 90 210399 % Byte offset to the start of the table of contents. |
112 %%EOF | 91 %%EOF |
113 | 92 |
114 The class SkPDFCatalog and the virtual class SkPDFObject are used to | 93 The class SkPDFObjNumMap and the virtual class SkPDFObject are used to |
115 manage the needs of the file format. Any object that will represent a | 94 manage the needs of the file format. Any object that will represent a |
116 PDF object must inherit from SkPDFObject and implement the methods to | 95 PDF object must inherit from SkPDFObject and implement the methods to |
117 generate the binary representation and report any other SkPDFObjects | 96 generate the binary representation and report any other SkPDFObjects |
118 used as resources. SkPDFTypes.h defines most of the basic PDF objects | 97 used as resources. SkPDFTypes.h defines most of the basic PDF objects |
tomhudson
2016/09/01 19:11:58
Nit: object shouldn't be plural here.
hal.canary
2016/09/28 18:18:28
Done.
| |
119 types: bool, int, scalar, string, name, array, dictionary, and object | 98 types: bool, int, scalar, string, name, array, dictionary, and stream. |
120 reference. The stream type is defined in SkPDFStream.h. A stream is a | 99 A stream is a |
121 dictionary containing at least a Length entry followed by the data of | 100 dictionary containing at least a Length entry followed by the data of |
122 the stream. All of these types except the stream type can be used in | 101 the stream. All of these types except the stream type can be used in |
123 both a direct and an indirect fashion, i.e. an array can have an int | 102 both a direct and an indirect fashion, i.e. an array can have an int |
tomhudson
2016/09/01 19:11:58
Nit: this isn't clear at all. Most of the rest of
hal.canary
2016/09/28 18:18:28
Acknowledged.
| |
124 or a dictionary as an inline entry, which does not require an object | 103 or a dictionary as an inline entry, which does not require an object |
125 number. The stream type, cannot be inlined and must be referred to | 104 number. The stream type, cannot be inlined and must be referred to |
126 with an object reference. Most of the time, other objects types can be | 105 with an object reference. Most of the time, other objects types can be |
127 referred to with an object reference, but there are specific rules in | 106 referred to with an object reference, but there are specific rules in |
128 the PDF specification that requires an inline reference in some place | 107 the PDF specification that requires an inline reference in some place |
129 or an indirect reference in other places. All indirect objects must | 108 or an indirect reference in other places. All indirect objects must |
130 have an object number assigned. | 109 have an object number assigned. |
131 | 110 |
132 * **bools**: `true` `false` | 111 * **bools**: `true` `false` |
133 * **ints**: `42` `0` `-1` | 112 * **ints**: `42` `0` `-1` |
134 * **scalars**: `0.001` | 113 * **scalars**: `0.001` |
135 * **strings**: `(strings are in parentheses or byte encoded)` `<74657374>` | 114 * **strings**: `(strings are in parentheses or byte encoded)` `<74657374>` |
136 * **name**: `/Name` `/Name#20with#20spaces` | 115 * **name**: `/Name` `/Name#20with#20spaces` |
137 * **array**: `[/Foo 42 (arrays can contain multiple types)]` | 116 * **array**: `[/Foo 42 (arrays can contain multiple types)]` |
138 * **dictionary**: `<</Key1 (value1) /key2 42>>` | 117 * **dictionary**: `<</Key1 (value1) /key2 42>>` |
139 * **indirect object**: | 118 * **indirect object**: |
140 `5 0 obj | 119 `5 0 obj |
141 (An indirect string. Indirect objects have an object number and a | 120 (An indirect string. Indirect objects have an object number and a |
142 generation number, Skia always uses generation 0 objects) | 121 generation number, Skia always uses generation 0 objects) |
143 endobj` | 122 endobj` |
144 * **object reference**: `5 0 R` | 123 * **object reference**: `5 0 R` |
145 * **stream**: `<</Length 56>> | 124 * **stream**: `<</Length 56>> |
146 stream | 125 stream |
147 ...stream contents can be arbitrary, including binary... | 126 ...stream contents can be arbitrary, including binary... |
148 endstream` | 127 endstream` |
149 | 128 |
150 The PDF backend requires all indirect objects used in a PDF to be | 129 The PDF backend requires all indirect objects used in a PDF to be |
151 added to the SkPDFCatalog of the SkPDFDocument. The catalog is | 130 added to the SkPDFObjNumMap of the SkPDFDocument. The catalog is |
152 responsible for assigning object numbers and generating the table of | 131 responsible for assigning object numbers and generating the table of |
153 contents required at the end of PDF files. In some sense, generating a | 132 contents required at the end of PDF files. In some sense, generating a |
154 PDF is a three step process. In the first step all the objects and | 133 PDF is a three step process. In the first step all the objects and |
155 references among them are created (mostly done by SkPDFDevice). In the | 134 references among them are created (mostly done by SkPDFDevice). In the |
156 second step, object numbers are assigned and SkPDFCatalog is informed | 135 second step, SkPDFObjNumMap assigns and remembers object numbers. |
157 of the file offset of each indirect object. Finally, in the third | 136 Finally, in the third |
158 step, the header is printed, each object is printed, and then the | 137 step, the header is printed, each object is printed, and then the |
159 table of contents and trailer are printed. SkPDFDocument takes care of | 138 table of contents and trailer are printed. SkPDFDocument takes care of |
160 collecting all the objects from the various SkPDFDevice instances, | 139 collecting all the objects from the various SkPDFDevice instances, |
161 adding them to an SkPDFCatalog, iterating through the objects once to | 140 adding them to an SkPDFObjNumMap, iterating through the objects once to |
162 set their file positions, and iterating again to generate the final | 141 set their file positions, and iterating again to generate the final |
163 PDF. | 142 PDF. |
164 | 143 |
144 As an optimization, many leaf nodes in the direct graph of indirect | |
145 objects can be assigned object numbers and serialized early. | |
146 | |
165 %PDF-1.4 | 147 %PDF-1.4 |
166 2 0 obj << | 148 2 0 obj << |
167 /Type /Catalog | 149 /Type /Catalog |
168 /Pages 1 0 R | 150 /Pages 1 0 R |
169 >> | 151 >> |
170 endobj | 152 endobj |
171 3 0 obj << | 153 3 0 obj << |
172 /Type /Page | 154 /Type /Page |
173 /Parent 1 0 R | 155 /Parent 1 0 R |
174 /Resources <> | 156 /Resources <> |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
247 Interned objects | 229 Interned objects |
248 ---------------- | 230 ---------------- |
249 | 231 |
250 There are a number of high level PDF objects (like fonts, graphic | 232 There are a number of high level PDF objects (like fonts, graphic |
251 states, etc) that are likely to be referenced multiple times in a | 233 states, etc) that are likely to be referenced multiple times in a |
252 single PDF. To ensure that there is only one copy of each object | 234 single PDF. To ensure that there is only one copy of each object |
253 instance these objects an implemented with an | 235 instance these objects an implemented with an |
254 [interning pattern](http://en.wikipedia.org/wiki/String_interning). | 236 [interning pattern](http://en.wikipedia.org/wiki/String_interning). |
255 As such, the classes representing these objects (like | 237 As such, the classes representing these objects (like |
256 SkPDFGraphicState) have private constructors and static methods to | 238 SkPDFGraphicState) have private constructors and static methods to |
257 retrieve an instance of the class. Internally, the class has a list of | 239 retrieve an instance of the class. |
258 unique instances that it consults before returning a new instance of | 240 |
259 the class. If the requested instance already exists, the existing one | 241 The SkPDFCanon object owns the interned objects. For obvious reasons, |
260 is returned. For obvious reasons, the returned instance should not be | 242 the returned instance should not be modified. A mechanism to ensure |
261 modified. A mechanism to ensure that interned classes are immutable is | 243 that interned classes are immutable is needed. See [issue |
262 needed. See [issue 2683](https://bug.skia.org/2683). | 244 2683](https://bug.skia.org/2683). |
263 | 245 |
264 <a name="Graphic_States"></a> | 246 <a name="Graphic_States"></a> |
265 Graphic States | 247 Graphic States |
266 -------------- | 248 -------------- |
267 | 249 |
268 PDF has a number of parameters that affect how things are drawn. The | 250 PDF has a number of parameters that affect how things are drawn. The |
269 ones that correspond to drawing options in Skia are: color, alpha, | 251 ones that correspond to drawing options in Skia are: color, alpha, |
270 line cap, line join type, line width, miter limit, and xfer/blend mode | 252 line cap, line join type, line width, miter limit, and xfer/blend mode |
271 (see later section for xfer modes). With the exception of color, these | 253 (see later section for xfer modes). With the exception of color, these |
272 can all be specified in a single pdf object, represented by the | 254 can all be specified in a single pdf object, represented by the |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
325 SkPDFGraphicState (interned) with the rest (color, font size, etc) | 307 SkPDFGraphicState (interned) with the rest (color, font size, etc) |
326 explicitly stored in the ContentEntry. After populating the | 308 explicitly stored in the ContentEntry. After populating the |
327 ContentEntry with all the relevant context, it is compared to the the | 309 ContentEntry with all the relevant context, it is compared to the the |
328 most recently used ContentEntry. If the context matches, then the | 310 most recently used ContentEntry. If the context matches, then the |
329 previous one is appended to instead of using the new one. In either | 311 previous one is appended to instead of using the new one. In either |
330 case, with the context populated into the ContentEntry, the | 312 case, with the context populated into the ContentEntry, the |
331 appropriate draw call is allowed to append to the content stream | 313 appropriate draw call is allowed to append to the content stream |
332 snippet in the ContentEntry to affect the core of the drawing call, | 314 snippet in the ContentEntry to affect the core of the drawing call, |
333 i.e. drawing a shape, an image, text, etc. | 315 i.e. drawing a shape, an image, text, etc. |
334 | 316 |
335 When all drawing is complete, SkPDFDocument::emitPDF() will call | 317 When all drawing is complete, SkPDFDocument::onEndPage() will call |
336 SkPDFDevice::content() to request the complete content stream for the | 318 SkPDFDevice::content() to request the complete content stream for the |
337 page. The first thing done is to apply the initial transform specified | 319 page. The first thing done is to apply the initial transform specified |
338 in part in the constructor, this transform takes care of changing the | 320 in part in the constructor, this transform takes care of changing the |
339 coordinate space from an origin in the lower left (PDF default) to the | 321 coordinate space from an origin in the lower left (PDF default) to the |
340 upper left (Skia default) as well as any translation or scaling | 322 upper left (Skia default) as well as any translation or scaling |
341 requested by the user (i.e. to achieve a margin or scale the | 323 requested by the user (i.e. to achieve a margin or scale the |
342 canvas). Next (well almost next, see the next section), a clip is | 324 canvas). Next (well almost next, see the next section), a clip is |
343 applied to restrict drawing to the content area (the part of the page | 325 applied to restrict drawing to the content area (the part of the page |
344 inside the margins) of the page. Then, each ContentEntry is applied to | 326 inside the margins) of the page. Then, each ContentEntry is applied to |
345 the content stream with the help of a helper class, GraphicStackState, | 327 the content stream with the help of a helper class, GraphicStackState, |
346 which tracks the state of the PDF graphics stack and optimizes the | 328 which tracks the state of the PDF graphics stack and optimizes the |
347 output. For each ContentEntry, commands are emitted to the final | 329 output. For each ContentEntry, commands are emitted to the final |
348 content entry to update the clip from its current state to the state | 330 content entry to update the clip from its current state to the state |
349 specified in the ContentEntry, similarly the Matrix and drawing state | 331 specified in the ContentEntry, similarly the Matrix and drawing state |
350 (color, line joins, etc) are updated, then the content entry fragment | 332 (color, line joins, etc) are updated, then the content entry fragment |
351 (the actual drawing operation) is appended. | 333 (the actual drawing operation) is appended. |
352 | 334 |
353 <a name="Margins_and_content_area"></a> | |
354 Margins and content area | |
355 ------------------------ | |
356 | |
357 The above procedure does not permit drawing in the margins. This is | |
358 done in order to contain any rendering problems in WebKit. In order to | |
359 support headers and footers, which are drawn in the margin, a second | |
360 set of ContentEntry’s are maintained. The | |
361 methodSkPDFDevice::setDrawingArea() selects which set of | |
362 ContentEntry’s are drawn into. Then, in the SkPDFDevice::content() | |
363 method, just before the clip to the content area is applied the margin | |
364 ContentEntry's are played back. | |
365 | |
366 <!-- TODO(halcanary): update this documentation. --> | |
367 | |
368 <a name="Drawing_details"></a> | 335 <a name="Drawing_details"></a> |
369 Drawing details | 336 Drawing details |
370 --------------- | 337 --------------- |
371 | 338 |
372 Certain objects have specific properties that need to be dealt | 339 Certain objects have specific properties that need to be dealt |
373 with. Images, layers (see below), and fonts assume the standard PDF | 340 with. Images, layers (see below), and fonts assume the standard PDF |
374 coordinate system, so we have to undo any flip to the Skia coordinate | 341 coordinate system, so we have to undo any flip to the Skia coordinate |
375 system before drawing these entities. We don’t currently support | 342 system before drawing these entities. We don’t currently support |
376 inverted paths, so filling an inverted path will give the wrong result | 343 inverted paths, so filling an inverted path will give the wrong result |
377 ([issue 241](https://bug.skia.org/241)). PDF doesn’t draw zero length | 344 ([issue 241](https://bug.skia.org/241)). PDF doesn’t draw zero length |
378 lines that have butt of square caps, so that is emulated. | 345 lines that have butt of square caps, so that is emulated. |
379 | 346 |
380 <a name="Layers"></a> | 347 <a name="Layers"></a> |
381 ### Layers ### | 348 ### Layers ### |
382 | 349 |
383 PDF has a higher level object called a form x-object (form external | 350 PDF has a higher level object called a form x-object (form external |
384 object) that is basically a PDF page, with resources and a content | 351 object) that is basically a PDF page, with resources and a content |
385 stream, but can be transformed and drawn on an existing page. This is | 352 stream, but can be transformed and drawn on an existing page. This is |
386 used to implement layers. SkDevice has a method, | 353 used to implement layers. SkPDFDevice has a method, |
387 createFormXObjectFromDevice, which uses the SkPDFDevice::content() | 354 makeFormXObjectFromDevice(), which uses the SkPDFDevice::content() |
388 method to construct a form x-object from the the | 355 method to construct a form x-object from the the |
389 device. SkPDFDevice::drawDevice() works by creating a form x-object of | 356 device. SkPDFDevice::drawDevice() works by creating a form x-object of |
390 the passed device and then drawing that form x-object in the root | 357 the passed device and then drawing that form x-object in the root |
391 device. There are a couple things to be aware of in this process. As | 358 device. There are a couple things to be aware of in this process. As |
392 noted previously, we have to be aware of any flip to the coordinate | 359 noted previously, we have to be aware of any flip to the coordinate |
393 system - flipping it an even number of times will lead to the wrong | 360 system - flipping it an even number of times will lead to the wrong |
394 result unless it is corrected for. The SkClipStack passed to drawing | 361 result unless it is corrected for. The SkClipStack passed to drawing |
395 commands includes the entire clip stack, including the clipping | 362 commands includes the entire clip stack, including the clipping |
396 operations done on the base layer. Since the form x-object will be | 363 operations done on the base layer. Since the form x-object will be |
397 drawn as a single operation onto the base layer, we can assume that | 364 drawn as a single operation onto the base layer, we can assume that |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
432 PDF only supports an 8-bit encoding for Type1 or Type3 fonts. However, | 399 PDF only supports an 8-bit encoding for Type1 or Type3 fonts. However, |
433 they can contain more than 256 glyphs. The PDF backend handles this by | 400 they can contain more than 256 glyphs. The PDF backend handles this by |
434 segmenting the glyphs into groups of 255 (glyph id 0 is always the | 401 segmenting the glyphs into groups of 255 (glyph id 0 is always the |
435 unknown glyph) and presenting the font as multiple fonts, each with up | 402 unknown glyph) and presenting the font as multiple fonts, each with up |
436 to 255 glyphs. | 403 to 255 glyphs. |
437 | 404 |
438 #### *Font subsetting* #### | 405 #### *Font subsetting* #### |
439 | 406 |
440 Many fonts, especially fonts with CJK support are fairly large, so it | 407 Many fonts, especially fonts with CJK support are fairly large, so it |
441 is desirable to subset them. Chrome uses the SFNTLY package to provide | 408 is desirable to subset them. Chrome uses the SFNTLY package to provide |
442 subsetting support to Skia for TrueType fonts. However, there is a | 409 subsetting support to Skia for TrueType fonts. |
443 conflict between font subsetting and interned objects. If the object | |
444 is immutable, how can it be subsetted? This conflict is resolved by | |
445 using a substitution mechanism in SkPDFCatalog. Font objects are still | |
446 interned, but the interned objects aren’t internally | |
447 populated. Subsetting starts while drawing text to an SkPDFDevice; a | |
448 bit set indicating which glyphs have been used is maintained. Later, | |
449 when SkPDFDocument::emitPDF() is rendering the PDF, it queries each | |
450 device (each page) for the set of fonts used and the glyphs used from | |
451 each font and combines the information. It then asks the interned | |
452 (unpopulated) font objects to create a populated instance with the | |
453 calculated subset of the font - this instance is not interned. The | |
454 subsetted instance is then set as a substitute for the interned font | |
455 object in the SkPDFCatalog. All future references to those fonts | |
456 within that document will refer to the subsetted instances, resulting | |
457 in a final PDF with exactly one instance of each used font that | |
458 includes only the glyphs used. | |
459 | |
460 The substitution mechanism is a little complicated, but is needed to | |
461 support the use case of an SkPDFDevice being added to multiple | |
462 documents. If fonts were subsetted in-situ, concurrent PDF generation | |
463 would have to be explicitly handled. Instead, by giving each document | |
464 its own subsetted instance, there is no need to worry about concurrent | |
465 PDF generation. The substitution method is also used to support | |
466 optional stream compression. A stream can used by different documents | |
467 in both a compressed and uncompressed form, leading to the same | |
468 potential difficulties faced by the concurrent font use case. | |
469 | 410 |
470 <a name="Shaders"></a> | 411 <a name="Shaders"></a> |
471 ### Shaders ### | 412 ### Shaders ### |
472 | 413 |
473 Skia has two types of predefined shaders, image shaders and gradient | 414 Skia has two types of predefined shaders, image shaders and gradient |
474 shaders. In both cases, shaders are effectively positioned absolutely, | 415 shaders. In both cases, shaders are effectively positioned absolutely, |
475 so the initial position and bounds of where they are visible is part | 416 so the initial position and bounds of where they are visible is part |
476 of the immutable state of the shader object. Each of the Skia’s tile | 417 of the immutable state of the shader object. Each of the Skia’s tile |
477 modes needs to be considered and handled explicitly. The image shader | 418 modes needs to be considered and handled explicitly. The image shader |
478 we generate will be tiled, so tiling is handled by default. To support | 419 we generate will be tiled, so tiling is handled by default. To support |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
568 Dst (or not). SrcIn is SrcMode with Src drawn with Dst as a | 509 Dst (or not). SrcIn is SrcMode with Src drawn with Dst as a |
569 mask. SrcOut is like SrcMode, but with Src drawn with an inverted Dst | 510 mask. SrcOut is like SrcMode, but with Src drawn with an inverted Dst |
570 as a mask. DstIn is SrcMode with Dst drawn with Src as a | 511 as a mask. DstIn is SrcMode with Dst drawn with Src as a |
571 mask. Finally, DstOut is SrcMode with Dst draw with an inverted Src as | 512 mask. Finally, DstOut is SrcMode with Dst draw with an inverted Src as |
572 a mask. | 513 a mask. |
573 | 514 |
574 <a name="Known_issues"></a> | 515 <a name="Known_issues"></a> |
575 Known issues | 516 Known issues |
576 ------------ | 517 ------------ |
577 | 518 |
578 * [issue 241](https://bug.skia.org/241) | |
579 As previously noted, a boolean geometry library | |
580 would improve clip fidelity in some places, add supported for | |
581 inverted fill types, as well as simplify code. | |
582 This is fixed, but behind a flag until path ops is production ready. | |
583 * [issue 237](https://bug.skia.org/237) | 519 * [issue 237](https://bug.skia.org/237) |
584 SkMaskFilter is not supported. | 520 SkMaskFilter is not supported. |
585 * [issue 238](https://bug.skia.org/238) | 521 * [issue 238](https://bug.skia.org/238) |
586 SkColorFilter is not supported. | 522 SkColorFilter is not supported. |
587 * [issue 249](https://bug.skia.org/249) | 523 * [issue 249](https://bug.skia.org/249) |
588 SrcAtop Xor, and Plus xfer modes are not supported. | 524 SrcAtop Xor, and Plus xfer modes are not supported. |
589 * [issue 240](https://bug.skia.org/240) | 525 * [issue 240](https://bug.skia.org/240) |
590 drawVerticies is not implemented. | 526 drawVerticies is not implemented. |
591 * [issue 244](https://bug.skia.org/244) | 527 * [issue 244](https://bug.skia.org/244) |
592 Mostly, only TTF fonts are directly supported. (User metrics | 528 Mostly, only TTF fonts are directly supported. (User metrics |
tomhudson
2016/09/01 19:11:58
Nit: mostly only?
hal.canary
2016/09/28 18:18:28
Acknowledged.
| |
593 show that almost all fonts are truetype. | 529 show that almost all fonts are truetype.) |
594 * [issue 260](https://bug.skia.org/260) | 530 * [issue 260](https://bug.skia.org/260) |
595 Page rotation is accomplished by specifying a different | 531 Page rotation is accomplished by specifying a different |
596 size page instead of including the appropriate rotation | 532 size page instead of including the appropriate rotation |
597 annotation. | 533 annotation. |
598 | 534 |
599 * * * | 535 * * * |
600 | 536 |
OLD | NEW |