OLD | NEW |
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 Loading... |
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 Loading... |
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 SkPDFObjectSet 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 fCatalog->emitObjectNumber(stream, object); |
198 out.stream((*fFirstPageResources)[i]); | 175 stream->writeText(" obj\n"); |
| 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 |
236 bool SkPDFDocument::setPage(int pageNumber, SkPDFDevice* pdfDevice) { | 185 bool SkPDFDocument::setPage(int pageNumber, SkPDFDevice* pdfDevice) { |
237 if (!fPageTree.isEmpty()) { | 186 if (!fPageTree.isEmpty()) { |
238 return false; | 187 return false; |
239 } | 188 } |
240 | 189 |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
349 fTrailerDict->insertInt("Size", int(objCount)); | 298 fTrailerDict->insertInt("Size", int(objCount)); |
350 fTrailerDict->insert("Root", new SkPDFObjRef(fDocCatalog))->unref(); | 299 fTrailerDict->insert("Root", new SkPDFObjRef(fDocCatalog))->unref(); |
351 } | 300 } |
352 | 301 |
353 stream->writeText("trailer\n"); | 302 stream->writeText("trailer\n"); |
354 fTrailerDict->emitObject(stream, fCatalog.get()); | 303 fTrailerDict->emitObject(stream, fCatalog.get()); |
355 stream->writeText("\nstartxref\n"); | 304 stream->writeText("\nstartxref\n"); |
356 stream->writeBigDecAsText(fXRefFileOffset); | 305 stream->writeBigDecAsText(fXRefFileOffset); |
357 stream->writeText("\n%%EOF"); | 306 stream->writeText("\n%%EOF"); |
358 } | 307 } |
OLD | NEW |