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

Unified Diff: src/doc/SkDocument_PDF.cpp

Issue 1398193002: Revert of SkPDF: Optionally output PDF/A-2b archive format. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 5 years, 2 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « gyp/pdf.gypi ('k') | src/pdf/SkPDFBitmap.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/doc/SkDocument_PDF.cpp
diff --git a/src/doc/SkDocument_PDF.cpp b/src/doc/SkDocument_PDF.cpp
index ff7a038b6bf268c9a9b85ba2dbd1da38eb1b5035..fb22f18ec5da5af7807935476b07f29783ef4651 100644
--- a/src/doc/SkDocument_PDF.cpp
+++ b/src/doc/SkDocument_PDF.cpp
@@ -13,7 +13,6 @@
#include "SkPDFTypes.h"
#include "SkPDFUtils.h"
#include "SkStream.h"
-#include "SkPDFMetadata.h"
class SkPDFDict;
@@ -31,18 +30,15 @@
SkPDFObject* docCatalog,
int64_t objCount,
int32_t xRefFileOffset,
- SkPDFObject* info /* take ownership */,
- SkPDFObject* id /* take ownership */) {
+ SkPDFDict* info) {
SkPDFDict trailerDict;
- // TODO(http://crbug.com/80908): Linearized format will take a
- // Prev entry too.
+ // TODO(vandebo): Linearized format will take a Prev entry too.
+ // TODO(vandebo): PDF/A requires an ID entry.
trailerDict.insertInt("Size", int(objCount));
trailerDict.insertObjRef("Root", SkRef(docCatalog));
SkASSERT(info);
- trailerDict.insertObjRef("Info", info);
- if (id) {
- trailerDict.insertObject("ID", id);
- }
+ trailerDict.insertObjRef("Info", SkRef(info));
+
stream->writeText("trailer\n");
trailerDict.emitObject(stream, objNumMap, substitutes);
stream->writeText("\nstartxref\n");
@@ -166,8 +162,49 @@
}
}
+struct Metadata {
+ SkTArray<SkDocument::Attribute> fInfo;
+ SkAutoTDelete<const SkTime::DateTime> fCreation;
+ SkAutoTDelete<const SkTime::DateTime> fModified;
+};
+
+static SkString pdf_date(const SkTime::DateTime& dt) {
+ int timeZoneMinutes = SkToInt(dt.fTimeZoneMinutes);
+ char timezoneSign = timeZoneMinutes >= 0 ? '+' : '-';
+ int timeZoneHours = SkTAbs(timeZoneMinutes) / 60;
+ timeZoneMinutes = SkTAbs(timeZoneMinutes) % 60;
+ return SkStringPrintf(
+ "D:%04u%02u%02u%02u%02u%02u%c%02d'%02d'",
+ static_cast<unsigned>(dt.fYear), static_cast<unsigned>(dt.fMonth),
+ static_cast<unsigned>(dt.fDay), static_cast<unsigned>(dt.fHour),
+ static_cast<unsigned>(dt.fMinute),
+ static_cast<unsigned>(dt.fSecond), timezoneSign, timeZoneHours,
+ timeZoneMinutes);
+}
+
+SkPDFDict* create_document_information_dict(const Metadata& metadata) {
+ SkAutoTUnref<SkPDFDict> dict(new SkPDFDict);
+ static const char* keys[] = {
+ "Title", "Author", "Subject", "Keywords", "Creator" };
+ for (const char* key : keys) {
+ for (const SkDocument::Attribute& keyValue : metadata.fInfo) {
+ if (keyValue.fKey.equals(key)) {
+ dict->insertString(key, keyValue.fValue);
+ }
+ }
+ }
+ dict->insertString("Producer", "Skia/PDF");
+ if (metadata.fCreation) {
+ dict->insertString("CreationDate", pdf_date(*metadata.fCreation.get()));
+ }
+ if (metadata.fModified) {
+ dict->insertString("ModDate", pdf_date(*metadata.fModified.get()));
+ }
+ return dict.detach();
+}
+
static bool emit_pdf_document(const SkTDArray<const SkPDFDevice*>& pageDevices,
- const SkPDFMetadata& metadata,
+ const Metadata& metadata,
SkWStream* stream) {
if (pageDevices.isEmpty()) {
return false;
@@ -185,37 +222,9 @@
pages.push(page.detach());
}
+ SkTDArray<SkPDFDict*> pageTree;
SkAutoTUnref<SkPDFDict> docCatalog(new SkPDFDict("Catalog"));
- SkAutoTUnref<SkPDFObject> infoDict(
- metadata.createDocumentInformationDict());
-
- SkAutoTUnref<SkPDFObject> id, xmp;
-#ifdef SK_PDF_GENERATE_PDFA
- SkPDFMetadata::UUID uuid = metadata.uuid();
- // We use the same UUID for Document ID and Instance ID since this
- // is the first revision of this document (and Skia does not
- // support revising existing PDF documents).
- // If we are not in PDF/A mode, don't use a UUID since testing
- // works best with reproducible outputs.
- id.reset(SkPDFMetadata::CreatePdfId(uuid, uuid));
- xmp.reset(metadata.createXMPObject(uuid, uuid));
- docCatalog->insertObjRef("Metadata", xmp.detach());
-
- // sRGB is specified by HTML, CSS, and SVG.
- SkAutoTUnref<SkPDFDict> outputIntent(new SkPDFDict("OutputIntent"));
- outputIntent->insertName("S", "GTS_PDFA1");
- outputIntent->insertString("RegistryName", "http://www.color.org");
- outputIntent->insertString("OutputConditionIdentifier",
- "sRGB IEC61966-2.1");
- SkAutoTUnref<SkPDFArray> intentArray(new SkPDFArray);
- intentArray->appendObject(outputIntent.detach());
- // Don't specify OutputIntents if we are not in PDF/A mode since
- // no one has ever asked for this feature.
- docCatalog->insertObject("OutputIntents", intentArray.detach());
-#endif
-
- SkTDArray<SkPDFDict*> pageTree;
SkPDFDict* pageTreeRoot;
generate_page_tree(pages, &pageTree, &pageTreeRoot);
docCatalog->insertObjRef("Pages", SkRef(pageTreeRoot));
@@ -224,13 +233,28 @@
docCatalog->insertObjRef("Dests", dests.detach());
}
+ /* TODO(vandebo): output intent
+ SkAutoTUnref<SkPDFDict> outputIntent = new SkPDFDict("OutputIntent");
+ outputIntent->insertName("S", "GTS_PDFA1");
+ outputIntent->insertString("OutputConditionIdentifier", "sRGB");
+ SkAutoTUnref<SkPDFArray> intentArray(new SkPDFArray);
+ intentArray->appendObject(SkRef(outputIntent.get()));
+ docCatalog->insertObject("OutputIntent", intentArray.detach());
+ */
+
// Build font subsetting info before proceeding.
SkPDFSubstituteMap substitutes;
perform_font_subsetting(pageDevices, &substitutes);
+ SkAutoTUnref<SkPDFDict> infoDict(
+ create_document_information_dict(metadata));
SkPDFObjNumMap objNumMap;
- objNumMap.addObjectRecursively(infoDict, substitutes);
- objNumMap.addObjectRecursively(docCatalog.get(), substitutes);
+ if (objNumMap.addObject(infoDict)) {
+ infoDict->addResources(&objNumMap, substitutes);
+ }
+ if (objNumMap.addObject(docCatalog.get())) {
+ docCatalog->addResources(&objNumMap, substitutes);
+ }
size_t baseOffset = stream->bytesWritten();
emit_pdf_header(stream);
SkTDArray<int32_t> offsets;
@@ -262,7 +286,7 @@
stream->writeText(" 00000 n \n");
}
emit_pdf_footer(stream, objNumMap, substitutes, docCatalog.get(), objCount,
- xRefFileOffset, infoDict.detach(), id.detach());
+ xRefFileOffset, infoDict);
// The page tree has both child and parent pointers, so it creates a
// reference cycle. We must clear that cycle to properly reclaim memory.
@@ -380,7 +404,7 @@
SkTDArray<const SkPDFDevice*> fPageDevices;
SkAutoTUnref<SkCanvas> fCanvas;
SkScalar fRasterDpi;
- SkPDFMetadata fMetadata;
+ Metadata fMetadata;
};
} // namespace
///////////////////////////////////////////////////////////////////////////////
« no previous file with comments | « gyp/pdf.gypi ('k') | src/pdf/SkPDFBitmap.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698