| 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 "SkPDFCanvas.h" | 9 #include "SkPDFCanvas.h" |
| 10 #include "SkPDFDevice.h" | 10 #include "SkPDFDevice.h" |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 231 fObjectSerializer.serializeObjects(this->getStream()); | 231 fObjectSerializer.serializeObjects(this->getStream()); |
| 232 } | 232 } |
| 233 | 233 |
| 234 SkCanvas* SkPDFDocument::onBeginPage(SkScalar width, SkScalar height, | 234 SkCanvas* SkPDFDocument::onBeginPage(SkScalar width, SkScalar height, |
| 235 const SkRect& trimBox) { | 235 const SkRect& trimBox) { |
| 236 SkASSERT(!fCanvas.get()); // endPage() was called before this. | 236 SkASSERT(!fCanvas.get()); // endPage() was called before this. |
| 237 if (fPages.empty()) { | 237 if (fPages.empty()) { |
| 238 // if this is the first page if the document. | 238 // if this is the first page if the document. |
| 239 fObjectSerializer.serializeHeader(this->getStream(), fMetadata); | 239 fObjectSerializer.serializeHeader(this->getStream(), fMetadata); |
| 240 fDests = sk_make_sp<SkPDFDict>(); | 240 fDests = sk_make_sp<SkPDFDict>(); |
| 241 #ifdef SK_PDF_GENERATE_PDFA |
| 242 SkPDFMetadata::UUID uuid = fMetadata.uuid(); |
| 243 // We use the same UUID for Document ID and Instance ID since this |
| 244 // is the first revision of this document (and Skia does not |
| 245 // support revising existing PDF documents). |
| 246 // If we are not in PDF/A mode, don't use a UUID since testing |
| 247 // works best with reproducible outputs. |
| 248 fID.reset(SkPDFMetadata::CreatePdfId(uuid, uuid)); |
| 249 fXMP.reset(fMetadata.createXMPObject(uuid, uuid)); |
| 250 fObjectSerializer.addObjectRecursively(fXMP); |
| 251 fObjectSerializer.serializeObjects(this->getStream()); |
| 252 #endif |
| 241 } | 253 } |
| 242 SkISize pageSize = SkISize::Make( | 254 SkISize pageSize = SkISize::Make( |
| 243 SkScalarRoundToInt(width), SkScalarRoundToInt(height)); | 255 SkScalarRoundToInt(width), SkScalarRoundToInt(height)); |
| 244 fPageDevice.reset( | 256 fPageDevice.reset( |
| 245 SkPDFDevice::Create(pageSize, fRasterDpi, this)); | 257 SkPDFDevice::Create(pageSize, fRasterDpi, this)); |
| 246 fCanvas = sk_make_sp<SkPDFCanvas>(fPageDevice); | 258 fCanvas = sk_make_sp<SkPDFCanvas>(fPageDevice); |
| 247 fCanvas->clipRect(trimBox); | 259 fCanvas->clipRect(trimBox); |
| 248 fCanvas->translate(trimBox.x(), trimBox.y()); | 260 fCanvas->translate(trimBox.x(), trimBox.y()); |
| 249 return fCanvas.get(); | 261 return fCanvas.get(); |
| 250 } | 262 } |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 290 | 302 |
| 291 bool SkPDFDocument::onClose(SkWStream* stream) { | 303 bool SkPDFDocument::onClose(SkWStream* stream) { |
| 292 SkASSERT(!fCanvas.get()); | 304 SkASSERT(!fCanvas.get()); |
| 293 if (fPages.empty()) { | 305 if (fPages.empty()) { |
| 294 fPages.reset(); | 306 fPages.reset(); |
| 295 fCanon.reset(); | 307 fCanon.reset(); |
| 296 renew(&fObjectSerializer); | 308 renew(&fObjectSerializer); |
| 297 return false; | 309 return false; |
| 298 } | 310 } |
| 299 auto docCatalog = sk_make_sp<SkPDFDict>("Catalog"); | 311 auto docCatalog = sk_make_sp<SkPDFDict>("Catalog"); |
| 300 sk_sp<SkPDFObject> id, xmp; | |
| 301 #ifdef SK_PDF_GENERATE_PDFA | 312 #ifdef SK_PDF_GENERATE_PDFA |
| 302 SkPDFMetadata::UUID uuid = metadata.uuid(); | 313 SkASSERT(fXMP); |
| 303 // We use the same UUID for Document ID and Instance ID since this | 314 docCatalog->insertObjRef("Metadata", fXMP); |
| 304 // is the first revision of this document (and Skia does not | |
| 305 // support revising existing PDF documents). | |
| 306 // If we are not in PDF/A mode, don't use a UUID since testing | |
| 307 // works best with reproducible outputs. | |
| 308 id.reset(SkPDFMetadata::CreatePdfId(uuid, uuid)); | |
| 309 xmp.reset(metadata.createXMPObject(uuid, uuid)); | |
| 310 docCatalog->insertObjRef("Metadata", std::move(xmp)); | |
| 311 | |
| 312 // sRGB is specified by HTML, CSS, and SVG. | 315 // sRGB is specified by HTML, CSS, and SVG. |
| 313 auto outputIntent = sk_make_sp<SkPDFDict>("OutputIntent"); | 316 auto outputIntent = sk_make_sp<SkPDFDict>("OutputIntent"); |
| 314 outputIntent->insertName("S", "GTS_PDFA1"); | 317 outputIntent->insertName("S", "GTS_PDFA1"); |
| 315 outputIntent->insertString("RegistryName", "http://www.color.org"); | 318 outputIntent->insertString("RegistryName", "http://www.color.org"); |
| 316 outputIntent->insertString("OutputConditionIdentifier", | 319 outputIntent->insertString("OutputConditionIdentifier", |
| 317 "sRGB IEC61966-2.1"); | 320 "sRGB IEC61966-2.1"); |
| 318 auto intentArray = sk_make_sp<SkPDFArray>(); | 321 auto intentArray = sk_make_sp<SkPDFArray>(); |
| 319 intentArray->appendObject(std::move(outputIntent)); | 322 intentArray->appendObject(std::move(outputIntent)); |
| 320 // Don't specify OutputIntents if we are not in PDF/A mode since | 323 // Don't specify OutputIntents if we are not in PDF/A mode since |
| 321 // no one has ever asked for this feature. | 324 // no one has ever asked for this feature. |
| 322 docCatalog->insertObject("OutputIntents", std::move(intentArray)); | 325 docCatalog->insertObject("OutputIntents", std::move(intentArray)); |
| 323 #endif | 326 #endif |
| 324 | |
| 325 docCatalog->insertObjRef("Pages", generate_page_tree(&fPages)); | 327 docCatalog->insertObjRef("Pages", generate_page_tree(&fPages)); |
| 326 | 328 |
| 327 if (fDests->size() > 0) { | 329 if (fDests->size() > 0) { |
| 328 docCatalog->insertObjRef("Dests", std::move(fDests)); | 330 docCatalog->insertObjRef("Dests", std::move(fDests)); |
| 329 } | 331 } |
| 330 | 332 |
| 331 // Build font subsetting info before calling addObjectRecursively(). | 333 // Build font subsetting info before calling addObjectRecursively(). |
| 332 for (const auto& entry : fGlyphUsage) { | 334 for (const auto& entry : fGlyphUsage) { |
| 333 sk_sp<SkPDFFont> subsetFont( | 335 sk_sp<SkPDFFont> subsetFont( |
| 334 entry.fFont->getFontSubset(entry.fGlyphSet)); | 336 entry.fFont->getFontSubset(entry.fGlyphSet)); |
| 335 if (subsetFont) { | 337 if (subsetFont) { |
| 336 fObjectSerializer.fSubstituteMap.setSubstitute( | 338 fObjectSerializer.fSubstituteMap.setSubstitute( |
| 337 entry.fFont, subsetFont.get()); | 339 entry.fFont, subsetFont.get()); |
| 338 } | 340 } |
| 339 } | 341 } |
| 340 | 342 |
| 341 fObjectSerializer.addObjectRecursively(docCatalog); | 343 fObjectSerializer.addObjectRecursively(docCatalog); |
| 342 fObjectSerializer.serializeObjects(this->getStream()); | 344 fObjectSerializer.serializeObjects(this->getStream()); |
| 343 fObjectSerializer.serializeFooter( | 345 #ifdef SK_PDF_GENERATE_PDFA |
| 344 this->getStream(), docCatalog, std::move(id)); | 346 fObjectSerializer.serializeFooter(this->getStream(), docCatalog, fID); |
| 345 | 347 #else |
| 348 fObjectSerializer.serializeFooter( |
| 349 this->getStream(), docCatalog, nullptr); |
| 350 #endif |
| 346 SkASSERT(fPages.count() == 0); | 351 SkASSERT(fPages.count() == 0); |
| 347 fCanon.reset(); | 352 fCanon.reset(); |
| 348 renew(&fObjectSerializer); | 353 renew(&fObjectSerializer); |
| 349 return true; | 354 return true; |
| 350 } | 355 } |
| 351 | 356 |
| 352 /////////////////////////////////////////////////////////////////////////////// | 357 /////////////////////////////////////////////////////////////////////////////// |
| 353 | 358 |
| 354 sk_sp<SkDocument> SkPDFMakeDocument(SkWStream* stream, | 359 sk_sp<SkDocument> SkPDFMakeDocument(SkWStream* stream, |
| 355 void (*proc)(SkWStream*, bool), | 360 void (*proc)(SkWStream*, bool), |
| (...skipping 12 matching lines...) Expand all Loading... |
| 368 return SkPDFMakeDocument(stream, nullptr, dpi, jpegEncoder).release(); | 373 return SkPDFMakeDocument(stream, nullptr, dpi, jpegEncoder).release(); |
| 369 } | 374 } |
| 370 | 375 |
| 371 SkDocument* SkDocument::CreatePDF(const char path[], SkScalar dpi) { | 376 SkDocument* SkDocument::CreatePDF(const char path[], SkScalar dpi) { |
| 372 auto delete_wstream = [](SkWStream* stream, bool) { delete stream; }; | 377 auto delete_wstream = [](SkWStream* stream, bool) { delete stream; }; |
| 373 std::unique_ptr<SkFILEWStream> stream(new SkFILEWStream(path)); | 378 std::unique_ptr<SkFILEWStream> stream(new SkFILEWStream(path)); |
| 374 return stream->isValid() | 379 return stream->isValid() |
| 375 ? SkPDFMakeDocument(stream.release(), delete_wstream, dpi, nullptr).rele
ase() | 380 ? SkPDFMakeDocument(stream.release(), delete_wstream, dpi, nullptr).rele
ase() |
| 376 : nullptr; | 381 : nullptr; |
| 377 } | 382 } |
| OLD | NEW |