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

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

Issue 2295373002: documentation: update PDF design doc (Closed)
Patch Set: final Created 4 years, 2 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
« no previous file with comments | « no previous file | 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
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
11 --> 11 -->
12 12
13 13
14 To make use of Skia's PDF backend, see 14 Internally, SkPDFDocument and SkPDFDevice represents PDF documents and
15 [Using Skia's PDF Backend](../../user/sample/pdf). 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.**
16 18
17 Internally, Skia uses SkPDFDocument and SkPDFDevice to represent PDF 19 See [Using Skia's PDF Backend](../../user/sample/pdf) to find out how
18 documents and pages. This document describes how the backend 20 to use SkPDF as a client calling Skia's public API.
19 operates, but **these interfaces are not part of the public API and
20 are subject to perpetual change.**
21 21
22 * * * 22 * * *
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
42 Typical usage of the PDF backend 41 <span id="Typical_usage_of_the_PDF_backend">Typical usage of the PDF backend</sp an>
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 to
47 care and feeding than SkDevice. Once drawing is complete, the device 46 the canvas is complete (SkDocument::onEndPage() is called), the
48 should be added to an SkPDFDocument as a page of the desired PDF. A 47 device's content and resouces are added to the SkPDFDocument that owns
49 new SkPDFDevice should be created for each page desired in the 48 the device. A new SkPDFDevice should be created for each page or
50 document. After all the pages have been added to the document, 49 layer desired in the document. After all the pages have been added to
51 `SkPDFDocument::emitPDF()` can be called to get a PDF file. One of the 50 the document, `SkPDFDocument::onClose()` is called to finish
52 special features of the PDF backend is that the same device can be 51 serializing the PDF file.
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 52
57 <!--?prettify lang=cc?-->
58 53
59 SkPDFCanon canon; 54 <span id="PDF_Objects_and_Document_Structure">PDF Objects and Document Structure </span>
60 SkAutoUnref<SkPDFDevice> pdfDevice( 55 -------------------------------------------------------------------------------- -------
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
70 <a name="PDF_Objects_and_Document_Structure"></a>
71 PDF Objects and Document Structure
72 ----------------------------------
73 56
74 ![PDF Logical Document Structure](/dev/design/PdfLogicalDocumentStructure.png) 57 ![PDF Logical Document Structure](/dev/design/PdfLogicalDocumentStructure.png)
75 58
76 **Background**: The PDF file format has a header, a set of objects and 59 **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 60 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 61 in the document (the cross-reference table). The table of contents
79 lists the specific byte position for each object. The objects may have 62 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 63 references to other objects and the ASCII size of those references is
81 dependent on the object number assigned to the referenced object; 64 dependent on the object number assigned to the referenced object;
82 therefore we can’t calculate the table of contents until the size of 65 therefore we can’t calculate the table of contents until the size of
83 objects is known, which requires assignment of object 66 objects is known, which requires assignment of object numbers. The
84 numbers. 67 document uses SkWStream::bytesWritten() to query the offsets of each
68 object and build the cross-reference table.
85 69
86 Furthermore, PDF files can support a *linearized* mode, where objects 70 Furthermore, PDF files can support a *linearized* mode, where objects
87 are in a specific order so that pdf-viewers can more easily retrieve 71 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 72 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 73 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 74 objects used or referenced on the first page of the PDF have object
91 numbers before the rest of the objects. Consequently, before 75 numbers before the rest of the objects. Consequently, before
92 generating a linearized PDF, all objects, their sizes, and object 76 generating a linearized PDF, all objects, their sizes, and object
93 references must be known. Skia has no plans to implement linearized 77 references must be known. Skia has no plans to implement linearized
94 PDFs. 78 PDFs.
95 79
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 80 %PDF-1.4
101 …objects... 81 …objects...
102 xref 82 xref
103 0 31 % Total number of entries in the table of contents. 83 0 31 % Total number of entries in the table of contents.
104 0000000000 65535 f 84 0000000000 65535 f
105 0000210343 00000 n 85 0000210343 00000 n
106 … 86 …
107 0000117055 00000 n 87 0000117055 00000 n
108 trailer 88 trailer
109 <</Size 31 /Root 1 0 R>> 89 <</Size 31 /Root 1 0 R>>
110 startxref 90 startxref
111 210399 % Byte offset to the start of the table of contents. 91 210399 % Byte offset to the start of the table of contents.
112 %%EOF 92 %%EOF
113 93
114 The class SkPDFCatalog and the virtual class SkPDFObject are used to 94 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 95 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 96 PDF object must inherit from SkPDFObject and implement the methods to
117 generate the binary representation and report any other SkPDFObjects 97 generate the binary representation and report any other SkPDFObjects
118 used as resources. SkPDFTypes.h defines most of the basic PDF objects 98 used as resources. SkPDFTypes.h defines most of the basic PDF object
119 types: bool, int, scalar, string, name, array, dictionary, and object 99 types: bool, int, scalar, string, name, array, dictionary, and stream.
120 reference. The stream type is defined in SkPDFStream.h. A stream is a 100 (A stream is a dictionary containing at least a Length entry followed
121 dictionary containing at least a Length entry followed by the data of 101 by the data of the stream.)
122 the stream. All of these types except the stream type can be used in 102
103 All of these PDF object 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 104 both a direct and an indirect fashion, i.e. an array can have an int
124 or a dictionary as an inline entry, which does not require an object 105 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 106 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 107 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 108 referred to with an object reference, but there are specific rules in
128 the PDF specification that requires an inline reference in some place 109 the PDF specification that requires an inline reference in some place
129 or an indirect reference in other places. All indirect objects must 110 or an indirect reference in other places. All indirect objects must
130 have an object number assigned. 111 have an object number assigned.
131 112
132 * **bools**: `true` `false` 113 * **bools**: `true` `false`
133 * **ints**: `42` `0` `-1` 114 * **ints**: `42` `0` `-1`
134 * **scalars**: `0.001` 115 * **scalars**: `0.001`
135 * **strings**: `(strings are in parentheses or byte encoded)` `<74657374>` 116 * **strings**: `(strings are in parentheses or byte encoded)` `<74657374>`
136 * **name**: `/Name` `/Name#20with#20spaces` 117 * **name**: `/Name` `/Name#20with#20spaces`
137 * **array**: `[/Foo 42 (arrays can contain multiple types)]` 118 * **array**: `[/Foo 42 (arrays can contain multiple types)]`
138 * **dictionary**: `<</Key1 (value1) /key2 42>>` 119 * **dictionary**: `<</Key1 (value1) /key2 42>>`
139 * **indirect object**: 120 * **indirect object**:
140 `5 0 obj 121 `5 0 obj
141 (An indirect string. Indirect objects have an object number and a 122 (An indirect string. Indirect objects have an object number and a
142 generation number, Skia always uses generation 0 objects) 123 generation number, Skia always uses generation 0 objects)
143 endobj` 124 endobj`
144 * **object reference**: `5 0 R` 125 * **object reference**: `5 0 R`
145 * **stream**: `<</Length 56>> 126 * **stream**: `<</Length 56>>
146 stream 127 stream
147 ...stream contents can be arbitrary, including binary... 128 ...stream contents can be arbitrary, including binary...
148 endstream` 129 endstream`
149 130
150 The PDF backend requires all indirect objects used in a PDF to be 131 The PDF backend requires all indirect objects used in a PDF to be
151 added to the SkPDFCatalog of the SkPDFDocument. The catalog is 132 added to the SkPDFObjNumMap of the SkPDFDocument. The catalog is
152 responsible for assigning object numbers and generating the table of 133 responsible for assigning object numbers and generating the table of
153 contents required at the end of PDF files. In some sense, generating a 134 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 135 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 136 references among them are created (mostly done by SkPDFDevice). In the
156 second step, object numbers are assigned and SkPDFCatalog is informed 137 second step, SkPDFObjNumMap assigns and remembers object numbers.
157 of the file offset of each indirect object. Finally, in the third 138 Finally, in the third
158 step, the header is printed, each object is printed, and then the 139 step, the header is printed, each object is printed, and then the
159 table of contents and trailer are printed. SkPDFDocument takes care of 140 table of contents and trailer are printed. SkPDFDocument takes care of
160 collecting all the objects from the various SkPDFDevice instances, 141 collecting all the objects from the various SkPDFDevice instances,
161 adding them to an SkPDFCatalog, iterating through the objects once to 142 adding them to an SkPDFObjNumMap, iterating through the objects once to
162 set their file positions, and iterating again to generate the final 143 set their file positions, and iterating again to generate the final
163 PDF. 144 PDF.
164 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
165 %PDF-1.4 149 %PDF-1.4
166 2 0 obj << 150 2 0 obj <<
167 /Type /Catalog 151 /Type /Catalog
168 /Pages 1 0 R 152 /Pages 1 0 R
169 >> 153 >>
170 endobj 154 endobj
171 3 0 obj << 155 3 0 obj <<
172 /Type /Page 156 /Type /Page
173 /Parent 1 0 R 157 /Parent 1 0 R
174 /Resources <> 158 /Resources <>
(...skipping 16 matching lines...) Expand all
191 0000000236 00000 n 175 0000000236 00000 n
192 0000000009 00000 n 176 0000000009 00000 n
193 0000000062 00000 n 177 0000000062 00000 n
194 0000000190 00000 n 178 0000000190 00000 n
195 trailer 179 trailer
196 <</Size 5 /Root 2 0 R>> 180 <</Size 5 /Root 2 0 R>>
197 startxref 181 startxref
198 299 182 299
199 %%EOF 183 %%EOF
200 184
201 <a name="PDF_drawing"></a> 185
202 PDF drawing 186 <span id="PDF_drawing">PDF drawing</span>
203 ----------- 187 -----------------------------------------
204 188
205 Most drawing in PDF is specified by the text of a stream, referred to 189 Most drawing in PDF is specified by the text of a stream, referred to
206 as a content stream. The syntax of the content stream is different 190 as a content stream. The syntax of the content stream is different
207 than the syntax of the file format described above and is much closer 191 than the syntax of the file format described above and is much closer
208 to PostScript in nature. The commands in the content stream tell the 192 to PostScript in nature. The commands in the content stream tell the
209 PDF interpreter to draw things, like a rectangle (`x y w h re`), an 193 PDF interpreter to draw things, like a rectangle (`x y w h re`), an
210 image, or text, or to do meta operations like set the drawing color, 194 image, or text, or to do meta operations like set the drawing color,
211 apply a transform to the drawing coordinates, or clip future drawing 195 apply a transform to the drawing coordinates, or clip future drawing
212 operations. The page object that references a content stream has a 196 operations. The page object that references a content stream has a
213 list of resources that can be used in the content stream using the 197 list of resources that can be used in the content stream using the
(...skipping 22 matching lines...) Expand all
236 /F1 12 Tf 220 /F1 12 Tf
237 72 96 Td 221 72 96 Td
238 (Hello World) Tj 222 (Hello World) Tj
239 ET 223 ET
240 % Draw a filled rectange. 224 % Draw a filled rectange.
241 200 96 72 72 re B 225 200 96 72 72 re B
242 ... 226 ...
243 endstream 227 endstream
244 endobj 228 endobj
245 229
246 <a name="Interned_objects"></a> 230 <span id="Interned_objects">Interned objects</span>
247 Interned objects 231 ---------------------------------------------------
248 ----------------
249 232
250 There are a number of high level PDF objects (like fonts, graphic 233 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 234 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 235 single PDF. To ensure that there is only one copy of each object
253 instance these objects an implemented with an 236 instance these objects an implemented with an
254 [interning pattern](http://en.wikipedia.org/wiki/String_interning). 237 [interning pattern](http://en.wikipedia.org/wiki/String_interning).
255 As such, the classes representing these objects (like 238 As such, the classes representing these objects (like
256 SkPDFGraphicState) have private constructors and static methods to 239 SkPDFGraphicState) have private constructors and static methods to
257 retrieve an instance of the class. Internally, the class has a list of 240 retrieve an instance of the class.
258 unique instances that it consults before returning a new instance of
259 the class. If the requested instance already exists, the existing one
260 is returned. For obvious reasons, the returned instance should not be
261 modified. A mechanism to ensure that interned classes are immutable is
262 needed. See [issue 2683](https://bug.skia.org/2683).
263 241
264 <a name="Graphic_States"></a> 242 The SkPDFCanon object owns the interned objects. For obvious reasons,
265 Graphic States 243 the returned instance should not be modified. A mechanism to ensure
266 -------------- 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 -----------------------------------------------
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
273 SkPDFGraphicState class. A simple command in the content stream can 255 SkPDFGraphicState class. A simple command in the content stream can
274 then set the drawing parameters to the values specified in that 256 then set the drawing parameters to the values specified in that
275 graphic state object. PDF does not allow specifying color in the 257 graphic state object. PDF does not allow specifying color in the
276 graphic state object, instead it must be specified directly in the 258 graphic state object, instead it must be specified directly in the
277 content stream. Similarly the current font and font size are set 259 content stream. Similarly the current font and font size are set
278 directly in the content stream. 260 directly in the content stream.
279 261
280 6 0 obj << 262 6 0 obj <<
281 /Type /ExtGState 263 /Type /ExtGState
282 /CA 1 % Opaque - alpha = 1 264 /CA 1 % Opaque - alpha = 1
283 /LC 0 % Butt linecap 265 /LC 0 % Butt linecap
284 /LJ 0 % Miter line-join 266 /LJ 0 % Miter line-join
285 /LW 2 % Line width of 2 267 /LW 2 % Line width of 2
286 /ML 6 % Miter limit of 6 268 /ML 6 % Miter limit of 6
287 /BM /Normal % Blend mode is normal i.e. source over 269 /BM /Normal % Blend mode is normal i.e. source over
288 >> 270 >>
289 endobj 271 endobj
290 272
291 <a name="Clip_and_Transform"></a> 273 <span id="Clip_and_Transform">Clip and Transform</span>
292 Clip and Transform 274 -------------------------------------------------------
293 ------------------
294 275
295 Similar to Skia, PDF allows drawing to be clipped or 276 Similar to Skia, PDF allows drawing to be clipped or
296 transformed. However, there are a few caveats that affect the design 277 transformed. However, there are a few caveats that affect the design
297 of the PDF backend. PDF does not support perspective transforms 278 of the PDF backend. PDF does not support perspective transforms
298 (perspective transform are treated as identity transforms). Clips, 279 (perspective transform are treated as identity transforms). Clips,
299 however, have more issues to cotend with. PDF clips cannot be directly 280 however, have more issues to cotend with. PDF clips cannot be directly
300 unapplied or expanded. i.e. once an area has been clipped off, there 281 unapplied or expanded. i.e. once an area has been clipped off, there
301 is no way to draw to it. However, PDF provides a limited depth stack 282 is no way to draw to it. However, PDF provides a limited depth stack
302 for the PDF graphic state (which includes the drawing parameters 283 for the PDF graphic state (which includes the drawing parameters
303 mentioned above in the Graphic States section as well as the clip and 284 mentioned above in the Graphic States section as well as the clip and
304 transform). Therefore to undo a clip, the PDF graphic state must be 285 transform). Therefore to undo a clip, the PDF graphic state must be
305 pushed before the clip is applied, then popped to revert to the state 286 pushed before the clip is applied, then popped to revert to the state
306 of the graphic state before the clip was applied. 287 of the graphic state before the clip was applied.
307 288
308 As the canvas makes drawing calls into SkPDFDevice, the active 289 As the canvas makes drawing calls into SkPDFDevice, the active
309 transform, clip region, and clip stack are stored in a ContentEntry 290 transform, clip region, and clip stack are stored in a ContentEntry
310 structure. Later, when the ContentEntry structures are flattened into 291 structure. Later, when the ContentEntry structures are flattened into
311 a valid PDF content stream, the transforms and clips are compared to 292 a valid PDF content stream, the transforms and clips are compared to
312 decide on an efficient set of operations to transition between the 293 decide on an efficient set of operations to transition between the
313 states needed. Currently, a local optimization is used, to figure out 294 states needed. Currently, a local optimization is used, to figure out
314 the best transition from one state to the next. A global optimization 295 the best transition from one state to the next. A global optimization
315 could improve things by more effectively using the graphics state 296 could improve things by more effectively using the graphics state
316 stack provided in the PDF format. 297 stack provided in the PDF format.
317 298
318 <a name="Generating_a_content_stream"></a> 299 <span id="Generating_a_content_stream">Generating a content stream</span>
319 Generating a content stream 300 -------------------------------------------------------------------------
320 ---------------------------
321 301
322 For each draw call on an SkPDFDevice, a new ContentEntry is created, 302 For each draw call on an SkPDFDevice, a new ContentEntry is created,
323 which stores the matrix, clip region, and clip stack as well as the 303 which stores the matrix, clip region, and clip stack as well as the
324 paint parameters. Most of the paint parameters are bundled into an 304 paint parameters. Most of the paint parameters are bundled into an
325 SkPDFGraphicState (interned) with the rest (color, font size, etc) 305 SkPDFGraphicState (interned) with the rest (color, font size, etc)
326 explicitly stored in the ContentEntry. After populating the 306 explicitly stored in the ContentEntry. After populating the
327 ContentEntry with all the relevant context, it is compared to the the 307 ContentEntry with all the relevant context, it is compared to the the
328 most recently used ContentEntry. If the context matches, then the 308 most recently used ContentEntry. If the context matches, then the
329 previous one is appended to instead of using the new one. In either 309 previous one is appended to instead of using the new one. In either
330 case, with the context populated into the ContentEntry, the 310 case, with the context populated into the ContentEntry, the
331 appropriate draw call is allowed to append to the content stream 311 appropriate draw call is allowed to append to the content stream
332 snippet in the ContentEntry to affect the core of the drawing call, 312 snippet in the ContentEntry to affect the core of the drawing call,
333 i.e. drawing a shape, an image, text, etc. 313 i.e. drawing a shape, an image, text, etc.
334 314
335 When all drawing is complete, SkPDFDocument::emitPDF() will call 315 When all drawing is complete, SkPDFDocument::onEndPage() will call
336 SkPDFDevice::content() to request the complete content stream for the 316 SkPDFDevice::content() to request the complete content stream for the
337 page. The first thing done is to apply the initial transform specified 317 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 318 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 319 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 320 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 321 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 322 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 323 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 324 inside the margins) of the page. Then, each ContentEntry is applied to
345 the content stream with the help of a helper class, GraphicStackState, 325 the content stream with the help of a helper class, GraphicStackState,
346 which tracks the state of the PDF graphics stack and optimizes the 326 which tracks the state of the PDF graphics stack and optimizes the
347 output. For each ContentEntry, commands are emitted to the final 327 output. For each ContentEntry, commands are emitted to the final
348 content entry to update the clip from its current state to the state 328 content entry to update the clip from its current state to the state
349 specified in the ContentEntry, similarly the Matrix and drawing state 329 specified in the ContentEntry, similarly the Matrix and drawing state
350 (color, line joins, etc) are updated, then the content entry fragment 330 (color, line joins, etc) are updated, then the content entry fragment
351 (the actual drawing operation) is appended. 331 (the actual drawing operation) is appended.
352 332
353 <a name="Margins_and_content_area"></a> 333 <span id="Drawing_details">Drawing details</span>
354 Margins and content area 334 -------------------------------------------------
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>
369 Drawing details
370 ---------------
371 335
372 Certain objects have specific properties that need to be dealt 336 Certain objects have specific properties that need to be dealt
373 with. Images, layers (see below), and fonts assume the standard PDF 337 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 338 coordinate system, so we have to undo any flip to the Skia coordinate
375 system before drawing these entities. We don’t currently support 339 system before drawing these entities. We don’t currently support
376 inverted paths, so filling an inverted path will give the wrong result 340 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 341 ([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. 342 lines that have butt of square caps, so that is emulated.
379 343
380 <a name="Layers"></a> 344 ### <span id="Layers">Layers</span> ###
381 ### Layers ###
382 345
383 PDF has a higher level object called a form x-object (form external 346 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 347 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 348 stream, but can be transformed and drawn on an existing page. This is
386 used to implement layers. SkDevice has a method, 349 used to implement layers. SkPDFDevice has a method,
387 createFormXObjectFromDevice, which uses the SkPDFDevice::content() 350 makeFormXObjectFromDevice(), which uses the SkPDFDevice::content()
388 method to construct a form x-object from the the 351 method to construct a form x-object from the the
389 device. SkPDFDevice::drawDevice() works by creating a form x-object of 352 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 353 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 354 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 355 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 356 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 357 result unless it is corrected for. The SkClipStack passed to drawing
395 commands includes the entire clip stack, including the clipping 358 commands includes the entire clip stack, including the clipping
396 operations done on the base layer. Since the form x-object will be 359 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 360 drawn as a single operation onto the base layer, we can assume that
398 all of those clips are in effect and need not apply them within the 361 all of those clips are in effect and need not apply them within the
399 layer. 362 layer.
400 363
401 <a name="Fonts"></a> 364 ### <span id="Fonts">Fonts</span> ###
402 ### Fonts ###
403 365
404 There are many details for dealing with fonts, so this document will 366 There are many details for dealing with fonts, so this document will
405 only talk about some of the more important ones. A couple short 367 only talk about some of the more important ones. A couple short
406 details: 368 details:
407 369
408 * We can’t assume that an arbitrary font will be available at PDF view 370 * We can’t assume that an arbitrary font will be available at PDF view
409 time, so we embed all fonts in accordance with modern PDF 371 time, so we embed all fonts in accordance with modern PDF
410 guidelines. 372 guidelines.
411 * Most fonts these days are TrueType fonts, so this is where most of 373 * Most fonts these days are TrueType fonts, so this is where most of
412 the effort has been concentrated. 374 the effort has been concentrated.
(...skipping 19 matching lines...) Expand all
432 PDF only supports an 8-bit encoding for Type1 or Type3 fonts. However, 394 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 395 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 396 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 397 unknown glyph) and presenting the font as multiple fonts, each with up
436 to 255 glyphs. 398 to 255 glyphs.
437 399
438 #### *Font subsetting* #### 400 #### *Font subsetting* ####
439 401
440 Many fonts, especially fonts with CJK support are fairly large, so it 402 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 403 is desirable to subset them. Chrome uses the SFNTLY package to provide
442 subsetting support to Skia for TrueType fonts. However, there is a 404 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 405
460 The substitution mechanism is a little complicated, but is needed to 406 ### <span id="Shaders">Shaders</span> ###
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
470 <a name="Shaders"></a>
471 ### Shaders ###
472 407
473 Skia has two types of predefined shaders, image shaders and gradient 408 Skia has two types of predefined shaders, image shaders and gradient
474 shaders. In both cases, shaders are effectively positioned absolutely, 409 shaders. In both cases, shaders are effectively positioned absolutely,
475 so the initial position and bounds of where they are visible is part 410 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 411 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 412 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 413 we generate will be tiled, so tiling is handled by default. To support
479 mirroring, we draw the image, reversed, on the appropriate axis, or on 414 mirroring, we draw the image, reversed, on the appropriate axis, or on
480 both axes plus a fourth in the vacant quadrant. For clamp mode, we 415 both axes plus a fourth in the vacant quadrant. For clamp mode, we
481 extract the pixels along the appropriate edge and stretch the single 416 extract the pixels along the appropriate edge and stretch the single
482 pixel wide/long image to fill the bounds. For both x and y in clamp 417 pixel wide/long image to fill the bounds. For both x and y in clamp
483 mode, we fill the corners with a rectangle of the appropriate 418 mode, we fill the corners with a rectangle of the appropriate
484 color. The composed shader is then rotated or scaled as appropriate 419 color. The composed shader is then rotated or scaled as appropriate
485 for the request. 420 for the request.
486 421
487 Gradient shaders are handled purely mathematically. First, the matrix 422 Gradient shaders are handled purely mathematically. First, the matrix
488 is transformed so that specific points in the requested gradient are 423 is transformed so that specific points in the requested gradient are
489 at pre-defined locations, for example, the linear distance of the 424 at pre-defined locations, for example, the linear distance of the
490 gradient is always normalized to one. Then, a type 4 PDF function is 425 gradient is always normalized to one. Then, a type 4 PDF function is
491 created that achieves the desired gradient. A type 4 function is a 426 created that achieves the desired gradient. A type 4 function is a
492 function defined by a resticted postscript language. The generated 427 function defined by a resticted postscript language. The generated
493 functions clamp at the edges so if the desired tiling mode is tile or 428 functions clamp at the edges so if the desired tiling mode is tile or
494 mirror, we hav to add a bit more postscript code to map any input 429 mirror, we hav to add a bit more postscript code to map any input
495 parameter into the 0-1 range appropriately. The code to generate the 430 parameter into the 0-1 range appropriately. The code to generate the
496 postscript code is somewhat obtuse, since it is trying to generate 431 postscript code is somewhat obtuse, since it is trying to generate
497 optimized (for space) postscript code, but there is a significant 432 optimized (for space) postscript code, but there is a significant
498 number of comments to explain the intent. 433 number of comments to explain the intent.
499 434
500 <a name="Xfer_modes"></a> 435 ### <span id="Xfer_modes">Xfer modes</span> ###
501 ### Xfer modes ###
502 436
503 PDF supports some of the xfer modes used in Skia directly. For those, 437 PDF supports some of the xfer modes used in Skia directly. For those,
504 it is simply a matter of setting the blend mode in the graphic state 438 it is simply a matter of setting the blend mode in the graphic state
505 to the appropriate value (Normal/SrcOver, Multiply, Screen, Overlay, 439 to the appropriate value (Normal/SrcOver, Multiply, Screen, Overlay,
506 Darken, Lighten, !ColorDOdge, ColorBurn, HardLight, SoftLight, 440 Darken, Lighten, !ColorDOdge, ColorBurn, HardLight, SoftLight,
507 Difference, Exclusion). Aside from the standard SrcOver mode, PDF does 441 Difference, Exclusion). Aside from the standard SrcOver mode, PDF does
508 not directly support the porter-duff xfer modes though. Most of them 442 not directly support the porter-duff xfer modes though. Most of them
509 (Clear, SrcMode, DstMode, DstOver, SrcIn, DstIn, SrcOut, DstOut) can 443 (Clear, SrcMode, DstMode, DstOver, SrcIn, DstIn, SrcOut, DstOut) can
510 be emulated by various means, mostly by creating form x-objects out of 444 be emulated by various means, mostly by creating form x-objects out of
511 part of the content and drawing it with a another form x-object as a 445 part of the content and drawing it with a another form x-object as a
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
564 this is accomplished by inserting the new ContentEntry at the 498 this is accomplished by inserting the new ContentEntry at the
565 beginning of the list of ContentEntry’s in setUpContentEntry instead 499 beginning of the list of ContentEntry’s in setUpContentEntry instead
566 of at the end. SrcIn, SrcOut, DstIn, DstOut are similar to each, the 500 of at the end. SrcIn, SrcOut, DstIn, DstOut are similar to each, the
567 difference being an inverted or non-inverted mask and swapping Src and 501 difference being an inverted or non-inverted mask and swapping Src and
568 Dst (or not). SrcIn is SrcMode with Src drawn with Dst as a 502 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 503 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 504 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 505 mask. Finally, DstOut is SrcMode with Dst draw with an inverted Src as
572 a mask. 506 a mask.
573 507
574 <a name="Known_issues"></a> 508 <span id="Known_issues">Known issues</span>
575 Known issues 509 -------------------------------------------
576 ------------
577 510
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) 511 * [issue 237](https://bug.skia.org/237)
584 SkMaskFilter is not supported. 512 SkMaskFilter is not supported.
585 * [issue 238](https://bug.skia.org/238) 513 * [issue 238](https://bug.skia.org/238)
586 SkColorFilter is not supported. 514 SkColorFilter is not supported.
587 * [issue 249](https://bug.skia.org/249) 515 * [issue 249](https://bug.skia.org/249)
588 SrcAtop Xor, and Plus xfer modes are not supported. 516 SrcAtop Xor, and Plus xfer modes are not supported.
589 * [issue 240](https://bug.skia.org/240) 517 * [issue 240](https://bug.skia.org/240)
590 drawVerticies is not implemented. 518 drawVerticies is not implemented.
591 * [issue 244](https://bug.skia.org/244) 519 * [issue 244](https://bug.skia.org/244)
592 Mostly, only TTF fonts are directly supported. (User metrics 520 Mostly, only TTF fonts are *directly* supported.
593 show that almost all fonts are truetype. 521 (User metrics show that almost all fonts are truetype.)
594 * [issue 260](https://bug.skia.org/260) 522 * [issue 260](https://bug.skia.org/260)
595 Page rotation is accomplished by specifying a different 523 Page rotation is accomplished by specifying a different
596 size page instead of including the appropriate rotation 524 size page instead of including the appropriate rotation
597 annotation. 525 annotation.
598 526
599 * * * 527 * * *
600 528
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698