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

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

Issue 1772493002: SkPDF: AutoTUnref<T> changes in use (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: 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 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
74 static SkPDFObject* create_pdf_page_content(const SkPDFDevice* pageDevice) { 74 static SkPDFObject* create_pdf_page_content(const SkPDFDevice* pageDevice) {
75 SkAutoTDelete<SkStreamAsset> content(pageDevice->content()); 75 SkAutoTDelete<SkStreamAsset> content(pageDevice->content());
76 return new SkPDFStream(content.get()); 76 return new SkPDFStream(content.get());
77 } 77 }
78 78
79 static SkPDFDict* create_pdf_page(const SkPDFDevice* pageDevice) { 79 static SkPDFDict* create_pdf_page(const SkPDFDevice* pageDevice) {
80 SkAutoTUnref<SkPDFDict> page(new SkPDFDict("Page")); 80 SkAutoTUnref<SkPDFDict> page(new SkPDFDict("Page"));
81 page->insertObject("Resources", pageDevice->createResourceDict()); 81 page->insertObject("Resources", pageDevice->createResourceDict());
82 page->insertObject("MediaBox", pageDevice->copyMediaBox()); 82 page->insertObject("MediaBox", pageDevice->copyMediaBox());
83 SkAutoTUnref<SkPDFArray> annotations(new SkPDFArray); 83 SkAutoTUnref<SkPDFArray> annotations(new SkPDFArray);
84 pageDevice->appendAnnotations(annotations); 84 pageDevice->appendAnnotations(annotations.get());
85 if (annotations->size() > 0) { 85 if (annotations->size() > 0) {
86 page->insertObject("Annots", annotations.detach()); 86 page->insertObject("Annots", annotations.release());
87 } 87 }
88 page->insertObjRef("Contents", create_pdf_page_content(pageDevice)); 88 page->insertObjRef("Contents", create_pdf_page_content(pageDevice));
89 return page.detach(); 89 return page.release();
90 } 90 }
91 91
92 static void generate_page_tree(const SkTDArray<SkPDFDict*>& pages, 92 static void generate_page_tree(const SkTDArray<SkPDFDict*>& pages,
93 SkTDArray<SkPDFDict*>* pageTree, 93 SkTDArray<SkPDFDict*>* pageTree,
94 SkPDFDict** rootNode) { 94 SkPDFDict** rootNode) {
95 // PDF wants a tree describing all the pages in the document. We arbitrary 95 // 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 96 // 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 97 // 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 98 // 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 99 // into the method, have type "Page" and need a parent pointer. This method
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
144 // It is hard to count the number of leaf nodes in the current 144 // 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 145 // subtree. However, by construction, we know that unless it's the
146 // last subtree for the current depth, the leaf count will be 146 // last subtree for the current depth, the leaf count will be
147 // treeCapacity, otherwise it's what ever is left over after 147 // treeCapacity, otherwise it's what ever is left over after
148 // consuming treeCapacity chunks. 148 // consuming treeCapacity chunks.
149 int pageCount = treeCapacity; 149 int pageCount = treeCapacity;
150 if (i == curNodes.count()) { 150 if (i == curNodes.count()) {
151 pageCount = ((pages.count() - 1) % treeCapacity) + 1; 151 pageCount = ((pages.count() - 1) % treeCapacity) + 1;
152 } 152 }
153 newNode->insertInt("Count", pageCount); 153 newNode->insertInt("Count", pageCount);
154 newNode->insertObject("Kids", kids.detach()); 154 newNode->insertObject("Kids", kids.release());
155 nextRoundNodes.push(newNode.detach()); // Transfer reference. 155 nextRoundNodes.push(newNode.release()); // Transfer reference.
156 } 156 }
157 157
158 curNodes = nextRoundNodes; 158 curNodes = nextRoundNodes;
159 nextRoundNodes.rewind(); 159 nextRoundNodes.rewind();
160 treeCapacity *= kNodeSize; 160 treeCapacity *= kNodeSize;
161 } while (curNodes.count() > 1); 161 } while (curNodes.count() > 1);
162 162
163 pageTree->push(curNodes[0]); // Transfer reference. 163 pageTree->push(curNodes[0]); // Transfer reference.
164 if (rootNode) { 164 if (rootNode) {
165 *rootNode = curNodes[0]; 165 *rootNode = curNodes[0];
166 } 166 }
167 } 167 }
168 168
169 static bool emit_pdf_document(const SkTDArray<const SkPDFDevice*>& pageDevices, 169 static bool emit_pdf_document(const SkTDArray<const SkPDFDevice*>& pageDevices,
170 const SkPDFMetadata& metadata, 170 const SkPDFMetadata& metadata,
171 SkWStream* stream) { 171 SkWStream* stream) {
172 if (pageDevices.isEmpty()) { 172 if (pageDevices.isEmpty()) {
173 return false; 173 return false;
174 } 174 }
175 175
176 SkTDArray<SkPDFDict*> pages; 176 SkTDArray<SkPDFDict*> pages;
177 SkAutoTUnref<SkPDFDict> dests(new SkPDFDict); 177 SkAutoTUnref<SkPDFDict> dests(new SkPDFDict);
178 178
179 for (int i = 0; i < pageDevices.count(); i++) { 179 for (int i = 0; i < pageDevices.count(); i++) {
180 SkASSERT(pageDevices[i]); 180 SkASSERT(pageDevices[i]);
181 SkASSERT(i == 0 || 181 SkASSERT(i == 0 ||
182 pageDevices[i - 1]->getCanon() == pageDevices[i]->getCanon()); 182 pageDevices[i - 1]->getCanon() == pageDevices[i]->getCanon());
183 SkAutoTUnref<SkPDFDict> page(create_pdf_page(pageDevices[i])); 183 SkAutoTUnref<SkPDFDict> page(create_pdf_page(pageDevices[i]));
184 pageDevices[i]->appendDestinations(dests, page.get()); 184 pageDevices[i]->appendDestinations(dests.get(), page.get());
185 pages.push(page.detach()); 185 pages.push(page.release());
186 } 186 }
187 187
188 SkAutoTUnref<SkPDFDict> docCatalog(new SkPDFDict("Catalog")); 188 SkAutoTUnref<SkPDFDict> docCatalog(new SkPDFDict("Catalog"));
189 189
190 SkAutoTUnref<SkPDFObject> infoDict( 190 SkAutoTUnref<SkPDFObject> infoDict(
191 metadata.createDocumentInformationDict()); 191 metadata.createDocumentInformationDict());
192 192
193 SkAutoTUnref<SkPDFObject> id, xmp; 193 SkAutoTUnref<SkPDFObject> id, xmp;
194 #ifdef SK_PDF_GENERATE_PDFA 194 #ifdef SK_PDF_GENERATE_PDFA
195 SkPDFMetadata::UUID uuid = metadata.uuid(); 195 SkPDFMetadata::UUID uuid = metadata.uuid();
196 // We use the same UUID for Document ID and Instance ID since this 196 // 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 197 // is the first revision of this document (and Skia does not
198 // support revising existing PDF documents). 198 // support revising existing PDF documents).
199 // If we are not in PDF/A mode, don't use a UUID since testing 199 // If we are not in PDF/A mode, don't use a UUID since testing
200 // works best with reproducible outputs. 200 // works best with reproducible outputs.
201 id.reset(SkPDFMetadata::CreatePdfId(uuid, uuid)); 201 id.reset(SkPDFMetadata::CreatePdfId(uuid, uuid));
202 xmp.reset(metadata.createXMPObject(uuid, uuid)); 202 xmp.reset(metadata.createXMPObject(uuid, uuid));
203 docCatalog->insertObjRef("Metadata", xmp.detach()); 203 docCatalog->insertObjRef("Metadata", xmp.release());
204 204
205 // sRGB is specified by HTML, CSS, and SVG. 205 // sRGB is specified by HTML, CSS, and SVG.
206 SkAutoTUnref<SkPDFDict> outputIntent(new SkPDFDict("OutputIntent")); 206 SkAutoTUnref<SkPDFDict> outputIntent(new SkPDFDict("OutputIntent"));
207 outputIntent->insertName("S", "GTS_PDFA1"); 207 outputIntent->insertName("S", "GTS_PDFA1");
208 outputIntent->insertString("RegistryName", "http://www.color.org"); 208 outputIntent->insertString("RegistryName", "http://www.color.org");
209 outputIntent->insertString("OutputConditionIdentifier", 209 outputIntent->insertString("OutputConditionIdentifier",
210 "sRGB IEC61966-2.1"); 210 "sRGB IEC61966-2.1");
211 SkAutoTUnref<SkPDFArray> intentArray(new SkPDFArray); 211 SkAutoTUnref<SkPDFArray> intentArray(new SkPDFArray);
212 intentArray->appendObject(outputIntent.detach()); 212 intentArray->appendObject(outputIntent.release());
213 // Don't specify OutputIntents if we are not in PDF/A mode since 213 // Don't specify OutputIntents if we are not in PDF/A mode since
214 // no one has ever asked for this feature. 214 // no one has ever asked for this feature.
215 docCatalog->insertObject("OutputIntents", intentArray.detach()); 215 docCatalog->insertObject("OutputIntents", intentArray.release());
216 #endif 216 #endif
217 217
218 SkTDArray<SkPDFDict*> pageTree; 218 SkTDArray<SkPDFDict*> pageTree;
219 SkPDFDict* pageTreeRoot; 219 SkPDFDict* pageTreeRoot;
220 generate_page_tree(pages, &pageTree, &pageTreeRoot); 220 generate_page_tree(pages, &pageTree, &pageTreeRoot);
221 docCatalog->insertObjRef("Pages", SkRef(pageTreeRoot)); 221 docCatalog->insertObjRef("Pages", SkRef(pageTreeRoot));
222 222
223 if (dests->size() > 0) { 223 if (dests->size() > 0) {
224 docCatalog->insertObjRef("Dests", dests.detach()); 224 docCatalog->insertObjRef("Dests", dests.release());
225 } 225 }
226 226
227 // Build font subsetting info before proceeding. 227 // Build font subsetting info before proceeding.
228 SkPDFSubstituteMap substitutes; 228 SkPDFSubstituteMap substitutes;
229 perform_font_subsetting(pageDevices, &substitutes); 229 perform_font_subsetting(pageDevices, &substitutes);
230 230
231 SkPDFObjNumMap objNumMap; 231 SkPDFObjNumMap objNumMap;
232 objNumMap.addObjectRecursively(infoDict, substitutes); 232 objNumMap.addObjectRecursively(infoDict.get(), substitutes);
233 objNumMap.addObjectRecursively(docCatalog.get(), substitutes); 233 objNumMap.addObjectRecursively(docCatalog.get(), substitutes);
234 size_t baseOffset = stream->bytesWritten(); 234 size_t baseOffset = stream->bytesWritten();
235 emit_pdf_header(stream); 235 emit_pdf_header(stream);
236 SkTDArray<int32_t> offsets; 236 SkTDArray<int32_t> offsets;
237 for (int i = 0; i < objNumMap.objects().count(); ++i) { 237 for (int i = 0; i < objNumMap.objects().count(); ++i) {
238 SkPDFObject* object = objNumMap.objects()[i]; 238 SkPDFObject* object = objNumMap.objects()[i];
239 size_t offset = stream->bytesWritten(); 239 size_t offset = stream->bytesWritten();
240 // This assert checks that size(pdf_header) > 0 and that 240 // This assert checks that size(pdf_header) > 0 and that
241 // the output stream correctly reports bytesWritten(). 241 // the output stream correctly reports bytesWritten().
242 SkASSERT(offset > baseOffset); 242 SkASSERT(offset > baseOffset);
(...skipping 12 matching lines...) Expand all
255 255
256 stream->writeText("xref\n0 "); 256 stream->writeText("xref\n0 ");
257 stream->writeDecAsText(objCount); 257 stream->writeDecAsText(objCount);
258 stream->writeText("\n0000000000 65535 f \n"); 258 stream->writeText("\n0000000000 65535 f \n");
259 for (int i = 0; i < offsets.count(); i++) { 259 for (int i = 0; i < offsets.count(); i++) {
260 SkASSERT(offsets[i] > 0); 260 SkASSERT(offsets[i] > 0);
261 stream->writeBigDecAsText(offsets[i], 10); 261 stream->writeBigDecAsText(offsets[i], 10);
262 stream->writeText(" 00000 n \n"); 262 stream->writeText(" 00000 n \n");
263 } 263 }
264 emit_pdf_footer(stream, objNumMap, substitutes, docCatalog.get(), objCount, 264 emit_pdf_footer(stream, objNumMap, substitutes, docCatalog.get(), objCount,
265 xRefFileOffset, infoDict.detach(), id.detach()); 265 xRefFileOffset, infoDict.release(), id.release());
266 266
267 // The page tree has both child and parent pointers, so it creates a 267 // 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. 268 // reference cycle. We must clear that cycle to properly reclaim memory.
269 for (int i = 0; i < pageTree.count(); i++) { 269 for (int i = 0; i < pageTree.count(); i++) {
270 pageTree[i]->clear(); 270 pageTree[i]->clear();
271 } 271 }
272 pageTree.safeUnrefAll(); 272 pageTree.safeUnrefAll();
273 pages.unrefAll(); 273 pages.unrefAll();
274 return true; 274 return true;
275 } 275 }
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
319 319
320 namespace { 320 namespace {
321 class SkDocument_PDF : public SkDocument { 321 class SkDocument_PDF : public SkDocument {
322 public: 322 public:
323 SkDocument_PDF(SkWStream* stream, 323 SkDocument_PDF(SkWStream* stream,
324 void (*doneProc)(SkWStream*, bool), 324 void (*doneProc)(SkWStream*, bool),
325 SkScalar rasterDpi, 325 SkScalar rasterDpi,
326 SkPixelSerializer* jpegEncoder) 326 SkPixelSerializer* jpegEncoder)
327 : SkDocument(stream, doneProc) 327 : SkDocument(stream, doneProc)
328 , fRasterDpi(rasterDpi) { 328 , fRasterDpi(rasterDpi) {
329 fCanon.fPixelSerializer.reset(SkSafeRef(jpegEncoder)); 329 fCanon.setPixelSerializer(SkSafeRef(jpegEncoder));
330 } 330 }
331 331
332 virtual ~SkDocument_PDF() { 332 virtual ~SkDocument_PDF() {
333 // subclasses must call close() in their destructors 333 // subclasses must call close() in their destructors
334 this->close(); 334 this->close();
335 } 335 }
336 336
337 protected: 337 protected:
338 SkCanvas* onBeginPage(SkScalar width, SkScalar height, 338 SkCanvas* onBeginPage(SkScalar width, SkScalar height,
339 const SkRect& trimBox) override { 339 const SkRect& trimBox) override {
340 SkASSERT(!fCanvas.get()); 340 SkASSERT(!fCanvas.get());
341 341
342 SkISize pageSize = SkISize::Make( 342 SkISize pageSize = SkISize::Make(
343 SkScalarRoundToInt(width), SkScalarRoundToInt(height)); 343 SkScalarRoundToInt(width), SkScalarRoundToInt(height));
344 SkAutoTUnref<SkPDFDevice> device( 344 SkAutoTUnref<SkPDFDevice> device(
345 SkPDFDevice::Create(pageSize, fRasterDpi, &fCanon)); 345 SkPDFDevice::Create(pageSize, fRasterDpi, &fCanon));
346 fCanvas.reset(new SkCanvas(device.get())); 346 fCanvas.reset(new SkCanvas(device.get()));
347 fPageDevices.push(device.detach()); 347 fPageDevices.push(device.release());
348 fCanvas->clipRect(trimBox); 348 fCanvas->clipRect(trimBox);
349 fCanvas->translate(trimBox.x(), trimBox.y()); 349 fCanvas->translate(trimBox.x(), trimBox.y());
350 return fCanvas.get(); 350 return fCanvas.get();
351 } 351 }
352 352
353 void onEndPage() override { 353 void onEndPage() override {
354 SkASSERT(fCanvas.get()); 354 SkASSERT(fCanvas.get());
355 fCanvas->flush(); 355 fCanvas->flush();
356 fCanvas.reset(nullptr); 356 fCanvas.reset(nullptr);
357 } 357 }
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
403 403
404 SkDocument* SkDocument::CreatePDF(const char path[], SkScalar dpi) { 404 SkDocument* SkDocument::CreatePDF(const char path[], SkScalar dpi) {
405 SkFILEWStream* stream = new SkFILEWStream(path); 405 SkFILEWStream* stream = new SkFILEWStream(path);
406 if (!stream->isValid()) { 406 if (!stream->isValid()) {
407 delete stream; 407 delete stream;
408 return nullptr; 408 return nullptr;
409 } 409 }
410 auto delete_wstream = [](SkWStream* stream, bool) { delete stream; }; 410 auto delete_wstream = [](SkWStream* stream, bool) { delete stream; };
411 return new SkDocument_PDF(stream, delete_wstream, dpi, nullptr); 411 return new SkDocument_PDF(stream, delete_wstream, dpi, nullptr);
412 } 412 }
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