sk_sp<SkPDFObject> SkPDFMetadata::MakeDocumentInformationDict( const SkDocument::PDFMetadata& metadata) { auto dict = sk_make_sp<SkPDFDict>(); for (const auto keyValuePtr : gMetadataKeys) { const SkString& value = metadata.*(keyValuePtr.valuePtr); if (value.size() > 0) { dict->insertString(keyValuePtr.key, value); } } dict->insertString("Producer", "Skia/PDF m" SKPDF_STRING(SK_MILESTONE)); if (metadata.fCreation.fEnabled) { dict->insertString("CreationDate", pdf_date(metadata.fCreation.fDateTime)); } if (metadata.fModified.fEnabled) { dict->insertString("ModDate", pdf_date(metadata.fModified.fDateTime)); } return dict; }
SkPDFObject* SkPDFMetadata::createDocumentInformationDict() const { auto dict = sk_make_sp<SkPDFDict>(); static const char* keys[] = { "Title", "Author", "Subject", "Keywords", "Creator"}; for (const char* key : keys) { for (const SkDocument::Attribute& keyValue : fInfo) { if (keyValue.fKey.equals(key)) { dict->insertString(key, keyValue.fValue); } } } dict->insertString("Producer", "Skia/PDF m" SKPDF_STRING(SK_MILESTONE)); if (fCreation) { dict->insertString("CreationDate", pdf_date(*fCreation.get())); } if (fModified) { dict->insertString("ModDate", pdf_date(*fModified.get())); } return dict.release(); }
sk_sp<SkPDFObject> SkPDFMetadata::MakeXMPObject( const SkDocument::PDFMetadata& metadata, const UUID& doc, const UUID& instance) { static const char templateString[] = "<?xpacket begin=\"\" id=\"W5M0MpCehiHzreSzNTczkc9d\"?>\n" "<x:xmpmeta xmlns:x=\"adobe:ns:meta/\"\n" " x:xmptk=\"Adobe XMP Core 5.4-c005 78.147326, " "2012/08/23-13:03:03\">\n" "<rdf:RDF " "xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">\n" "<rdf:Description rdf:about=\"\"\n" " xmlns:xmp=\"http://ns.adobe.com/xap/1.0/\"\n" " xmlns:dc=\"http://purl.org/dc/elements/1.1/\"\n" " xmlns:xmpMM=\"http://ns.adobe.com/xap/1.0/mm/\"\n" " xmlns:pdf=\"http://ns.adobe.com/pdf/1.3/\"\n" " xmlns:pdfaid=\"http://www.aiim.org/pdfa/ns/id/\">\n" "<pdfaid:part>2</pdfaid:part>\n" "<pdfaid:conformance>B</pdfaid:conformance>\n" "%s" // ModifyDate "%s" // CreateDate "%s" // xmp:CreatorTool "<dc:format>application/pdf</dc:format>\n" "%s" // dc:title "%s" // dc:description "%s" // author "%s" // keywords "<xmpMM:DocumentID>uuid:%s</xmpMM:DocumentID>\n" "<xmpMM:InstanceID>uuid:%s</xmpMM:InstanceID>\n" "<pdf:Producer>Skia/PDF m" SKPDF_STRING(SK_MILESTONE) "</pdf:Producer>\n" "%s" // pdf:Keywords "</rdf:Description>\n" "</rdf:RDF>\n" "</x:xmpmeta>\n" // Note: the standard suggests 4k of padding. "<?xpacket end=\"w\"?>\n"; SkString creationDate; SkString modificationDate; if (metadata.fCreation.fEnabled) { SkString tmp; metadata.fCreation.fDateTime.toISO8601(&tmp); SkASSERT(0 == count_xml_escape_size(tmp)); // YYYY-mm-ddTHH:MM:SS[+|-]ZZ:ZZ; no need to escape creationDate = SkStringPrintf("<xmp:CreateDate>%s</xmp:CreateDate>\n", tmp.c_str()); } if (metadata.fModified.fEnabled) { SkString tmp; metadata.fModified.fDateTime.toISO8601(&tmp); SkASSERT(0 == count_xml_escape_size(tmp)); modificationDate = SkStringPrintf( "<xmp:ModifyDate>%s</xmp:ModifyDate>\n", tmp.c_str()); } SkString title = escape_xml(metadata.fTitle, "<dc:title><rdf:Alt><rdf:li xml:lang=\"x-default\">", "</rdf:li></rdf:Alt></dc:title>\n"); SkString author = escape_xml(metadata.fAuthor, "<dc:creator><rdf:Bag><rdf:li>", "</rdf:li></rdf:Bag></dc:creator>\n"); // TODO: in theory, XMP can support multiple authors. Split on a delimiter? SkString subject = escape_xml( metadata.fSubject, "<dc:description><rdf:Alt><rdf:li xml:lang=\"x-default\">", "</rdf:li></rdf:Alt></dc:description>\n"); SkString keywords1 = escape_xml(metadata.fKeywords, "<dc:subject><rdf:Bag><rdf:li>", "</rdf:li></rdf:Bag></dc:subject>\n"); SkString keywords2 = escape_xml(metadata.fKeywords, "<pdf:Keywords>", "</pdf:Keywords>\n"); // TODO: in theory, keywords can be a list too. SkString creator = escape_xml(metadata.fCreator, "<xmp:CreatorTool>", "</xmp:CreatorTool>\n"); SkString documentID = uuid_to_string(doc); // no need to escape SkASSERT(0 == count_xml_escape_size(documentID)); SkString instanceID = uuid_to_string(instance); SkASSERT(0 == count_xml_escape_size(instanceID)); return sk_make_sp<PDFXMLObject>(SkStringPrintf( templateString, modificationDate.c_str(), creationDate.c_str(), creator.c_str(), title.c_str(), subject.c_str(), author.c_str(), keywords1.c_str(), documentID.c_str(), instanceID.c_str(), keywords2.c_str())); }