Flutter Engine
The Flutter Engine
Functions
SkPDFMetadata Namespace Reference

Functions

std::unique_ptr< SkPDFObjectMakeDocumentInformationDict (const SkPDF::Metadata &)
 
SkUUID CreateUUID (const SkPDF::Metadata &)
 
std::unique_ptr< SkPDFObjectMakePdfId (const SkUUID &doc, const SkUUID &instance)
 
SkPDFIndirectReference MakeXMPObject (const SkPDF::Metadata &metadata, const SkUUID &doc, const SkUUID &instance, SkPDFDocument *)
 

Function Documentation

◆ CreateUUID()

SkUUID SkPDFMetadata::CreateUUID ( const SkPDF::Metadata metadata)

Definition at line 86 of file SkPDFMetadata.cpp.

86 {
87 // The main requirement is for the UUID to be unique; the exact
88 // format of the data that will be hashed is not important.
89 SkMD5 md5;
90 const char uuidNamespace[] = "org.skia.pdf\n";
91 md5.writeText(uuidNamespace);
92 double msec = SkTime::GetMSecs();
93 md5.write(&msec, sizeof(msec));
94 SkPDF::DateTime dateTime;
95 SkPDFUtils::GetDateTime(&dateTime);
96 md5.write(&dateTime, sizeof(dateTime));
97 md5.write(&metadata.fCreation, sizeof(metadata.fCreation));
98 md5.write(&metadata.fModified, sizeof(metadata.fModified));
99
100 for (const auto keyValuePtr : gMetadataKeys) {
101 md5.writeText(keyValuePtr.key);
102 md5.write("\037", 1);
103 const SkString& value = metadata.*(keyValuePtr.valuePtr);
104 md5.write(value.c_str(), value.size());
105 md5.write("\036", 1);
106 }
107 SkMD5::Digest digest = md5.finish();
108 // See RFC 4122, page 6-7.
109 digest.data[6] = (digest.data[6] & 0x0F) | 0x30;
110 digest.data[8] = (digest.data[6] & 0x3F) | 0x80;
111 static_assert(sizeof(digest) == sizeof(SkUUID), "uuid_size");
112 SkUUID uuid;
113 memcpy((void*)&uuid, &digest, sizeof(digest));
114 return uuid;
115}
static SkMD5::Digest md5(const SkBitmap &bm)
Definition: CodecTest.cpp:77
Definition: SkMD5.h:19
uint8_t value
void GetDateTime(SkPDF::DateTime *)
Definition: SkPDFUtils.cpp:431
double GetMSecs()
Definition: SkTime.h:17
uint8_t data[16]
Definition: SkMD5.h:39
DateTime fCreation
DateTime fModified
Definition: SkUUID.h:9

◆ MakeDocumentInformationDict()

std::unique_ptr< SkPDFObject > SkPDFMetadata::MakeDocumentInformationDict ( const SkPDF::Metadata metadata)

Definition at line 68 of file SkPDFMetadata.cpp.

69 {
70 auto dict = SkPDFMakeDict();
71 for (const auto keyValuePtr : gMetadataKeys) {
72 const SkString& value = metadata.*(keyValuePtr.valuePtr);
73 if (value.size() > 0) {
74 dict->insertTextString(keyValuePtr.key, value);
75 }
76 }
77 if (metadata.fCreation != kZeroTime) {
78 dict->insertTextString("CreationDate", pdf_date(metadata.fCreation));
79 }
80 if (metadata.fModified != kZeroTime) {
81 dict->insertTextString("ModDate", pdf_date(metadata.fModified));
82 }
83 return dict;
84}
static SkString pdf_date(const SkPDF::DateTime &dt)
static constexpr SkPDF::DateTime kZeroTime
static std::unique_ptr< SkPDFDict > SkPDFMakeDict(const char *type=nullptr)
Definition: SkPDFTypes.h:185

◆ MakePdfId()

std::unique_ptr< SkPDFObject > SkPDFMetadata::MakePdfId ( const SkUUID doc,
const SkUUID instance 
)

Definition at line 117 of file SkPDFMetadata.cpp.

117 {
118 // /ID [ <81b14aafa313db63dbd6f981e49f94f4>
119 // <81b14aafa313db63dbd6f981e49f94f4> ]
120 auto array = SkPDFMakeArray();
121 static_assert(sizeof(SkUUID) == 16, "uuid_size");
122 array->appendByteString(SkString(reinterpret_cast<const char*>(&doc ), sizeof(SkUUID)));
123 array->appendByteString(SkString(reinterpret_cast<const char*>(&instance), sizeof(SkUUID)));
124 return array;
125}
static std::unique_ptr< SkPDFArray > SkPDFMakeArray(Args... args)
Definition: SkPDFTypes.h:125
VkInstance instance
Definition: main.cc:48

◆ MakeXMPObject()

SkPDFIndirectReference SkPDFMetadata::MakeXMPObject ( const SkPDF::Metadata metadata,
const SkUUID doc,
const SkUUID instance,
SkPDFDocument docPtr 
)

Definition at line 235 of file SkPDFMetadata.cpp.

