Chromium Code Reviews| Index: site/dev/design/pdftheory.md |
| diff --git a/site/dev/design/pdftheory.md b/site/dev/design/pdftheory.md |
| index e0433ba563dc563006ae08bdde1f4e181e4c494c..89ce42b7c2f6fa3d51e8c0a5db7c4182f955fc0a 100644 |
| --- a/site/dev/design/pdftheory.md |
| +++ b/site/dev/design/pdftheory.md |
| @@ -30,7 +30,6 @@ are subject to perpetual change.** |
| * [Graphic States](#Graphic_States) |
| * [Clip and Transform](#Clip_and_Transform) |
| * [Generating a content stream](#Generating_a_content_stream) |
| -* [Margins and content area](#Margins_and_content_area) |
| * [Drawing details](#Drawing_details) |
| + [Layers](#Layers) |
| + [Fonts](#Fonts) |
| @@ -43,29 +42,12 @@ Typical usage of the PDF backend |
| -------------------------------- |
| SkPDFDevice is the main interface to the PDF backend. This child of |
| -SkDevice can be set on an SkCanvas and drawn to. It requires no more |
| -care and feeding than SkDevice. Once drawing is complete, the device |
| -should be added to an SkPDFDocument as a page of the desired PDF. A |
| -new SkPDFDevice should be created for each page desired in the |
| -document. After all the pages have been added to the document, |
| -`SkPDFDocument::emitPDF()` can be called to get a PDF file. One of the |
| -special features of the PDF backend is that the same device can be |
| -added to multiple documents. This for example, would let you generate |
| -a PDF with the single page you just drew as well as adding it to a |
| -longer document with a bunch of other pages. |
| - |
| -<!--?prettify lang=cc?--> |
| - |
| - SkPDFCanon canon; |
| - SkAutoUnref<SkPDFDevice> pdfDevice( |
| - SkPDFDevice::Create(SkISize::Make(width, height), 72.0f, &canon)); |
| - |
| - SkCanvas canvas(pdfDevice); |
| - draw_content(&canvas); |
| - |
| - SkPDFDocument doc; |
| - doc.appendPage(dev); |
| - doc.emitPDF(&pdf_stream); |
| +SkDevice can be set on an SkPDFCanvas and drawn to. Once drawing is |
|
tomhudson
2016/09/01 19:11:58
...can be set on an SkPDFCanvas. Once drawing to t
hal.canary
2016/09/28 18:18:28
Done.
|
| +complete, the device's content and resouces are added to the |
|
tomhudson
2016/09/01 19:11:58
How is completion of drawing signaled via the API?
hal.canary
2016/09/28 18:18:28
Done.
|
| +SkPDFDocument that owns the device. A new SkPDFDevice should be |
| +created for each page or layer desired in the document. After all the |
| +pages have been added to the document, `SkPDFDocument::onClose()` is |
| +called to finish the PDF file. |
|
tomhudson
2016/09/01 19:11:58
Do we need any more definition of what 'finish' en
hal.canary
2016/09/28 18:18:28
Done.
|
| <a name="PDF_Objects_and_Document_Structure"></a> |
| PDF Objects and Document Structure |
| @@ -80,8 +62,9 @@ lists the specific byte position for each object. The objects may have |
| references to other objects and the ASCII size of those references is |
| dependent on the object number assigned to the referenced object; |
| therefore we can’t calculate the table of contents until the size of |
| -objects is known, which requires assignment of object |
| -numbers. |
| +objects is known, which requires assignment of object numbers. use |
|
bungeman-skia
2016/08/31 21:14:26
Capitalize 'use'.
hal.canary
2016/09/28 18:18:28
Done.
|
| +SkWStream::bytesWritten() to query the offsets of each object and |
| +build the cross-reference table. |
| Furthermore, PDF files can support a *linearized* mode, where objects |
| are in a specific order so that pdf-viewers can more easily retrieve |
| @@ -93,10 +76,6 @@ generating a linearized PDF, all objects, their sizes, and object |
| references must be known. Skia has no plans to implement linearized |
| PDFs. |
| -<!-- <del>At this point, linearized PDFs are not generated. The |
| -framework to generate them is in place, but the final bits of code |
| -have not been written.</del> --> |
| - |
| %PDF-1.4 |
| …objects... |
| xref |
| @@ -111,13 +90,13 @@ have not been written.</del> --> |
| 210399 % Byte offset to the start of the table of contents. |
| %%EOF |
| -The class SkPDFCatalog and the virtual class SkPDFObject are used to |
| +The class SkPDFObjNumMap and the virtual class SkPDFObject are used to |
| manage the needs of the file format. Any object that will represent a |
| PDF object must inherit from SkPDFObject and implement the methods to |
| generate the binary representation and report any other SkPDFObjects |
| used as resources. SkPDFTypes.h defines most of the basic PDF objects |
| -types: bool, int, scalar, string, name, array, dictionary, and object |
| -reference. The stream type is defined in SkPDFStream.h. A stream is a |
| +types: bool, int, scalar, string, name, array, dictionary, and stream. |
| +A stream is a |
| dictionary containing at least a Length entry followed by the data of |
| the stream. All of these types except the stream type can be used in |
| both a direct and an indirect fashion, i.e. an array can have an int |
| @@ -148,20 +127,23 @@ have an object number assigned. |
| endstream` |
| The PDF backend requires all indirect objects used in a PDF to be |
| -added to the SkPDFCatalog of the SkPDFDocument. The catalog is |
| +added to the SkPDFObjNumMap of the SkPDFDocument. The catalog is |
| responsible for assigning object numbers and generating the table of |
| contents required at the end of PDF files. In some sense, generating a |
| PDF is a three step process. In the first step all the objects and |
| references among them are created (mostly done by SkPDFDevice). In the |
| -second step, object numbers are assigned and SkPDFCatalog is informed |
| -of the file offset of each indirect object. Finally, in the third |
| +second step, SkPDFObjNumMap assigns and remembers object numbers. |
| +Finally, in the third |
| step, the header is printed, each object is printed, and then the |
| table of contents and trailer are printed. SkPDFDocument takes care of |
| collecting all the objects from the various SkPDFDevice instances, |
| -adding them to an SkPDFCatalog, iterating through the objects once to |
| +adding them to an SkPDFObjNumMap, iterating through the objects once to |
| set their file positions, and iterating again to generate the final |
| PDF. |
| +As an optimization, many leaf nodes in the direct graph of indirect |
| +objects can be assigned object numbers and serialized early. |
| + |
| %PDF-1.4 |
| 2 0 obj << |
| /Type /Catalog |
| @@ -254,12 +236,12 @@ instance these objects an implemented with an |
| [interning pattern](http://en.wikipedia.org/wiki/String_interning). |
| As such, the classes representing these objects (like |
| SkPDFGraphicState) have private constructors and static methods to |
| -retrieve an instance of the class. Internally, the class has a list of |
| -unique instances that it consults before returning a new instance of |
| -the class. If the requested instance already exists, the existing one |
| -is returned. For obvious reasons, the returned instance should not be |
| -modified. A mechanism to ensure that interned classes are immutable is |
| -needed. See [issue 2683](https://bug.skia.org/2683). |
| +retrieve an instance of the class. |
| + |
| +The SkPDFCanon object owns the interned objects. For obvious reasons, |
| +the returned instance should not be modified. A mechanism to ensure |
| +that interned classes are immutable is needed. See [issue |
| +2683](https://bug.skia.org/2683). |
| <a name="Graphic_States"></a> |
| Graphic States |
| @@ -332,7 +314,7 @@ appropriate draw call is allowed to append to the content stream |
| snippet in the ContentEntry to affect the core of the drawing call, |
| i.e. drawing a shape, an image, text, etc. |
| -When all drawing is complete, SkPDFDocument::emitPDF() will call |
| +When all drawing is complete, SkPDFDocument::onEndPage() will call |
| SkPDFDevice::content() to request the complete content stream for the |
| page. The first thing done is to apply the initial transform specified |
| in part in the constructor, this transform takes care of changing the |
| @@ -350,21 +332,6 @@ specified in the ContentEntry, similarly the Matrix and drawing state |
| (color, line joins, etc) are updated, then the content entry fragment |
| (the actual drawing operation) is appended. |
| -<a name="Margins_and_content_area"></a> |
| -Margins and content area |
| ------------------------- |
| - |
| -The above procedure does not permit drawing in the margins. This is |
| -done in order to contain any rendering problems in WebKit. In order to |
| -support headers and footers, which are drawn in the margin, a second |
| -set of ContentEntry’s are maintained. The |
| -methodSkPDFDevice::setDrawingArea() selects which set of |
| -ContentEntry’s are drawn into. Then, in the SkPDFDevice::content() |
| -method, just before the clip to the content area is applied the margin |
| -ContentEntry's are played back. |
| - |
| -<!-- TODO(halcanary): update this documentation. --> |
| - |
| <a name="Drawing_details"></a> |
| Drawing details |
| --------------- |
| @@ -383,8 +350,8 @@ lines that have butt of square caps, so that is emulated. |
| PDF has a higher level object called a form x-object (form external |
| object) that is basically a PDF page, with resources and a content |
| stream, but can be transformed and drawn on an existing page. This is |
| -used to implement layers. SkDevice has a method, |
| -createFormXObjectFromDevice, which uses the SkPDFDevice::content() |
| +used to implement layers. SkPDFDevice has a method, |
| +makeFormXObjectFromDevice(), which uses the SkPDFDevice::content() |
| method to construct a form x-object from the the |
| device. SkPDFDevice::drawDevice() works by creating a form x-object of |
| the passed device and then drawing that form x-object in the root |
| @@ -439,33 +406,7 @@ to 255 glyphs. |
| Many fonts, especially fonts with CJK support are fairly large, so it |
| is desirable to subset them. Chrome uses the SFNTLY package to provide |
| -subsetting support to Skia for TrueType fonts. However, there is a |
| -conflict between font subsetting and interned objects. If the object |
| -is immutable, how can it be subsetted? This conflict is resolved by |
| -using a substitution mechanism in SkPDFCatalog. Font objects are still |
| -interned, but the interned objects aren’t internally |
| -populated. Subsetting starts while drawing text to an SkPDFDevice; a |
| -bit set indicating which glyphs have been used is maintained. Later, |
| -when SkPDFDocument::emitPDF() is rendering the PDF, it queries each |
| -device (each page) for the set of fonts used and the glyphs used from |
| -each font and combines the information. It then asks the interned |
| -(unpopulated) font objects to create a populated instance with the |
| -calculated subset of the font - this instance is not interned. The |
| -subsetted instance is then set as a substitute for the interned font |
| -object in the SkPDFCatalog. All future references to those fonts |
| -within that document will refer to the subsetted instances, resulting |
| -in a final PDF with exactly one instance of each used font that |
| -includes only the glyphs used. |
| - |
| -The substitution mechanism is a little complicated, but is needed to |
| -support the use case of an SkPDFDevice being added to multiple |
| -documents. If fonts were subsetted in-situ, concurrent PDF generation |
| -would have to be explicitly handled. Instead, by giving each document |
| -its own subsetted instance, there is no need to worry about concurrent |
| -PDF generation. The substitution method is also used to support |
| -optional stream compression. A stream can used by different documents |
| -in both a compressed and uncompressed form, leading to the same |
| -potential difficulties faced by the concurrent font use case. |
| +subsetting support to Skia for TrueType fonts. |
| <a name="Shaders"></a> |
| ### Shaders ### |
| @@ -575,11 +516,6 @@ a mask. |
| Known issues |
| ------------ |
| -* [issue 241](https://bug.skia.org/241) |
| - As previously noted, a boolean geometry library |
| - would improve clip fidelity in some places, add supported for |
| - inverted fill types, as well as simplify code. |
| - This is fixed, but behind a flag until path ops is production ready. |
| * [issue 237](https://bug.skia.org/237) |
| SkMaskFilter is not supported. |
| * [issue 238](https://bug.skia.org/238) |