OLD | NEW |
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 "SkPDFCanon.h" | 8 #include "SkPDFCanon.h" |
9 #include "SkPDFDevice.h" | 9 #include "SkPDFDevice.h" |
10 #include "SkPDFDocument.h" | 10 #include "SkPDFDocument.h" |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
217 SkPDFSubstituteMap substitutes; | 217 SkPDFSubstituteMap substitutes; |
218 perform_font_subsetting(pageDevices, &substitutes); | 218 perform_font_subsetting(pageDevices, &substitutes); |
219 | 219 |
220 SkPDFObjNumMap objNumMap; | 220 SkPDFObjNumMap objNumMap; |
221 objNumMap.addObjectRecursively(infoDict.get(), substitutes); | 221 objNumMap.addObjectRecursively(infoDict.get(), substitutes); |
222 objNumMap.addObjectRecursively(docCatalog.get(), substitutes); | 222 objNumMap.addObjectRecursively(docCatalog.get(), substitutes); |
223 size_t baseOffset = stream->bytesWritten(); | 223 size_t baseOffset = stream->bytesWritten(); |
224 emit_pdf_header(stream); | 224 emit_pdf_header(stream); |
225 SkTDArray<int32_t> offsets; | 225 SkTDArray<int32_t> offsets; |
226 for (int i = 0; i < objNumMap.objects().count(); ++i) { | 226 for (int i = 0; i < objNumMap.objects().count(); ++i) { |
227 SkPDFObject* object = objNumMap.objects()[i]; | 227 SkPDFObject* object = objNumMap.objects()[i].get(); |
228 size_t offset = stream->bytesWritten(); | 228 size_t offset = stream->bytesWritten(); |
229 // This assert checks that size(pdf_header) > 0 and that | 229 // This assert checks that size(pdf_header) > 0 and that |
230 // the output stream correctly reports bytesWritten(). | 230 // the output stream correctly reports bytesWritten(). |
231 SkASSERT(offset > baseOffset); | 231 SkASSERT(offset > baseOffset); |
232 offsets.push(SkToS32(offset - baseOffset)); | 232 offsets.push(SkToS32(offset - baseOffset)); |
233 SkASSERT(object == substitutes.getSubstitute(object)); | 233 SkASSERT(object == substitutes.getSubstitute(object)); |
234 SkASSERT(objNumMap.getObjectNumber(object) == i + 1); | 234 SkASSERT(objNumMap.getObjectNumber(object) == i + 1); |
235 stream->writeDecAsText(i + 1); | 235 stream->writeDecAsText(i + 1); |
236 stream->writeText(" 0 obj\n"); // Generation number is always 0. | 236 stream->writeText(" 0 obj\n"); // Generation number is always 0. |
237 object->emitObject(stream, objNumMap, substitutes); | 237 object->emitObject(stream, objNumMap, substitutes); |
238 stream->writeText("\nendobj\n"); | 238 stream->writeText("\nendobj\n"); |
| 239 object->drop(); |
239 } | 240 } |
240 int32_t xRefFileOffset = SkToS32(stream->bytesWritten() - baseOffset); | 241 int32_t xRefFileOffset = SkToS32(stream->bytesWritten() - baseOffset); |
241 | 242 |
242 // Include the zeroth object in the count. | 243 // Include the zeroth object in the count. |
243 int32_t objCount = SkToS32(offsets.count() + 1); | 244 int32_t objCount = SkToS32(offsets.count() + 1); |
244 | 245 |
245 stream->writeText("xref\n0 "); | 246 stream->writeText("xref\n0 "); |
246 stream->writeDecAsText(objCount); | 247 stream->writeDecAsText(objCount); |
247 stream->writeText("\n0000000000 65535 f \n"); | 248 stream->writeText("\n0000000000 65535 f \n"); |
248 for (int i = 0; i < offsets.count(); i++) { | 249 for (int i = 0; i < offsets.count(); i++) { |
249 SkASSERT(offsets[i] > 0); | 250 SkASSERT(offsets[i] > 0); |
250 stream->writeBigDecAsText(offsets[i], 10); | 251 stream->writeBigDecAsText(offsets[i], 10); |
251 stream->writeText(" 00000 n \n"); | 252 stream->writeText(" 00000 n \n"); |
252 } | 253 } |
253 emit_pdf_footer(stream, objNumMap, substitutes, docCatalog.get(), objCount, | 254 emit_pdf_footer(stream, objNumMap, substitutes, docCatalog.get(), objCount, |
254 xRefFileOffset, std::move(infoDict), std::move(id)); | 255 xRefFileOffset, std::move(infoDict), std::move(id)); |
255 | 256 |
256 // The page tree has both child and parent pointers, so it creates a | 257 // The page tree has both child and parent pointers, so it creates a |
257 // reference cycle. We must clear that cycle to properly reclaim memory. | 258 // reference cycle. We must clear that cycle to properly reclaim memory. |
258 for (int i = 0; i < pageTree.count(); i++) { | 259 for (int i = 0; i < pageTree.count(); i++) { |
259 pageTree[i]->clear(); | 260 pageTree[i]->drop(); |
260 } | 261 } |
261 pageTree.safeUnrefAll(); | 262 pageTree.safeUnrefAll(); |
262 pages.unrefAll(); | 263 pages.unrefAll(); |
263 return true; | 264 return true; |
264 } | 265 } |
265 | 266 |
266 #if 0 | 267 #if 0 |
267 // TODO(halcanary): expose notEmbeddableCount in SkDocument | 268 // TODO(halcanary): expose notEmbeddableCount in SkDocument |
268 void GetCountOfFontTypes( | 269 void GetCountOfFontTypes( |
269 const SkTDArray<SkPDFDevice*>& pageDevices, | 270 const SkTDArray<SkPDFDevice*>& pageDevices, |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
395 return SkPDFMakeDocument(stream, nullptr, dpi, jpegEncoder).release(); | 396 return SkPDFMakeDocument(stream, nullptr, dpi, jpegEncoder).release(); |
396 } | 397 } |
397 | 398 |
398 SkDocument* SkDocument::CreatePDF(const char path[], SkScalar dpi) { | 399 SkDocument* SkDocument::CreatePDF(const char path[], SkScalar dpi) { |
399 auto delete_wstream = [](SkWStream* stream, bool) { delete stream; }; | 400 auto delete_wstream = [](SkWStream* stream, bool) { delete stream; }; |
400 SkAutoTDelete<SkFILEWStream> stream(new SkFILEWStream(path)); | 401 SkAutoTDelete<SkFILEWStream> stream(new SkFILEWStream(path)); |
401 return stream->isValid() | 402 return stream->isValid() |
402 ? SkPDFMakeDocument(stream.release(), delete_wstream, dpi, nullptr).rele
ase() | 403 ? SkPDFMakeDocument(stream.release(), delete_wstream, dpi, nullptr).rele
ase() |
403 : nullptr; | 404 : nullptr; |
404 } | 405 } |
OLD | NEW |