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

Side by Side Diff: src/pdf/SkPDFMetadata.cpp

Issue 2074583003: SkPDF: allow overriding Producer metadata (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: 2016-06-30 (Thursday) 10:42:59 EDT Created 4 years, 5 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 unified diff | Download patch
« no previous file with comments | « include/core/SkDocument.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2015 Google Inc. 2 * Copyright 2015 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 "SkMD5.h" 8 #include "SkMD5.h"
9 #include "SkMilestone.h" 9 #include "SkMilestone.h"
10 #include "SkPDFMetadata.h" 10 #include "SkPDFMetadata.h"
11 #include "SkPDFTypes.h" 11 #include "SkPDFTypes.h"
12 #include <utility> 12 #include <utility>
13 13
14 #define SKPDF_STRING(X) SKPDF_STRING_IMPL(X)
15 #define SKPDF_STRING_IMPL(X) #X
16 #define SKPDF_PRODUCER "Skia/PDF m" SKPDF_STRING(SK_MILESTONE)
17 #define SKPDF_CUSTOM_PRODUCER_KEY "ProductionLibrary"
18
14 static SkString pdf_date(const SkTime::DateTime& dt) { 19 static SkString pdf_date(const SkTime::DateTime& dt) {
15 int timeZoneMinutes = SkToInt(dt.fTimeZoneMinutes); 20 int timeZoneMinutes = SkToInt(dt.fTimeZoneMinutes);
16 char timezoneSign = timeZoneMinutes >= 0 ? '+' : '-'; 21 char timezoneSign = timeZoneMinutes >= 0 ? '+' : '-';
17 int timeZoneHours = SkTAbs(timeZoneMinutes) / 60; 22 int timeZoneHours = SkTAbs(timeZoneMinutes) / 60;
18 timeZoneMinutes = SkTAbs(timeZoneMinutes) % 60; 23 timeZoneMinutes = SkTAbs(timeZoneMinutes) % 60;
19 return SkStringPrintf( 24 return SkStringPrintf(
20 "D:%04u%02u%02u%02u%02u%02u%c%02d'%02d'", 25 "D:%04u%02u%02u%02u%02u%02u%c%02d'%02d'",
21 static_cast<unsigned>(dt.fYear), static_cast<unsigned>(dt.fMonth), 26 static_cast<unsigned>(dt.fYear), static_cast<unsigned>(dt.fMonth),
22 static_cast<unsigned>(dt.fDay), static_cast<unsigned>(dt.fHour), 27 static_cast<unsigned>(dt.fDay), static_cast<unsigned>(dt.fHour),
23 static_cast<unsigned>(dt.fMinute), 28 static_cast<unsigned>(dt.fMinute),
24 static_cast<unsigned>(dt.fSecond), timezoneSign, timeZoneHours, 29 static_cast<unsigned>(dt.fSecond), timezoneSign, timeZoneHours,
25 timeZoneMinutes); 30 timeZoneMinutes);
26 } 31 }
27 32
28 #define SKPDF_STRING(X) SKPDF_STRING_IMPL(X)
29 #define SKPDF_STRING_IMPL(X) #X
30
31 namespace { 33 namespace {
32 static const struct { 34 static const struct {
33 const char* const key; 35 const char* const key;
34 SkString SkDocument::PDFMetadata::*const valuePtr; 36 SkString SkDocument::PDFMetadata::*const valuePtr;
35 } gMetadataKeys[] = { 37 } gMetadataKeys[] = {
36 {"Title", &SkDocument::PDFMetadata::fTitle}, 38 {"Title", &SkDocument::PDFMetadata::fTitle},
37 {"Author", &SkDocument::PDFMetadata::fAuthor}, 39 {"Author", &SkDocument::PDFMetadata::fAuthor},
38 {"Subject", &SkDocument::PDFMetadata::fSubject}, 40 {"Subject", &SkDocument::PDFMetadata::fSubject},
39 {"Keywords", &SkDocument::PDFMetadata::fKeywords}, 41 {"Keywords", &SkDocument::PDFMetadata::fKeywords},
40 {"Creator", &SkDocument::PDFMetadata::fCreator}, 42 {"Creator", &SkDocument::PDFMetadata::fCreator},
(...skipping 15 matching lines...) Expand all
56 58
57 sk_sp<SkPDFObject> SkPDFMetadata::MakeDocumentInformationDict( 59 sk_sp<SkPDFObject> SkPDFMetadata::MakeDocumentInformationDict(
58 const SkDocument::PDFMetadata& metadata) { 60 const SkDocument::PDFMetadata& metadata) {
59 auto dict = sk_make_sp<SkPDFDict>(); 61 auto dict = sk_make_sp<SkPDFDict>();
60 for (const auto keyValuePtr : gMetadataKeys) { 62 for (const auto keyValuePtr : gMetadataKeys) {
61 const SkString& value = metadata.*(keyValuePtr.valuePtr); 63 const SkString& value = metadata.*(keyValuePtr.valuePtr);
62 if (value.size() > 0) { 64 if (value.size() > 0) {
63 dict->insertString(keyValuePtr.key, value); 65 dict->insertString(keyValuePtr.key, value);
64 } 66 }
65 } 67 }
66 dict->insertString("Producer", "Skia/PDF m" SKPDF_STRING(SK_MILESTONE)); 68 if (metadata.fProducer.isEmpty()) {
69 dict->insertString("Producer", SKPDF_PRODUCER);
70 } else {
71 dict->insertString("Producer", metadata.fProducer);
72 dict->insertString(SKPDF_CUSTOM_PRODUCER_KEY, SKPDF_PRODUCER);
73 }
67 if (metadata.fCreation.fEnabled) { 74 if (metadata.fCreation.fEnabled) {
68 dict->insertString("CreationDate", 75 dict->insertString("CreationDate",
69 pdf_date(metadata.fCreation.fDateTime)); 76 pdf_date(metadata.fCreation.fDateTime));
70 } 77 }
71 if (metadata.fModified.fEnabled) { 78 if (metadata.fModified.fEnabled) {
72 dict->insertString("ModDate", pdf_date(metadata.fModified.fDateTime)); 79 dict->insertString("ModDate", pdf_date(metadata.fModified.fDateTime));
73 } 80 }
74 return dict; 81 return dict;
75 } 82 }
76 83
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 "%s" // ModifyDate 264 "%s" // ModifyDate
258 "%s" // CreateDate 265 "%s" // CreateDate
259 "%s" // xmp:CreatorTool 266 "%s" // xmp:CreatorTool
260 "<dc:format>application/pdf</dc:format>\n" 267 "<dc:format>application/pdf</dc:format>\n"
261 "%s" // dc:title 268 "%s" // dc:title
262 "%s" // dc:description 269 "%s" // dc:description
263 "%s" // author 270 "%s" // author
264 "%s" // keywords 271 "%s" // keywords
265 "<xmpMM:DocumentID>uuid:%s</xmpMM:DocumentID>\n" 272 "<xmpMM:DocumentID>uuid:%s</xmpMM:DocumentID>\n"
266 "<xmpMM:InstanceID>uuid:%s</xmpMM:InstanceID>\n" 273 "<xmpMM:InstanceID>uuid:%s</xmpMM:InstanceID>\n"
267 "<pdf:Producer>Skia/PDF m" SKPDF_STRING(SK_MILESTONE) "</pdf:Produce r>\n" 274 "%s" // pdf:Producer
268 "%s" // pdf:Keywords 275 "%s" // pdf:Keywords
269 "</rdf:Description>\n" 276 "</rdf:Description>\n"
270 "</rdf:RDF>\n" 277 "</rdf:RDF>\n"
271 "</x:xmpmeta>\n" // Note: the standard suggests 4k of padding. 278 "</x:xmpmeta>\n" // Note: the standard suggests 4k of padding.
272 "<?xpacket end=\"w\"?>\n"; 279 "<?xpacket end=\"w\"?>\n";
273 280
274 SkString creationDate; 281 SkString creationDate;
275 SkString modificationDate; 282 SkString modificationDate;
276 if (metadata.fCreation.fEnabled) { 283 if (metadata.fCreation.fEnabled) {
277 SkString tmp; 284 SkString tmp;
(...skipping 20 matching lines...) Expand all
298 // TODO: in theory, XMP can support multiple authors. Split on a delimiter? 305 // TODO: in theory, XMP can support multiple authors. Split on a delimiter?
299 SkString subject = escape_xml( 306 SkString subject = escape_xml(
300 metadata.fSubject, 307 metadata.fSubject,
301 "<dc:description><rdf:Alt><rdf:li xml:lang=\"x-default\">", 308 "<dc:description><rdf:Alt><rdf:li xml:lang=\"x-default\">",
302 "</rdf:li></rdf:Alt></dc:description>\n"); 309 "</rdf:li></rdf:Alt></dc:description>\n");
303 SkString keywords1 = 310 SkString keywords1 =
304 escape_xml(metadata.fKeywords, "<dc:subject><rdf:Bag><rdf:li>", 311 escape_xml(metadata.fKeywords, "<dc:subject><rdf:Bag><rdf:li>",
305 "</rdf:li></rdf:Bag></dc:subject>\n"); 312 "</rdf:li></rdf:Bag></dc:subject>\n");
306 SkString keywords2 = escape_xml(metadata.fKeywords, "<pdf:Keywords>", 313 SkString keywords2 = escape_xml(metadata.fKeywords, "<pdf:Keywords>",
307 "</pdf:Keywords>\n"); 314 "</pdf:Keywords>\n");
315 // TODO: in theory, keywords can be a list too.
308 316
309 // TODO: in theory, keywords can be a list too. 317 SkString producer("<pdf:Producer>SKPDF_PRODUCER</pdf:Producer>\n");
318 if (!metadata.fProducer.isEmpty()) {
319 // TODO: register a developer prefix to make
320 // <skia:SKPDF_CUSTOM_PRODUCER_KEY> a real XML tag.
321 producer = escape_xml(
322 metadata.fProducer, "<pdf:Producer>",
323 "</pdf:Producer>\n<!-- <skia:" SKPDF_CUSTOM_PRODUCER_KEY ">"
324 SKPDF_PRODUCER "</skia:" SKPDF_CUSTOM_PRODUCER_KEY "> -->\n");
325 }
326
310 SkString creator = escape_xml(metadata.fCreator, "<xmp:CreatorTool>", 327 SkString creator = escape_xml(metadata.fCreator, "<xmp:CreatorTool>",
311 "</xmp:CreatorTool>\n"); 328 "</xmp:CreatorTool>\n");
312 SkString documentID = uuid_to_string(doc); // no need to escape 329 SkString documentID = uuid_to_string(doc); // no need to escape
313 SkASSERT(0 == count_xml_escape_size(documentID)); 330 SkASSERT(0 == count_xml_escape_size(documentID));
314 SkString instanceID = uuid_to_string(instance); 331 SkString instanceID = uuid_to_string(instance);
315 SkASSERT(0 == count_xml_escape_size(instanceID)); 332 SkASSERT(0 == count_xml_escape_size(instanceID));
316 return sk_make_sp<PDFXMLObject>(SkStringPrintf( 333 return sk_make_sp<PDFXMLObject>(SkStringPrintf(
317 templateString, modificationDate.c_str(), creationDate.c_str(), 334 templateString, modificationDate.c_str(), creationDate.c_str(),
318 creator.c_str(), title.c_str(), subject.c_str(), author.c_str(), 335 creator.c_str(), title.c_str(), subject.c_str(), author.c_str(),
319 keywords1.c_str(), documentID.c_str(), instanceID.c_str(), 336 keywords1.c_str(), documentID.c_str(), instanceID.c_str(),
320 keywords2.c_str())); 337 producer.c_str(), keywords2.c_str()));
321 } 338 }
322 339
340 #undef SKPDF_CUSTOM_PRODUCER_KEY
341 #undef SKPDF_PRODUCER
323 #undef SKPDF_STRING 342 #undef SKPDF_STRING
324 #undef SKPDF_STRING_IMPL 343 #undef SKPDF_STRING_IMPL
OLDNEW
« no previous file with comments | « include/core/SkDocument.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698