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 |