SkPDFDocument.cpp revision a43b41538ad6af0f2b7742b4ade8265d344b9d64
199ac02bb701c1e30b20f2174aac25ffbe487c0afreed@google.com/* 2a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary * Copyright 2011 Google Inc. 399ac02bb701c1e30b20f2174aac25ffbe487c0afreed@google.com * 499ac02bb701c1e30b20f2174aac25ffbe487c0afreed@google.com * Use of this source code is governed by a BSD-style license that can be 599ac02bb701c1e30b20f2174aac25ffbe487c0afreed@google.com * found in the LICENSE file. 699ac02bb701c1e30b20f2174aac25ffbe487c0afreed@google.com */ 799ac02bb701c1e30b20f2174aac25ffbe487c0afreed@google.com 899ac02bb701c1e30b20f2174aac25ffbe487c0afreed@google.com#include "SkDocument.h" 9a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary#include "SkPDFCanon.h" 10a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary#include "SkPDFCatalog.h" 115867736b08d3689356b49f505bcf748c2194a0bcreed#include "SkPDFDevice.h" 12a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary#include "SkPDFFont.h" 13a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary#include "SkPDFPage.h" 14a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary#include "SkPDFTypes.h" 15a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary#include "SkStream.h" 16a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary 17a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanarystatic void emit_pdf_header(SkWStream* stream) { 18a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary stream->writeText("%PDF-1.4\n%"); 19a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary // The PDF spec recommends including a comment with four bytes, all 20a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary // with their high bits set. This is "Skia" with the high bits set. 21a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary stream->write32(0xD3EBE9E1); 22a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary stream->writeText("\n"); 23a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary} 24a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary 25a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanarystatic void emit_pdf_footer(SkWStream* stream, 26a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary SkPDFCatalog* catalog, 27a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary SkPDFObject* docCatalog, 28a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary int64_t objCount, 29a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary int32_t xRefFileOffset) { 30a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary SkPDFDict trailerDict; 31a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary // TODO(vandebo): Linearized format will take a Prev entry too. 32a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary // TODO(vandebo): PDF/A requires an ID entry. 33a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary trailerDict.insertInt("Size", int(objCount)); 34a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary trailerDict.insert("Root", new SkPDFObjRef(docCatalog))->unref(); 35a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary 36a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary stream->writeText("trailer\n"); 37a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary trailerDict.emitObject(stream, catalog); 38a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary stream->writeText("\nstartxref\n"); 39a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary stream->writeBigDecAsText(xRefFileOffset); 40a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary stream->writeText("\n%%EOF"); 41a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary} 42a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary 43a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanarystatic void perform_font_subsetting(SkPDFCatalog* catalog, 44a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary const SkTDArray<SkPDFPage*>& pages) { 45a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary SkASSERT(catalog); 46a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary 47a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary SkPDFGlyphSetMap usage; 48a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary for (int i = 0; i < pages.count(); ++i) { 49a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary usage.merge(pages[i]->getFontGlyphUsage()); 50a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary } 51a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary SkPDFGlyphSetMap::F2BIter iterator(usage); 52a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary const SkPDFGlyphSetMap::FontGlyphSetPair* entry = iterator.next(); 53a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary while (entry) { 54a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary SkAutoTUnref<SkPDFFont> subsetFont( 55a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary entry->fFont->getFontSubset(entry->fGlyphSet)); 56a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary if (subsetFont) { 57a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary catalog->setSubstitute(entry->fFont, subsetFont.get()); 58a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary } 59a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary entry = iterator.next(); 60a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary } 61a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary} 62a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary 63a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanarystatic bool emit_pdf_document(const SkTDArray<const SkPDFDevice*>& pageDevices, 64a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary SkWStream* stream) { 65a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary if (pageDevices.isEmpty()) { 66a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary return false; 67a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary } 68a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary 69a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary SkTDArray<SkPDFPage*> pages; 70a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary SkAutoTUnref<SkPDFDict> dests(SkNEW(SkPDFDict)); 71a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary 72a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary for (int i = 0; i < pageDevices.count(); i++) { 73a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary SkASSERT(pageDevices[i]); 74a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary SkASSERT(i == 0 || 75a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary pageDevices[i - 1]->getCanon() == pageDevices[i]->getCanon()); 76a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary // Reference from new passed to pages. 77a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary SkAutoTUnref<SkPDFPage> page(SkNEW_ARGS(SkPDFPage, (pageDevices[i]))); 78a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary page->finalizePage(); 79a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary page->appendDestinations(dests); 80a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary pages.push(page.detach()); 81a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary } 82a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary SkPDFCatalog catalog; 83a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary 84a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary SkTDArray<SkPDFDict*> pageTree; 85a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary SkAutoTUnref<SkPDFDict> docCatalog(SkNEW_ARGS(SkPDFDict, ("Catalog"))); 86a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary 87a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary SkPDFDict* pageTreeRoot; 88a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary SkPDFPage::GeneratePageTree(pages, &pageTree, &pageTreeRoot); 89a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary 90a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary docCatalog->insert("Pages", new SkPDFObjRef(pageTreeRoot))->unref(); 91a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary 92a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary /* TODO(vandebo): output intent 93a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary SkAutoTUnref<SkPDFDict> outputIntent = new SkPDFDict("OutputIntent"); 94a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary outputIntent->insert("S", new SkPDFName("GTS_PDFA1"))->unref(); 95a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary outputIntent->insert("OutputConditionIdentifier", 96a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary new SkPDFString("sRGB"))->unref(); 97a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary SkAutoTUnref<SkPDFArray> intentArray = new SkPDFArray; 98a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary intentArray->append(outputIntent.get()); 99a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary docCatalog->insert("OutputIntent", intentArray.get()); 100a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary */ 101a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary 102a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary if (dests->size() > 0) { 103a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary docCatalog->insert("Dests", SkNEW_ARGS(SkPDFObjRef, (dests.get()))) 104a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary ->unref(); 105a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary } 106a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary 107a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary // Build font subsetting info before proceeding. 108a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary perform_font_subsetting(&catalog, pages); 109a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary 110a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary SkTSet<SkPDFObject*> resourceSet; 111a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary if (resourceSet.add(docCatalog.get())) { 112a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary docCatalog->addResources(&resourceSet, &catalog); 113a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary } 114a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary for (int i = 0; i < resourceSet.count(); ++i) { 115a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary SkAssertResult(catalog.addObject(resourceSet[i])); 116a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary } 117a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary 118a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary size_t baseOffset = SkToOffT(stream->bytesWritten()); 119a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary emit_pdf_header(stream); 120a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary SkTDArray<int32_t> offsets; 121a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary for (int i = 0; i < resourceSet.count(); ++i) { 122a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary SkPDFObject* object = resourceSet[i]; 123a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary offsets.push(SkToS32(stream->bytesWritten() - baseOffset)); 124a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary SkASSERT(object == catalog.getSubstituteObject(object)); 125a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary SkASSERT(catalog.getObjectNumber(object) == i + 1); 126a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary stream->writeDecAsText(i + 1); 127a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary stream->writeText(" 0 obj\n"); // Generation number is always 0. 128a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary object->emitObject(stream, &catalog); 129a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary stream->writeText("\nendobj\n"); 130a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary } 131a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary int32_t xRefFileOffset = SkToS32(stream->bytesWritten() - baseOffset); 132a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary 133a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary int32_t objCount = SkToS32(offsets.count() + 1); 134a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary 135a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary stream->writeText("xref\n0 "); 136a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary stream->writeDecAsText(objCount + 1); 137a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary stream->writeText("\n0000000000 65535 f \n"); 138a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary for (int i = 0; i < offsets.count(); i++) { 139a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary SkASSERT(offsets[i] > 0); 140a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary stream->writeBigDecAsText(offsets[i], 10); 141a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary stream->writeText(" 00000 n \n"); 142a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary } 143a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary emit_pdf_footer(stream, &catalog, docCatalog.get(), objCount, 144a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary xRefFileOffset); 145a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary 146a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary // The page tree has both child and parent pointers, so it creates a 147a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary // reference cycle. We must clear that cycle to properly reclaim memory. 148a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary for (int i = 0; i < pageTree.count(); i++) { 149a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary pageTree[i]->clear(); 150a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary } 151a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary pageTree.safeUnrefAll(); 152a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary pages.unrefAll(); 153a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary return true; 154a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary} 155a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary 156a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary#if 0 157a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary// TODO(halcanary): expose notEmbeddableCount in SkDocument 158a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanaryvoid GetCountOfFontTypes( 159a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary const SkTDArray<SkPDFDevice*>& pageDevices, 160a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary int counts[SkAdvancedTypefaceMetrics::kOther_Font + 1], 161a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary int* notSubsettableCount, 162a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary int* notEmbeddableCount) { 163a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary sk_bzero(counts, sizeof(int) * 164a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary (SkAdvancedTypefaceMetrics::kOther_Font + 1)); 165a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary SkTDArray<SkFontID> seenFonts; 166a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary int notSubsettable = 0; 167a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary int notEmbeddable = 0; 168a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary 169a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary for (int pageNumber = 0; pageNumber < pageDevices.count(); pageNumber++) { 170a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary const SkTDArray<SkPDFFont*>& fontResources = 171a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary pageDevices[pageNumber]->getFontResources(); 172a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary for (int font = 0; font < fontResources.count(); font++) { 173a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary SkFontID fontID = fontResources[font]->typeface()->uniqueID(); 174a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary if (seenFonts.find(fontID) == -1) { 175a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary counts[fontResources[font]->getType()]++; 176a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary seenFonts.push(fontID); 177a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary if (!fontResources[font]->canSubset()) { 178a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary notSubsettable++; 179a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary } 180a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary if (!fontResources[font]->canEmbed()) { 181a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary notEmbeddable++; 182a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary } 183a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary } 184a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary } 185a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary } 186a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary if (notSubsettableCount) { 187a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary *notSubsettableCount = notSubsettable; 188a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary 189a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary } 190a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary if (notEmbeddableCount) { 191a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary *notEmbeddableCount = notEmbeddable; 192a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary } 193a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary} 194a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary#endif 195a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary//////////////////////////////////////////////////////////////////////////////// 19699ac02bb701c1e30b20f2174aac25ffbe487c0afreed@google.com 1977a0118465a2dd1783d7b19b026bedd7e13afadf2halcanarynamespace { 19899ac02bb701c1e30b20f2174aac25ffbe487c0afreed@google.comclass SkDocument_PDF : public SkDocument { 19999ac02bb701c1e30b20f2174aac25ffbe487c0afreed@google.compublic: 2008c92dc1dc281649f9e6b0ff534c25bc89dded3eahalcanary SkDocument_PDF(SkWStream* stream, 201792c80f5a7b66e75d42664ccb298f31962c6654chalcanary void (*doneProc)(SkWStream*, bool), 2028c294900f31d8d032b62182f011019276d27d5d0commit-bot@chromium.org SkScalar rasterDpi) 2038c92dc1dc281649f9e6b0ff534c25bc89dded3eahalcanary : SkDocument(stream, doneProc) 2048c92dc1dc281649f9e6b0ff534c25bc89dded3eahalcanary , fRasterDpi(rasterDpi) {} 2056319367bdcbf5e5050632ab97973f5035d0dd8faskia.committer@gmail.com 20699ac02bb701c1e30b20f2174aac25ffbe487c0afreed@google.com virtual ~SkDocument_PDF() { 20799ac02bb701c1e30b20f2174aac25ffbe487c0afreed@google.com // subclasses must call close() in their destructors 20899ac02bb701c1e30b20f2174aac25ffbe487c0afreed@google.com this->close(); 20999ac02bb701c1e30b20f2174aac25ffbe487c0afreed@google.com } 21099ac02bb701c1e30b20f2174aac25ffbe487c0afreed@google.com 21199ac02bb701c1e30b20f2174aac25ffbe487c0afreed@google.comprotected: 21299ac02bb701c1e30b20f2174aac25ffbe487c0afreed@google.com virtual SkCanvas* onBeginPage(SkScalar width, SkScalar height, 2135e00989a283111cef05bed8102e45c16651e43e4commit-bot@chromium.org const SkRect& trimBox) SK_OVERRIDE { 214a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary SkASSERT(!fCanvas.get()); 21599ac02bb701c1e30b20f2174aac25ffbe487c0afreed@google.com 216a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary SkISize pageSize = SkISize::Make( 217a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary SkScalarRoundToInt(width), SkScalarRoundToInt(height)); 2187a0118465a2dd1783d7b19b026bedd7e13afadf2halcanary SkAutoTUnref<SkPDFDevice> device( 2197a0118465a2dd1783d7b19b026bedd7e13afadf2halcanary SkPDFDevice::Create(pageSize, fRasterDpi, &fCanon)); 2207a0118465a2dd1783d7b19b026bedd7e13afadf2halcanary fCanvas.reset(SkNEW_ARGS(SkCanvas, (device.get()))); 2217a0118465a2dd1783d7b19b026bedd7e13afadf2halcanary fPageDevices.push(device.detach()); 222be519ad718371cc40c432572173e47f851476486halcanary fCanvas->clipRect(trimBox); 22393f816129356d6764a9402817cc36bffd8f991fbhalcanary fCanvas->translate(trimBox.x(), trimBox.y()); 224a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary return fCanvas.get(); 22599ac02bb701c1e30b20f2174aac25ffbe487c0afreed@google.com } 22699ac02bb701c1e30b20f2174aac25ffbe487c0afreed@google.com 22772c9faab45124e08c85f70ca38536914862d947cmtklein void onEndPage() SK_OVERRIDE { 228a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary SkASSERT(fCanvas.get()); 22999ac02bb701c1e30b20f2174aac25ffbe487c0afreed@google.com fCanvas->flush(); 230a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary fCanvas.reset(NULL); 23199ac02bb701c1e30b20f2174aac25ffbe487c0afreed@google.com } 23299ac02bb701c1e30b20f2174aac25ffbe487c0afreed@google.com 23372c9faab45124e08c85f70ca38536914862d947cmtklein bool onClose(SkWStream* stream) SK_OVERRIDE { 234a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary SkASSERT(!fCanvas.get()); 23599ac02bb701c1e30b20f2174aac25ffbe487c0afreed@google.com 236a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary bool success = emit_pdf_document(fPageDevices, stream); 2377a0118465a2dd1783d7b19b026bedd7e13afadf2halcanary fPageDevices.unrefAll(); 2382e3f9d8a9309686eeb4c76ccfde5800da87a68b3halcanary fCanon.reset(); 239b5a6651f9f69570d964382134d64360915db9a29commit-bot@chromium.org return success; 240b5a6651f9f69570d964382134d64360915db9a29commit-bot@chromium.org } 241b5a6651f9f69570d964382134d64360915db9a29commit-bot@chromium.org 24272c9faab45124e08c85f70ca38536914862d947cmtklein void onAbort() SK_OVERRIDE { 2437a0118465a2dd1783d7b19b026bedd7e13afadf2halcanary fPageDevices.unrefAll(); 2442e3f9d8a9309686eeb4c76ccfde5800da87a68b3halcanary fCanon.reset(); 24599ac02bb701c1e30b20f2174aac25ffbe487c0afreed@google.com } 24699ac02bb701c1e30b20f2174aac25ffbe487c0afreed@google.com 24799ac02bb701c1e30b20f2174aac25ffbe487c0afreed@google.comprivate: 248a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary SkPDFCanon fCanon; 2496d622703e578eddc64ab4e3340d0ab0033268799halcanary SkTDArray<const SkPDFDevice*> fPageDevices; 250a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary SkAutoTUnref<SkCanvas> fCanvas; 251a1f1ee98a1f6d0770f6243270ca2f0e6c92efabahalcanary SkScalar fRasterDpi; 25299ac02bb701c1e30b20f2174aac25ffbe487c0afreed@google.com}; 2537a0118465a2dd1783d7b19b026bedd7e13afadf2halcanary} // namespace 25499ac02bb701c1e30b20f2174aac25ffbe487c0afreed@google.com/////////////////////////////////////////////////////////////////////////////// 25599ac02bb701c1e30b20f2174aac25ffbe487c0afreed@google.com 2568c92dc1dc281649f9e6b0ff534c25bc89dded3eahalcanarySkDocument* SkDocument::CreatePDF(SkWStream* stream, SkScalar dpi) { 2578c92dc1dc281649f9e6b0ff534c25bc89dded3eahalcanary return stream ? SkNEW_ARGS(SkDocument_PDF, (stream, NULL, dpi)) : NULL; 25899ac02bb701c1e30b20f2174aac25ffbe487c0afreed@google.com} 25999ac02bb701c1e30b20f2174aac25ffbe487c0afreed@google.com 2608c92dc1dc281649f9e6b0ff534c25bc89dded3eahalcanarySkDocument* SkDocument::CreatePDF(const char path[], SkScalar dpi) { 26199ac02bb701c1e30b20f2174aac25ffbe487c0afreed@google.com SkFILEWStream* stream = SkNEW_ARGS(SkFILEWStream, (path)); 26299ac02bb701c1e30b20f2174aac25ffbe487c0afreed@google.com if (!stream->isValid()) { 26399ac02bb701c1e30b20f2174aac25ffbe487c0afreed@google.com SkDELETE(stream); 26499ac02bb701c1e30b20f2174aac25ffbe487c0afreed@google.com return NULL; 26599ac02bb701c1e30b20f2174aac25ffbe487c0afreed@google.com } 266a43b41538ad6af0f2b7742b4ade8265d344b9d64halcanary auto delete_wstream = [](SkWStream* stream, bool) { SkDELETE(stream); }; 2678c92dc1dc281649f9e6b0ff534c25bc89dded3eahalcanary return SkNEW_ARGS(SkDocument_PDF, (stream, delete_wstream, dpi)); 26899ac02bb701c1e30b20f2174aac25ffbe487c0afreed@google.com} 269