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

Side by Side Diff: src/doc/SkDocument_PDF.cpp

Issue 1775043002: SkPDF: Add sk_sp setters; .release() becomes std::move() (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: fix -Wpessimizing-move Created 4 years, 9 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 | src/pdf/SkPDFBitmap.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2011 Google Inc. 2 * Copyright 2011 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "SkDocument.h" 8 #include "SkDocument.h"
9 #include "SkPDFCanon.h" 9 #include "SkPDFCanon.h"
10 #include "SkPDFDevice.h" 10 #include "SkPDFDevice.h"
(...skipping 13 matching lines...) Expand all
24 stream->write32(0xD3EBE9E1); 24 stream->write32(0xD3EBE9E1);
25 stream->writeText("\n"); 25 stream->writeText("\n");
26 } 26 }
27 27
28 static void emit_pdf_footer(SkWStream* stream, 28 static void emit_pdf_footer(SkWStream* stream,
29 const SkPDFObjNumMap& objNumMap, 29 const SkPDFObjNumMap& objNumMap,
30 const SkPDFSubstituteMap& substitutes, 30 const SkPDFSubstituteMap& substitutes,
31 SkPDFObject* docCatalog, 31 SkPDFObject* docCatalog,
32 int64_t objCount, 32 int64_t objCount,
33 int32_t xRefFileOffset, 33 int32_t xRefFileOffset,
34 SkPDFObject* info /* take ownership */, 34 sk_sp<SkPDFObject> info,
35 SkPDFObject* id /* take ownership */) { 35 sk_sp<SkPDFObject> id) {
36 SkPDFDict trailerDict; 36 SkPDFDict trailerDict;
37 // TODO(http://crbug.com/80908): Linearized format will take a 37 // TODO(http://crbug.com/80908): Linearized format will take a
38 // Prev entry too. 38 // Prev entry too.
39 trailerDict.insertInt("Size", int(objCount)); 39 trailerDict.insertInt("Size", int(objCount));
40 trailerDict.insertObjRef("Root", SkRef(docCatalog)); 40 trailerDict.insertObjRef("Root", sk_sp<SkPDFObject>(SkRef(docCatalog)));
41 SkASSERT(info); 41 SkASSERT(info);
42 trailerDict.insertObjRef("Info", info); 42 trailerDict.insertObjRef("Info", std::move(info));
43 if (id) { 43 if (id) {
44 trailerDict.insertObject("ID", id); 44 trailerDict.insertObject("ID", std::move(id));
45 } 45 }
46 stream->writeText("trailer\n"); 46 stream->writeText("trailer\n");
47 trailerDict.emitObject(stream, objNumMap, substitutes); 47 trailerDict.emitObject(stream, objNumMap, substitutes);
48 stream->writeText("\nstartxref\n"); 48 stream->writeText("\nstartxref\n");
49 stream->writeBigDecAsText(xRefFileOffset); 49 stream->writeBigDecAsText(xRefFileOffset);
50 stream->writeText("\n%%EOF"); 50 stream->writeText("\n%%EOF");
51 } 51 }
52 52
53 static void perform_font_subsetting( 53 static void perform_font_subsetting(
54 const SkTDArray<const SkPDFDevice*>& pageDevices, 54 const SkTArray<sk_sp<const SkPDFDevice>>& pageDevices,
55 SkPDFSubstituteMap* substituteMap) { 55 SkPDFSubstituteMap* substituteMap) {
56 SkASSERT(substituteMap); 56 SkASSERT(substituteMap);
57 57
58 SkPDFGlyphSetMap usage; 58 SkPDFGlyphSetMap usage;
59 for (int i = 0; i < pageDevices.count(); ++i) { 59 for (const sk_sp<const SkPDFDevice>& pageDevice : pageDevices) {
60 usage.merge(pageDevices[i]->getFontGlyphUsage()); 60 usage.merge(pageDevice->getFontGlyphUsage());
61 } 61 }
62 SkPDFGlyphSetMap::F2BIter iterator(usage); 62 SkPDFGlyphSetMap::F2BIter iterator(usage);
63 const SkPDFGlyphSetMap::FontGlyphSetPair* entry = iterator.next(); 63 const SkPDFGlyphSetMap::FontGlyphSetPair* entry = iterator.next();
64 while (entry) { 64 while (entry) {
65 sk_sp<SkPDFFont> subsetFont( 65 sk_sp<SkPDFFont> subsetFont(
66 entry->fFont->getFontSubset(entry->fGlyphSet)); 66 entry->fFont->getFontSubset(entry->fGlyphSet));
67 if (subsetFont) { 67 if (subsetFont) {
68 substituteMap->setSubstitute(entry->fFont, subsetFont.get()); 68 substituteMap->setSubstitute(entry->fFont, subsetFont.get());
69 } 69 }
70 entry = iterator.next(); 70 entry = iterator.next();
71 } 71 }
72 } 72 }
73 73
74 static SkPDFObject* create_pdf_page_content(const SkPDFDevice* pageDevice) { 74 static sk_sp<SkPDFDict> create_pdf_page(const SkPDFDevice* pageDevice) {
75 SkAutoTDelete<SkStreamAsset> content(pageDevice->content());
76 return new SkPDFStream(content.get());
77 }
78
79 static SkPDFDict* create_pdf_page(const SkPDFDevice* pageDevice) {
80 auto page = sk_make_sp<SkPDFDict>("Page"); 75 auto page = sk_make_sp<SkPDFDict>("Page");
81 page->insertObject("Resources", pageDevice->createResourceDict()); 76 page->insertObject("Resources", pageDevice->makeResourceDict());
82 page->insertObject("MediaBox", pageDevice->copyMediaBox()); 77 page->insertObject("MediaBox", pageDevice->copyMediaBox());
83 auto annotations = sk_make_sp<SkPDFArray>(); 78 auto annotations = sk_make_sp<SkPDFArray>();
84 pageDevice->appendAnnotations(annotations.get()); 79 pageDevice->appendAnnotations(annotations.get());
85 if (annotations->size() > 0) { 80 if (annotations->size() > 0) {
86 page->insertObject("Annots", annotations.release()); 81 page->insertObject("Annots", std::move(annotations));
87 } 82 }
88 page->insertObjRef("Contents", create_pdf_page_content(pageDevice)); 83 auto content = pageDevice->content();
89 return page.release(); 84 page->insertObjRef("Contents", sk_make_sp<SkPDFStream>(content.get()));
85 return page;
90 } 86 }
91 87
92 static void generate_page_tree(const SkTDArray<SkPDFDict*>& pages, 88 // return root node.
93 SkTDArray<SkPDFDict*>* pageTree, 89 static sk_sp<SkPDFDict> generate_page_tree(
94 SkPDFDict** rootNode) { 90 const SkTDArray<SkPDFDict*>& pages,
91 SkTDArray<SkPDFDict*>* pageTree) {
95 // PDF wants a tree describing all the pages in the document. We arbitrary 92 // PDF wants a tree describing all the pages in the document. We arbitrary
96 // choose 8 (kNodeSize) as the number of allowed children. The internal 93 // choose 8 (kNodeSize) as the number of allowed children. The internal
97 // nodes have type "Pages" with an array of children, a parent pointer, and 94 // nodes have type "Pages" with an array of children, a parent pointer, and
98 // the number of leaves below the node as "Count." The leaves are passed 95 // the number of leaves below the node as "Count." The leaves are passed
99 // into the method, have type "Page" and need a parent pointer. This method 96 // into the method, have type "Page" and need a parent pointer. This method
100 // builds the tree bottom up, skipping internal nodes that would have only 97 // builds the tree bottom up, skipping internal nodes that would have only
101 // one child. 98 // one child.
102 static const int kNodeSize = 8; 99 static const int kNodeSize = 8;
103 100
104 // curNodes takes a reference to its items, which it passes to pageTree. 101 // curNodes takes a reference to its items, which it passes to pageTree.
(...skipping 15 matching lines...) Expand all
120 nextRoundNodes.push(curNodes[i]); 117 nextRoundNodes.push(curNodes[i]);
121 break; 118 break;
122 } 119 }
123 120
124 auto newNode = sk_make_sp<SkPDFDict>("Pages"); 121 auto newNode = sk_make_sp<SkPDFDict>("Pages");
125 auto kids = sk_make_sp<SkPDFArray>(); 122 auto kids = sk_make_sp<SkPDFArray>();
126 kids->reserve(kNodeSize); 123 kids->reserve(kNodeSize);
127 124
128 int count = 0; 125 int count = 0;
129 for (; i < curNodes.count() && count < kNodeSize; i++, count++) { 126 for (; i < curNodes.count() && count < kNodeSize; i++, count++) {
130 curNodes[i]->insertObjRef("Parent", SkRef(newNode.get())); 127 curNodes[i]->insertObjRef("Parent", newNode);
131 kids->appendObjRef(SkRef(curNodes[i])); 128 kids->appendObjRef(sk_sp<SkPDFDict>(SkRef(curNodes[i])));
132 129
133 // TODO(vandebo): put the objects in strict access order. 130 // TODO(vandebo): put the objects in strict access order.
134 // Probably doesn't matter because they are so small. 131 // Probably doesn't matter because they are so small.
135 if (curNodes[i] != pages[0]) { 132 if (curNodes[i] != pages[0]) {
136 pageTree->push(curNodes[i]); // Transfer reference. 133 pageTree->push(curNodes[i]); // Transfer reference.
137 } else { 134 } else {
138 SkSafeUnref(curNodes[i]); 135 SkSafeUnref(curNodes[i]);
139 } 136 }
140 } 137 }
141 138
142 // treeCapacity is the number of leaf nodes possible for the 139 // treeCapacity is the number of leaf nodes possible for the
143 // current set of subtrees being generated. (i.e. 8, 64, 512, ...). 140 // current set of subtrees being generated. (i.e. 8, 64, 512, ...).
144 // It is hard to count the number of leaf nodes in the current 141 // It is hard to count the number of leaf nodes in the current
145 // subtree. However, by construction, we know that unless it's the 142 // subtree. However, by construction, we know that unless it's the
146 // last subtree for the current depth, the leaf count will be 143 // last subtree for the current depth, the leaf count will be
147 // treeCapacity, otherwise it's what ever is left over after 144 // treeCapacity, otherwise it's what ever is left over after
148 // consuming treeCapacity chunks. 145 // consuming treeCapacity chunks.
149 int pageCount = treeCapacity; 146 int pageCount = treeCapacity;
150 if (i == curNodes.count()) { 147 if (i == curNodes.count()) {
151 pageCount = ((pages.count() - 1) % treeCapacity) + 1; 148 pageCount = ((pages.count() - 1) % treeCapacity) + 1;
152 } 149 }
153 newNode->insertInt("Count", pageCount); 150 newNode->insertInt("Count", pageCount);
154 newNode->insertObject("Kids", kids.release()); 151 newNode->insertObject("Kids", std::move(kids));
155 nextRoundNodes.push(newNode.release()); // Transfer reference. 152 nextRoundNodes.push(newNode.release()); // Transfer reference.
156 } 153 }
157 154
158 curNodes = nextRoundNodes; 155 curNodes = nextRoundNodes;
159 nextRoundNodes.rewind(); 156 nextRoundNodes.rewind();
160 treeCapacity *= kNodeSize; 157 treeCapacity *= kNodeSize;
161 } while (curNodes.count() > 1); 158 } while (curNodes.count() > 1);
162 159
163 pageTree->push(curNodes[0]); // Transfer reference. 160 pageTree->push(curNodes[0]); // Transfer reference.
164 if (rootNode) { 161 return sk_sp<SkPDFDict>(SkRef(curNodes[0]));
165 *rootNode = curNodes[0];
166 }
167 } 162 }
168 163
169 static bool emit_pdf_document(const SkTDArray<const SkPDFDevice*>& pageDevices, 164 static bool emit_pdf_document(const SkTArray<sk_sp<const SkPDFDevice>>& pageDevi ces,
170 const SkPDFMetadata& metadata, 165 const SkPDFMetadata& metadata,
171 SkWStream* stream) { 166 SkWStream* stream) {
172 if (pageDevices.isEmpty()) { 167 if (pageDevices.empty()) {
173 return false; 168 return false;
174 } 169 }
175 170
176 SkTDArray<SkPDFDict*> pages; 171 SkTDArray<SkPDFDict*> pages; // TODO: SkTArray<sk_sp<SkPDFDict>>
177 auto dests = sk_make_sp<SkPDFDict>(); 172 auto dests = sk_make_sp<SkPDFDict>();
178 173
179 for (int i = 0; i < pageDevices.count(); i++) { 174 for (const sk_sp<const SkPDFDevice>& pageDevice : pageDevices) {
180 SkASSERT(pageDevices[i]); 175 SkASSERT(pageDevice);
181 SkASSERT(i == 0 || 176 SkASSERT(pageDevices[0]->getCanon() == pageDevice->getCanon());
182 pageDevices[i - 1]->getCanon() == pageDevices[i]->getCanon()); 177 sk_sp<SkPDFDict> page(create_pdf_page(pageDevice.get()));
183 sk_sp<SkPDFDict> page(create_pdf_page(pageDevices[i])); 178 pageDevice->appendDestinations(dests.get(), page.get());
184 pageDevices[i]->appendDestinations(dests.get(), page.get());
185 pages.push(page.release()); 179 pages.push(page.release());
186 } 180 }
187 181
188 auto docCatalog = sk_make_sp<SkPDFDict>("Catalog"); 182 auto docCatalog = sk_make_sp<SkPDFDict>("Catalog");
189 183
190 sk_sp<SkPDFObject> infoDict( 184 sk_sp<SkPDFObject> infoDict(metadata.createDocumentInformationDict());
191 metadata.createDocumentInformationDict());
192 185
193 sk_sp<SkPDFObject> id, xmp; 186 sk_sp<SkPDFObject> id, xmp;
194 #ifdef SK_PDF_GENERATE_PDFA 187 #ifdef SK_PDF_GENERATE_PDFA
195 SkPDFMetadata::UUID uuid = metadata.uuid(); 188 SkPDFMetadata::UUID uuid = metadata.uuid();
196 // We use the same UUID for Document ID and Instance ID since this 189 // We use the same UUID for Document ID and Instance ID since this
197 // is the first revision of this document (and Skia does not 190 // is the first revision of this document (and Skia does not
198 // support revising existing PDF documents). 191 // support revising existing PDF documents).
199 // If we are not in PDF/A mode, don't use a UUID since testing 192 // If we are not in PDF/A mode, don't use a UUID since testing
200 // works best with reproducible outputs. 193 // works best with reproducible outputs.
201 id.reset(SkPDFMetadata::CreatePdfId(uuid, uuid)); 194 id.reset(SkPDFMetadata::CreatePdfId(uuid, uuid));
202 xmp.reset(metadata.createXMPObject(uuid, uuid)); 195 xmp.reset(metadata.createXMPObject(uuid, uuid));
203 docCatalog->insertObjRef("Metadata", xmp.release()); 196 docCatalog->insertObjRef("Metadata", std::move(xmp));
204 197
205 // sRGB is specified by HTML, CSS, and SVG. 198 // sRGB is specified by HTML, CSS, and SVG.
206 auto outputIntent = sk_make_sp<SkPDFDict>("OutputIntent"); 199 auto outputIntent = sk_make_sp<SkPDFDict>("OutputIntent");
207 outputIntent->insertName("S", "GTS_PDFA1"); 200 outputIntent->insertName("S", "GTS_PDFA1");
208 outputIntent->insertString("RegistryName", "http://www.color.org"); 201 outputIntent->insertString("RegistryName", "http://www.color.org");
209 outputIntent->insertString("OutputConditionIdentifier", 202 outputIntent->insertString("OutputConditionIdentifier",
210 "sRGB IEC61966-2.1"); 203 "sRGB IEC61966-2.1");
211 auto intentArray = sk_make_sp<SkPDFArray>(); 204 auto intentArray = sk_make_sp<SkPDFArray>();
212 intentArray->appendObject(outputIntent.release()); 205 intentArray->appendObject(std::move(outputIntent));
213 // Don't specify OutputIntents if we are not in PDF/A mode since 206 // Don't specify OutputIntents if we are not in PDF/A mode since
214 // no one has ever asked for this feature. 207 // no one has ever asked for this feature.
215 docCatalog->insertObject("OutputIntents", intentArray.release()); 208 docCatalog->insertObject("OutputIntents", std::move(intentArray));
216 #endif 209 #endif
217 210
218 SkTDArray<SkPDFDict*> pageTree; 211 SkTDArray<SkPDFDict*> pageTree;
219 SkPDFDict* pageTreeRoot; 212 docCatalog->insertObjRef("Pages", generate_page_tree(pages, &pageTree));
220 generate_page_tree(pages, &pageTree, &pageTreeRoot);
221 docCatalog->insertObjRef("Pages", SkRef(pageTreeRoot));
222 213
223 if (dests->size() > 0) { 214 if (dests->size() > 0) {
224 docCatalog->insertObjRef("Dests", dests.release()); 215 docCatalog->insertObjRef("Dests", std::move(dests));
225 } 216 }
226 217
227 // Build font subsetting info before proceeding. 218 // Build font subsetting info before proceeding.
228 SkPDFSubstituteMap substitutes; 219 SkPDFSubstituteMap substitutes;
229 perform_font_subsetting(pageDevices, &substitutes); 220 perform_font_subsetting(pageDevices, &substitutes);
230 221
231 SkPDFObjNumMap objNumMap; 222 SkPDFObjNumMap objNumMap;
232 objNumMap.addObjectRecursively(infoDict.get(), substitutes); 223 objNumMap.addObjectRecursively(infoDict.get(), substitutes);
233 objNumMap.addObjectRecursively(docCatalog.get(), substitutes); 224 objNumMap.addObjectRecursively(docCatalog.get(), substitutes);
234 size_t baseOffset = stream->bytesWritten(); 225 size_t baseOffset = stream->bytesWritten();
(...skipping 20 matching lines...) Expand all
255 246
256 stream->writeText("xref\n0 "); 247 stream->writeText("xref\n0 ");
257 stream->writeDecAsText(objCount); 248 stream->writeDecAsText(objCount);
258 stream->writeText("\n0000000000 65535 f \n"); 249 stream->writeText("\n0000000000 65535 f \n");
259 for (int i = 0; i < offsets.count(); i++) { 250 for (int i = 0; i < offsets.count(); i++) {
260 SkASSERT(offsets[i] > 0); 251 SkASSERT(offsets[i] > 0);
261 stream->writeBigDecAsText(offsets[i], 10); 252 stream->writeBigDecAsText(offsets[i], 10);
262 stream->writeText(" 00000 n \n"); 253 stream->writeText(" 00000 n \n");
263 } 254 }
264 emit_pdf_footer(stream, objNumMap, substitutes, docCatalog.get(), objCount, 255 emit_pdf_footer(stream, objNumMap, substitutes, docCatalog.get(), objCount,
265 xRefFileOffset, infoDict.release(), id.release()); 256 xRefFileOffset, std::move(infoDict), std::move(id));
266 257
267 // The page tree has both child and parent pointers, so it creates a 258 // The page tree has both child and parent pointers, so it creates a
268 // reference cycle. We must clear that cycle to properly reclaim memory. 259 // reference cycle. We must clear that cycle to properly reclaim memory.
269 for (int i = 0; i < pageTree.count(); i++) { 260 for (int i = 0; i < pageTree.count(); i++) {
270 pageTree[i]->clear(); 261 pageTree[i]->clear();
271 } 262 }
272 pageTree.safeUnrefAll(); 263 pageTree.safeUnrefAll();
273 pages.unrefAll(); 264 pages.unrefAll();
274 return true; 265 return true;
275 } 266 }
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
337 protected: 328 protected:
338 SkCanvas* onBeginPage(SkScalar width, SkScalar height, 329 SkCanvas* onBeginPage(SkScalar width, SkScalar height,
339 const SkRect& trimBox) override { 330 const SkRect& trimBox) override {
340 SkASSERT(!fCanvas.get()); 331 SkASSERT(!fCanvas.get());
341 332
342 SkISize pageSize = SkISize::Make( 333 SkISize pageSize = SkISize::Make(
343 SkScalarRoundToInt(width), SkScalarRoundToInt(height)); 334 SkScalarRoundToInt(width), SkScalarRoundToInt(height));
344 sk_sp<SkPDFDevice> device( 335 sk_sp<SkPDFDevice> device(
345 SkPDFDevice::Create(pageSize, fRasterDpi, &fCanon)); 336 SkPDFDevice::Create(pageSize, fRasterDpi, &fCanon));
346 fCanvas.reset(new SkCanvas(device.get())); 337 fCanvas.reset(new SkCanvas(device.get()));
347 fPageDevices.push(device.release()); 338 fPageDevices.push_back(std::move(device));
348 fCanvas->clipRect(trimBox); 339 fCanvas->clipRect(trimBox);
349 fCanvas->translate(trimBox.x(), trimBox.y()); 340 fCanvas->translate(trimBox.x(), trimBox.y());
350 return fCanvas.get(); 341 return fCanvas.get();
351 } 342 }
352 343
353 void onEndPage() override { 344 void onEndPage() override {
354 SkASSERT(fCanvas.get()); 345 SkASSERT(fCanvas.get());
355 fCanvas->flush(); 346 fCanvas->flush();
356 fCanvas.reset(nullptr); 347 fCanvas.reset(nullptr);
357 } 348 }
358 349
359 bool onClose(SkWStream* stream) override { 350 bool onClose(SkWStream* stream) override {
360 SkASSERT(!fCanvas.get()); 351 SkASSERT(!fCanvas.get());
361 352
362 bool success = emit_pdf_document(fPageDevices, fMetadata, stream); 353 bool success = emit_pdf_document(fPageDevices, fMetadata, stream);
363 fPageDevices.unrefAll(); 354 fPageDevices.reset();
364 fCanon.reset(); 355 fCanon.reset();
365 return success; 356 return success;
366 } 357 }
367 358
368 void onAbort() override { 359 void onAbort() override {
369 fPageDevices.unrefAll(); 360 fPageDevices.reset();
370 fCanon.reset(); 361 fCanon.reset();
371 } 362 }
372 363
373 void setMetadata(const SkDocument::Attribute info[], 364 void setMetadata(const SkDocument::Attribute info[],
374 int infoCount, 365 int infoCount,
375 const SkTime::DateTime* creationDate, 366 const SkTime::DateTime* creationDate,
376 const SkTime::DateTime* modifiedDate) override { 367 const SkTime::DateTime* modifiedDate) override {
377 fMetadata.fInfo.reset(info, infoCount); 368 fMetadata.fInfo.reset(info, infoCount);
378 fMetadata.fCreation.reset(clone(creationDate)); 369 fMetadata.fCreation.reset(clone(creationDate));
379 fMetadata.fModified.reset(clone(modifiedDate)); 370 fMetadata.fModified.reset(clone(modifiedDate));
380 } 371 }
381 372
382 private: 373 private:
383 SkPDFCanon fCanon; 374 SkPDFCanon fCanon;
384 SkTDArray<const SkPDFDevice*> fPageDevices; 375 SkTArray<sk_sp<const SkPDFDevice>> fPageDevices;
385 sk_sp<SkCanvas> fCanvas; 376 sk_sp<SkCanvas> fCanvas;
386 SkScalar fRasterDpi; 377 SkScalar fRasterDpi;
387 SkPDFMetadata fMetadata; 378 SkPDFMetadata fMetadata;
388 }; 379 };
389 } // namespace 380 } // namespace
390 /////////////////////////////////////////////////////////////////////////////// 381 ///////////////////////////////////////////////////////////////////////////////
391 382
392 SkDocument* SkDocument::CreatePDF(SkWStream* stream, SkScalar dpi) { 383 SkDocument* SkDocument::CreatePDF(SkWStream* stream, SkScalar dpi) {
393 return stream ? new SkDocument_PDF(stream, nullptr, dpi, nullptr) : nullptr; 384 return stream ? new SkDocument_PDF(stream, nullptr, dpi, nullptr) : nullptr;
394 } 385 }
395 386
396 SkDocument* SkDocument::CreatePDF(SkWStream* stream, 387 SkDocument* SkDocument::CreatePDF(SkWStream* stream,
397 SkScalar dpi, 388 SkScalar dpi,
398 SkPixelSerializer* jpegEncoder) { 389 SkPixelSerializer* jpegEncoder) {
399 return stream 390 return stream
400 ? new SkDocument_PDF(stream, nullptr, dpi, jpegEncoder) 391 ? new SkDocument_PDF(stream, nullptr, dpi, jpegEncoder)
401 : nullptr; 392 : nullptr;
402 } 393 }
403 394
404 SkDocument* SkDocument::CreatePDF(const char path[], SkScalar dpi) { 395 SkDocument* SkDocument::CreatePDF(const char path[], SkScalar dpi) {
405 SkFILEWStream* stream = new SkFILEWStream(path); 396 SkFILEWStream* stream = new SkFILEWStream(path);
406 if (!stream->isValid()) { 397 if (!stream->isValid()) {
407 delete stream; 398 delete stream;
408 return nullptr; 399 return nullptr;
409 } 400 }
410 auto delete_wstream = [](SkWStream* stream, bool) { delete stream; }; 401 auto delete_wstream = [](SkWStream* stream, bool) { delete stream; };
411 return new SkDocument_PDF(stream, delete_wstream, dpi, nullptr); 402 return new SkDocument_PDF(stream, delete_wstream, dpi, nullptr);
412 } 403 }
OLDNEW
« no previous file with comments | « no previous file | src/pdf/SkPDFBitmap.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698