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* obj) { |
| 93 fCat->setFileOffset(obj, this->offset()); |
| 94 obj->emit(fOut, fCat, true); |
| 95 } |
| 96 |
| 97 off_t offset() { |
| 98 return SkToOffT(fOut->bytesWritten()) - fBaseOffset; |
| 99 } |
| 100 |
| 101 private: |
| 102 SkPDFCatalog* const fCat; |
| 103 SkWStream* const fOut; |
| 104 const off_t fBaseOffset; |
| 105 }; |
| 106 } // namespace |
| 107 |
85 bool SkPDFDocument::emitPDF(SkWStream* stream) { | 108 bool SkPDFDocument::emitPDF(SkWStream* stream) { |
86 if (fPages.isEmpty()) { | 109 if (fPages.isEmpty()) { |
87 return false; | 110 return false; |
88 } | 111 } |
89 for (int i = 0; i < fPages.count(); i++) { | 112 for (int i = 0; i < fPages.count(); i++) { |
90 if (fPages[i] == NULL) { | 113 if (fPages[i] == NULL) { |
91 return false; | 114 return false; |
92 } | 115 } |
93 } | 116 } |
94 | 117 |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
151 | 174 |
152 if (dests->size() > 0) { | 175 if (dests->size() > 0) { |
153 SkPDFDict* raw_dests = dests.get(); | 176 SkPDFDict* raw_dests = dests.get(); |
154 fFirstPageResources->add(dests.detach()); // Transfer ownership. | 177 fFirstPageResources->add(dests.detach()); // Transfer ownership. |
155 fCatalog->addObject(raw_dests, true /* onFirstPage */); | 178 fCatalog->addObject(raw_dests, true /* onFirstPage */); |
156 fDocCatalog->insert("Dests", SkNEW_ARGS(SkPDFObjRef, (raw_dests)))->
unref(); | 179 fDocCatalog->insert("Dests", SkNEW_ARGS(SkPDFObjRef, (raw_dests)))->
unref(); |
157 } | 180 } |
158 | 181 |
159 // Build font subsetting info before proceeding. | 182 // Build font subsetting info before proceeding. |
160 perform_font_subsetting(fCatalog.get(), fPages, &fSubstitutes); | 183 perform_font_subsetting(fCatalog.get(), fPages, &fSubstitutes); |
161 | |
162 // Figure out the size of things and inform the catalog of file offsets. | |
163 off_t fileOffset = SkToOffT(this->headerSize()); | |
164 fileOffset += SkToOffT(fCatalog->setFileOffset(fDocCatalog, fileOffset))
; | |
165 fileOffset += SkToOffT(fCatalog->setFileOffset(fPages[0], fileOffset)); | |
166 fileOffset += fPages[0]->getPageSize(fCatalog.get(), fileOffset); | |
167 for (int i = 0; i < fFirstPageResources->count(); i++) { | |
168 fileOffset += SkToOffT(fCatalog->setFileOffset((*fFirstPageResources
)[i], fileOffset)); | |
169 } | |
170 // Add the size of resources of substitute objects used on page 1. | |
171 fileOffset += fCatalog->setSubstituteResourcesOffsets(fileOffset, true); | |
172 if (fPages.count() > 1) { | |
173 // TODO(vandebo): For linearized format, save the start of the | |
174 // first page xref table and calculate the size. | |
175 } | |
176 | |
177 for (int i = 0; i < fPageTree.count(); i++) { | |
178 fileOffset += SkToOffT(fCatalog->setFileOffset(fPageTree[i], fileOff
set)); | |
179 } | |
180 | |
181 for (int i = 1; i < fPages.count(); i++) { | |
182 fileOffset += fPages[i]->getPageSize(fCatalog.get(), fileOffset); | |
183 } | |
184 | |
185 for (int i = 0; i < fOtherPageResources->count(); i++) { | |
186 fileOffset += SkToOffT(fCatalog->setFileOffset((*fOtherPageResources
)[i], fileOffset)); | |
187 } | |
188 | |
189 fileOffset += fCatalog->setSubstituteResourcesOffsets(fileOffset, false)
; | |
190 fXRefFileOffset = fileOffset; | |
191 } | 184 } |
192 | 185 |
| 186 Streamer out(fCatalog, stream); |
193 emitHeader(stream); | 187 emitHeader(stream); |
194 fDocCatalog->emitIndirectObject(stream, fCatalog.get()); | 188 |
195 fPages[0]->emitIndirectObject(stream, fCatalog.get()); | 189 out.stream(fDocCatalog); |
196 fPages[0]->emitPage(stream, fCatalog.get()); | 190 out.stream(fPages[0]); |
| 191 out.stream(fPages[0]->getContentStream()); |
| 192 |
197 for (int i = 0; i < fFirstPageResources->count(); i++) { | 193 for (int i = 0; i < fFirstPageResources->count(); i++) { |
198 (*fFirstPageResources)[i]->emit(stream, fCatalog.get(), true); | 194 out.stream((*fFirstPageResources)[i]); |
199 } | 195 } |
200 fCatalog->emitSubstituteResources(stream, true); | 196 |
| 197 SkTSet<SkPDFObject*>* firstPageSubstituteResources = |
| 198 fCatalog->getSubstituteList(true); |
| 199 for (int i = 0; i < firstPageSubstituteResources->count(); ++i) { |
| 200 out.stream((*firstPageSubstituteResources)[i]); |
| 201 } |
201 // TODO(vandebo): Support linearized format | 202 // TODO(vandebo): Support linearized format |
202 // if (fPages.size() > 1) { | 203 // if (fPages.size() > 1) { |
203 // // TODO(vandebo): Save the file offset for the first page xref table. | 204 // // TODO(vandebo): Save the file offset for the first page xref table. |
204 // fCatalog->emitXrefTable(stream, true); | 205 // fCatalog->emitXrefTable(stream, true); |
205 // } | 206 // } |
206 | 207 |
207 for (int i = 0; i < fPageTree.count(); i++) { | 208 for (int i = 0; i < fPageTree.count(); i++) { |
208 fPageTree[i]->emitIndirectObject(stream, fCatalog.get()); | 209 out.stream(fPageTree[i]); |
209 } | 210 } |
210 | 211 |
211 for (int i = 1; i < fPages.count(); i++) { | 212 for (int i = 1; i < fPages.count(); i++) { |
212 fPages[i]->emitPage(stream, fCatalog.get()); | 213 out.stream(fPages[i]->getContentStream()); |
213 } | 214 } |
214 | 215 |
215 for (int i = 0; i < fOtherPageResources->count(); i++) { | 216 for (int i = 0; i < fOtherPageResources->count(); i++) { |
216 (*fOtherPageResources)[i]->emit(stream, fCatalog.get(), true); | 217 out.stream((*fOtherPageResources)[i]); |
217 } | 218 } |
218 | 219 |
219 fCatalog->emitSubstituteResources(stream, false); | 220 SkTSet<SkPDFObject*>* otherSubstituteResources = |
| 221 fCatalog->getSubstituteList(false); |
| 222 for (int i = 0; i < otherSubstituteResources->count(); ++i) { |
| 223 out.stream((*otherSubstituteResources)[i]); |
| 224 } |
| 225 |
| 226 fXRefFileOffset = out.offset(); |
220 int64_t objCount = fCatalog->emitXrefTable(stream, fPages.count() > 1); | 227 int64_t objCount = fCatalog->emitXrefTable(stream, fPages.count() > 1); |
221 emitFooter(stream, objCount); | 228 emitFooter(stream, objCount); |
222 return true; | 229 return true; |
223 } | 230 } |
224 | 231 |
225 bool SkPDFDocument::setPage(int pageNumber, SkPDFDevice* pdfDevice) { | 232 bool SkPDFDocument::setPage(int pageNumber, SkPDFDevice* pdfDevice) { |
226 if (!fPageTree.isEmpty()) { | 233 if (!fPageTree.isEmpty()) { |
227 return false; | 234 return false; |
228 } | 235 } |
229 | 236 |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
338 fTrailerDict->insertInt("Size", int(objCount)); | 345 fTrailerDict->insertInt("Size", int(objCount)); |
339 fTrailerDict->insert("Root", new SkPDFObjRef(fDocCatalog))->unref(); | 346 fTrailerDict->insert("Root", new SkPDFObjRef(fDocCatalog))->unref(); |
340 } | 347 } |
341 | 348 |
342 stream->writeText("trailer\n"); | 349 stream->writeText("trailer\n"); |
343 fTrailerDict->emitObject(stream, fCatalog.get()); | 350 fTrailerDict->emitObject(stream, fCatalog.get()); |
344 stream->writeText("\nstartxref\n"); | 351 stream->writeText("\nstartxref\n"); |
345 stream->writeBigDecAsText(fXRefFileOffset); | 352 stream->writeBigDecAsText(fXRefFileOffset); |
346 stream->writeText("\n%%EOF"); | 353 stream->writeText("\n%%EOF"); |
347 } | 354 } |
OLD | NEW |