239 {
240 static const char templateString[] =
241 "<?xpacket begin=\"\" id=\"W5M0MpCehiHzreSzNTczkc9d\"?>\n"
242 "<x:xmpmeta xmlns:x=\"adobe:ns:meta/\"\n"
243 " x:xmptk=\"Adobe XMP Core 5.4-c005 78.147326, "
244 "2012/08/23-13:03:03\">\n"
245 "<rdf:RDF "
246 "xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">\n"
247 "<rdf:Description rdf:about=\"\"\n"
248 " xmlns:xmp=\"http://ns.adobe.com/xap/1.0/\"\n"
249 " xmlns:dc=\"http://purl.org/dc/elements/1.1/\"\n"
250 " xmlns:xmpMM=\"http://ns.adobe.com/xap/1.0/mm/\"\n"
251 " xmlns:pdf=\"http://ns.adobe.com/pdf/1.3/\"\n"
252 " xmlns:pdfaid=\"http://www.aiim.org/pdfa/ns/id/\">\n"
253 "<pdfaid:part>2</pdfaid:part>\n"
254 "<pdfaid:conformance>B</pdfaid:conformance>\n"
255 "%s" // ModifyDate
256 "%s" // CreateDate
257 "%s" // xmp:CreatorTool
258 "<dc:format>application/pdf</dc:format>\n"
259 "%s" // dc:title
260 "%s" // dc:description
261 "%s" // author
262 "%s" // keywords
263 "<xmpMM:DocumentID>uuid:%s</xmpMM:DocumentID>\n"
264 "<xmpMM:InstanceID>uuid:%s</xmpMM:InstanceID>\n"
265 "%s" // pdf:Producer
266 "%s" // pdf:Keywords
267 "</rdf:Description>\n"
268 "</rdf:RDF>\n"
269 "</x:xmpmeta>\n" // Note: the standard suggests 4k of padding.
270 "<?xpacket end=\"w\"?>\n";
271
272 SkString creationDate;
273 SkString modificationDate;
274 if (metadata.fCreation != kZeroTime) {
275 SkString tmp;
276 metadata.fCreation.toISO8601(&tmp);
278 // YYYY-mm-ddTHH:MM:SS[+|-]ZZ:ZZ; no need to escape
279 creationDate = SkStringPrintf("<xmp:CreateDate>%s</xmp:CreateDate>\n",
280 tmp.c_str());
281 }
282 if (metadata.fModified != kZeroTime) {
283 SkString tmp;
284 metadata.fModified.toISO8601(&tmp);
286 modificationDate = SkStringPrintf(
287 "<xmp:ModifyDate>%s</xmp:ModifyDate>\n", tmp.c_str());
288 }
289 SkString title =
290 escape_xml(metadata.fTitle,
291 "<dc:title><rdf:Alt><rdf:li xml:lang=\"x-default\">",
292 "</rdf:li></rdf:Alt></dc:title>\n");
293 SkString author =
294 escape_xml(metadata.fAuthor, "<dc:creator><rdf:Seq><rdf:li>",
295 "</rdf:li></rdf:Seq></dc:creator>\n");
296 // TODO: in theory, XMP can support multiple authors. Split on a delimiter?
297 SkString subject = escape_xml(
298 metadata.fSubject,
299 "<dc:description><rdf:Alt><rdf:li xml:lang=\"x-default\">",
300 "</rdf:li></rdf:Alt></dc:description>\n");
301 SkString keywords1 =
302 escape_xml(metadata.fKeywords, "<dc:subject><rdf:Bag><rdf:li>",
303 "</rdf:li></rdf:Bag></dc:subject>\n");
304 SkString keywords2 = escape_xml(metadata.fKeywords, "<pdf:Keywords>",
305 "</pdf:Keywords>\n");
306 // TODO: in theory, keywords can be a list too.
307
308 SkString producer = escape_xml(metadata.fProducer, "<pdf:Producer>", "</pdf:Producer>\n");
309
310 SkString creator = escape_xml(metadata.fCreator, "<xmp:CreatorTool>",
311 "</xmp:CreatorTool>\n");
312 SkString documentID = uuid_to_string(doc); // no need to escape
313 SkASSERT(0 == count_xml_escape_size(documentID));
314 SkString instanceID = uuid_to_string(instance);
315 SkASSERT(0 == count_xml_escape_size(instanceID));
316
317
318 auto value = SkStringPrintf(
319 templateString, modificationDate.c_str(), creationDate.c_str(),
320 creator.c_str(), title.c_str(), subject.c_str(), author.c_str(),
321 keywords1.c_str(), documentID.c_str(), instanceID.c_str(),
322 producer.c_str(), keywords2.c_str());
323
324 std::unique_ptr<SkPDFDict> dict = SkPDFMakeDict("Metadata");
325 dict->insertName("Subtype", "XML");
326 return SkPDFStreamOut(std::move(dict),
327 SkMemoryStream::MakeCopy(value.c_str(), value.size()),
329}
#define SkASSERT(cond)
Definition: SkAssert.h:116
static SkString uuid_to_string(const SkUUID &uuid)
SkString escape_xml(const SkString &input, const char *before=nullptr, const char *after=nullptr)
static int count_xml_escape_size(const SkString &input)
SkPDFIndirectReference SkPDFStreamOut(std::unique_ptr< SkPDFDict > dict, std::unique_ptr< SkStreamAsset > content, SkPDFDocument *doc, SkPDFSteamCompressionEnabled compress)
Definition: SkPDFTypes.cpp:591
SK_API SkString SkStringPrintf(const char *format,...) SK_PRINTF_LIKE(1
Creates a new string and writes into it using a printf()-style format.
static std::unique_ptr< SkMemoryStream > MakeCopy(const void *data, size_t length)
Definition: SkStream.cpp:306
const char * c_str() const
Definition: SkString.h:133
void toISO8601(SkString *dst) const
SkString fSubject
Definition: SkPDFDocument.h:96
SkString fAuthor
Definition: SkPDFDocument.h:92
SkString fProducer
SkString fKeywords