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

Side by Side Diff: src/pdf/SkPDFDocument.cpp

Issue 870333002: Simplify reference management in SkPDF (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: make Created 5 years, 10 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 | « src/pdf/SkPDFCatalog.cpp ('k') | src/pdf/SkPDFFont.h » ('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 /* 2 /*
3 * Copyright 2011 Google Inc. 3 * Copyright 2011 Google Inc.
4 * 4 *
5 * Use of this source code is governed by a BSD-style license that can be 5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file. 6 * found in the LICENSE file.
7 */ 7 */
8 8
9 9
10 #include "SkPDFCatalog.h" 10 #include "SkPDFCatalog.h"
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
75 } 75 }
76 76
77 fSubstitutes.safeUnrefAll(); 77 fSubstitutes.safeUnrefAll();
78 78
79 fDocCatalog->unref(); 79 fDocCatalog->unref();
80 SkSafeUnref(fTrailerDict); 80 SkSafeUnref(fTrailerDict);
81 SkDELETE(fFirstPageResources); 81 SkDELETE(fFirstPageResources);
82 SkDELETE(fOtherPageResources); 82 SkDELETE(fOtherPageResources);
83 } 83 }
84 84
85 namespace {
86 class Streamer {
87 public:
88 Streamer(SkPDFCatalog* cat, SkWStream* out)
89 : fCat(cat), fOut(out), fBaseOffset(SkToOffT(out->bytesWritten())) {
90 }
91
92 void stream(SkPDFObject* object) {
93 fCat->setFileOffset(object, this->offset());
94 SkPDFObject* realObject = fCat->getSubstituteObject(object);
95 fCat->emitObjectNumber(fOut, realObject);
96 fOut->writeText(" obj\n");
97 realObject->emitObject(fOut, fCat);
98 fOut->writeText("\nendobj\n");
99 }
100
101 off_t offset() {
102 return SkToOffT(fOut->bytesWritten()) - fBaseOffset;
103 }
104
105 private:
106 SkPDFCatalog* const fCat;
107 SkWStream* const fOut;
108 const off_t fBaseOffset;
109 };
110 } // namespace
111
112 bool SkPDFDocument::emitPDF(SkWStream* stream) { 85 bool SkPDFDocument::emitPDF(SkWStream* stream) {
113 if (fPages.isEmpty()) { 86 if (fPages.isEmpty()) {
114 return false; 87 return false;
115 } 88 }
116 for (int i = 0; i < fPages.count(); i++) { 89 for (int i = 0; i < fPages.count(); i++) {
117 if (fPages[i] == NULL) { 90 if (fPages[i] == NULL) {
118 return false; 91 return false;
119 } 92 }
120 } 93 }
121 94
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
180 SkPDFDict* raw_dests = dests.get(); 153 SkPDFDict* raw_dests = dests.get();
181 fFirstPageResources->add(dests.detach()); // Transfer ownership. 154 fFirstPageResources->add(dests.detach()); // Transfer ownership.
182 fCatalog->addObject(raw_dests, true /* onFirstPage */); 155 fCatalog->addObject(raw_dests, true /* onFirstPage */);
183 fDocCatalog->insert("Dests", SkNEW_ARGS(SkPDFObjRef, (raw_dests)))-> unref(); 156 fDocCatalog->insert("Dests", SkNEW_ARGS(SkPDFObjRef, (raw_dests)))-> unref();
184 } 157 }
185 158
186 // Build font subsetting info before proceeding. 159 // Build font subsetting info before proceeding.
187 perform_font_subsetting(fCatalog.get(), fPages, &fSubstitutes); 160 perform_font_subsetting(fCatalog.get(), fPages, &fSubstitutes);
188 } 161 }
189 162
190 Streamer out(fCatalog, stream); 163 SkTSet<SkPDFObject*> resourceSet;
164 if (resourceSet.add(fDocCatalog)) {
165 fDocCatalog->addResources(&resourceSet, fCatalog);
166 }
167 off_t baseOffset = SkToOffT(stream->bytesWritten());
191 emitHeader(stream); 168 emitHeader(stream);
192 169 for (int i = 0; i < resourceSet.count(); ++i) {
193 out.stream(fDocCatalog); 170 SkPDFObject* object = resourceSet[i];
194 out.stream(fPages[0]); 171 fCatalog->setFileOffset(object,
195 out.stream(fPages[0]->getContentStream()); 172 SkToOffT(stream->bytesWritten()) - baseOffset);
196 173 SkASSERT(object == fCatalog->getSubstituteObject(object));
197 for (int i = 0; i < fFirstPageResources->count(); i++) { 174 stream->writeDecAsText(fCatalog->getObjectNumber(object));
198 out.stream((*fFirstPageResources)[i]); 175 stream->writeText(" 0 obj\n"); // Generation number is always 0.
176 object->emitObject(stream, fCatalog);
177 stream->writeText("\nendobj\n");
199 } 178 }
200 179 fXRefFileOffset = SkToOffT(stream->bytesWritten()) - baseOffset;
201 SkTSet<SkPDFObject*>* firstPageSubstituteResources =
202 fCatalog->getSubstituteList(true);
203 for (int i = 0; i < firstPageSubstituteResources->count(); ++i) {
204 out.stream((*firstPageSubstituteResources)[i]);
205 }
206 // TODO(vandebo): Support linearized format
207 // if (fPages.size() > 1) {
208 // // TODO(vandebo): Save the file offset for the first page xref table.
209 // fCatalog->emitXrefTable(stream, true);
210 // }
211
212 for (int i = 0; i < fPageTree.count(); i++) {
213 out.stream(fPageTree[i]);
214 }
215
216 for (int i = 1; i < fPages.count(); i++) {
217 out.stream(fPages[i]->getContentStream());
218 }
219
220 for (int i = 0; i < fOtherPageResources->count(); i++) {
221 out.stream((*fOtherPageResources)[i]);
222 }
223
224 SkTSet<SkPDFObject*>* otherSubstituteResources =
225 fCatalog->getSubstituteList(false);
226 for (int i = 0; i < otherSubstituteResources->count(); ++i) {
227 out.stream((*otherSubstituteResources)[i]);
228 }
229
230 fXRefFileOffset = out.offset();
231 int64_t objCount = fCatalog->emitXrefTable(stream, fPages.count() > 1); 180 int64_t objCount = fCatalog->emitXrefTable(stream, fPages.count() > 1);
232 emitFooter(stream, objCount); 181 emitFooter(stream, objCount);
233 return true; 182 return true;
234 } 183 }
235 184
185 // TODO(halcanary): remove this method, since it is unused.
236 bool SkPDFDocument::setPage(int pageNumber, SkPDFDevice* pdfDevice) { 186 bool SkPDFDocument::setPage(int pageNumber, SkPDFDevice* pdfDevice) {
237 if (!fPageTree.isEmpty()) { 187 if (!fPageTree.isEmpty()) {
238 return false; 188 return false;
239 } 189 }
240 190
241 pageNumber--; 191 pageNumber--;
242 SkASSERT(pageNumber >= 0); 192 SkASSERT(pageNumber >= 0);
243 193
244 if (pageNumber >= fPages.count()) { 194 if (pageNumber >= fPages.count()) {
245 int oldSize = fPages.count(); 195 int oldSize = fPages.count();
(...skipping 13 matching lines...) Expand all
259 if (!fPageTree.isEmpty()) { 209 if (!fPageTree.isEmpty()) {
260 return false; 210 return false;
261 } 211 }
262 212
263 SkPDFPage* page = new SkPDFPage(pdfDevice); 213 SkPDFPage* page = new SkPDFPage(pdfDevice);
264 fPages.push(page); // Reference from new passed to fPages. 214 fPages.push(page); // Reference from new passed to fPages.
265 return true; 215 return true;
266 } 216 }
267 217
268 // Deprecated. 218 // Deprecated.
219 // TODO(halcanary): remove
269 void SkPDFDocument::getCountOfFontTypes( 220 void SkPDFDocument::getCountOfFontTypes(
270 int counts[SkAdvancedTypefaceMetrics::kOther_Font + 2]) const { 221 int counts[SkAdvancedTypefaceMetrics::kOther_Font + 2]) const {
271 sk_bzero(counts, sizeof(int) * 222 sk_bzero(counts, sizeof(int) *
272 (SkAdvancedTypefaceMetrics::kOther_Font + 2)); 223 (SkAdvancedTypefaceMetrics::kOther_Font + 2));
273 SkTDArray<SkFontID> seenFonts; 224 SkTDArray<SkFontID> seenFonts;
274 int notEmbeddable = 0; 225 int notEmbeddable = 0;
275 226
276 for (int pageNumber = 0; pageNumber < fPages.count(); pageNumber++) { 227 for (int pageNumber = 0; pageNumber < fPages.count(); pageNumber++) {
277 const SkTDArray<SkPDFFont*>& fontResources = 228 const SkTDArray<SkPDFFont*>& fontResources =
278 fPages[pageNumber]->getFontResources(); 229 fPages[pageNumber]->getFontResources();
279 for (int font = 0; font < fontResources.count(); font++) { 230 for (int font = 0; font < fontResources.count(); font++) {
280 SkFontID fontID = fontResources[font]->typeface()->uniqueID(); 231 SkFontID fontID = fontResources[font]->typeface()->uniqueID();
281 if (seenFonts.find(fontID) == -1) { 232 if (seenFonts.find(fontID) == -1) {
282 counts[fontResources[font]->getType()]++; 233 counts[fontResources[font]->getType()]++;
283 seenFonts.push(fontID); 234 seenFonts.push(fontID);
284 if (!fontResources[font]->canEmbed()) { 235 if (!fontResources[font]->canEmbed()) {
285 notEmbeddable++; 236 notEmbeddable++;
286 } 237 }
287 } 238 }
288 } 239 }
289 } 240 }
290 counts[SkAdvancedTypefaceMetrics::kOther_Font + 1] = notEmbeddable; 241 counts[SkAdvancedTypefaceMetrics::kOther_Font + 1] = notEmbeddable;
291 } 242 }
292 243
244 // TODO(halcanary): expose notEmbeddableCount in SkDocument
293 void SkPDFDocument::getCountOfFontTypes( 245 void SkPDFDocument::getCountOfFontTypes(
294 int counts[SkAdvancedTypefaceMetrics::kOther_Font + 1], 246 int counts[SkAdvancedTypefaceMetrics::kOther_Font + 1],
295 int* notSubsettableCount, 247 int* notSubsettableCount,
296 int* notEmbeddableCount) const { 248 int* notEmbeddableCount) const {
297 sk_bzero(counts, sizeof(int) * 249 sk_bzero(counts, sizeof(int) *
298 (SkAdvancedTypefaceMetrics::kOther_Font + 1)); 250 (SkAdvancedTypefaceMetrics::kOther_Font + 1));
299 SkTDArray<SkFontID> seenFonts; 251 SkTDArray<SkFontID> seenFonts;
300 int notSubsettable = 0; 252 int notSubsettable = 0;
301 int notEmbeddable = 0; 253 int notEmbeddable = 0;
302 254
(...skipping 24 matching lines...) Expand all
327 } 279 }
328 280
329 void SkPDFDocument::emitHeader(SkWStream* stream) { 281 void SkPDFDocument::emitHeader(SkWStream* stream) {
330 stream->writeText("%PDF-1.4\n%"); 282 stream->writeText("%PDF-1.4\n%");
331 // The PDF spec recommends including a comment with four bytes, all 283 // The PDF spec recommends including a comment with four bytes, all
332 // with their high bits set. This is "Skia" with the high bits set. 284 // with their high bits set. This is "Skia" with the high bits set.
333 stream->write32(0xD3EBE9E1); 285 stream->write32(0xD3EBE9E1);
334 stream->writeText("\n"); 286 stream->writeText("\n");
335 } 287 }
336 288
289 //TODO(halcanary): remove this function
337 size_t SkPDFDocument::headerSize() { 290 size_t SkPDFDocument::headerSize() {
338 SkDynamicMemoryWStream buffer; 291 SkDynamicMemoryWStream buffer;
339 emitHeader(&buffer); 292 emitHeader(&buffer);
340 return buffer.getOffset(); 293 return buffer.getOffset();
341 } 294 }
342 295
343 void SkPDFDocument::emitFooter(SkWStream* stream, int64_t objCount) { 296 void SkPDFDocument::emitFooter(SkWStream* stream, int64_t objCount) {
344 if (NULL == fTrailerDict) { 297 if (NULL == fTrailerDict) {
345 fTrailerDict = SkNEW(SkPDFDict); 298 fTrailerDict = SkNEW(SkPDFDict);
346 299
347 // TODO(vandebo): Linearized format will take a Prev entry too. 300 // TODO(vandebo): Linearized format will take a Prev entry too.
348 // TODO(vandebo): PDF/A requires an ID entry. 301 // TODO(vandebo): PDF/A requires an ID entry.
349 fTrailerDict->insertInt("Size", int(objCount)); 302 fTrailerDict->insertInt("Size", int(objCount));
350 fTrailerDict->insert("Root", new SkPDFObjRef(fDocCatalog))->unref(); 303 fTrailerDict->insert("Root", new SkPDFObjRef(fDocCatalog))->unref();
351 } 304 }
352 305
353 stream->writeText("trailer\n"); 306 stream->writeText("trailer\n");
354 fTrailerDict->emitObject(stream, fCatalog.get()); 307 fTrailerDict->emitObject(stream, fCatalog.get());
355 stream->writeText("\nstartxref\n"); 308 stream->writeText("\nstartxref\n");
356 stream->writeBigDecAsText(fXRefFileOffset); 309 stream->writeBigDecAsText(fXRefFileOffset);
357 stream->writeText("\n%%EOF"); 310 stream->writeText("\n%%EOF");
358 } 311 }
OLDNEW
« no previous file with comments | « src/pdf/SkPDFCatalog.cpp ('k') | src/pdf/SkPDFFont.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698