summaryrefslogtreecommitdiffstats
path: root/vcl/source/pdf/XmpMetadata.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'vcl/source/pdf/XmpMetadata.cxx')
-rw-r--r--vcl/source/pdf/XmpMetadata.cxx367
1 files changed, 367 insertions, 0 deletions
diff --git a/vcl/source/pdf/XmpMetadata.cxx b/vcl/source/pdf/XmpMetadata.cxx
new file mode 100644
index 0000000000..53bf3902ab
--- /dev/null
+++ b/vcl/source/pdf/XmpMetadata.cxx
@@ -0,0 +1,367 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#include <pdf/XmpMetadata.hxx>
+#include <tools/XmlWriter.hxx>
+
+namespace vcl::pdf
+{
+namespace
+{
+constexpr const char* constPadding = " "
+ " "
+ " "
+ " "
+ " "
+ "\n";
+}
+
+XmpMetadata::XmpMetadata()
+ : mbWritten(false)
+ , mnPDF_A(0)
+ , mbPDF_UA(false)
+{
+}
+
+void XmpMetadata::write()
+{
+ mpMemoryStream = std::make_unique<SvMemoryStream>(4096 /*Initial*/, 64 /*Resize*/);
+
+ // Header
+ mpMemoryStream->WriteOString(
+ OStringLiteral(u8"<?xpacket begin=\"\uFEFF\" id=\"W5M0MpCehiHzreSzNTczkc9d\"?>\n"));
+
+ {
+ tools::XmlWriter aXmlWriter(mpMemoryStream.get());
+ aXmlWriter.startDocument(2, false);
+ aXmlWriter.startElement("x"_ostr, "xmpmeta"_ostr, "adobe:ns:meta/"_ostr);
+ aXmlWriter.startElement("rdf"_ostr, "RDF"_ostr,
+ "http://www.w3.org/1999/02/22-rdf-syntax-ns#"_ostr);
+
+ // PDF/A part ( ISO 19005-1:2005 - 6.7.11 )
+ if (mnPDF_A > 0)
+ {
+ OString sPdfVersion = OString::number(mnPDF_A);
+
+ aXmlWriter.startElement("rdf:Description");
+ aXmlWriter.attribute("rdf:about", ""_ostr);
+ aXmlWriter.attribute("xmlns:pdfaid", "http://www.aiim.org/pdfa/ns/id/"_ostr);
+
+ aXmlWriter.startElement("pdfaid:part");
+ aXmlWriter.content(sPdfVersion);
+ aXmlWriter.endElement();
+
+ aXmlWriter.startElement("pdfaid:conformance");
+ aXmlWriter.content("B"_ostr);
+ aXmlWriter.endElement();
+
+ aXmlWriter.endElement();
+ }
+
+ // Dublin Core properties
+ if (!msTitle.isEmpty() || !msAuthor.isEmpty() || !msSubject.isEmpty()
+ || !maContributor.empty() || !msCoverage.isEmpty() || !msIdentifier.isEmpty()
+ || !maPublisher.empty() || !maRelation.empty() || !msRights.isEmpty()
+ || !msSource.isEmpty() || !msType.isEmpty())
+ {
+ aXmlWriter.startElement("rdf:Description");
+ aXmlWriter.attribute("rdf:about", ""_ostr);
+ aXmlWriter.attribute("xmlns:dc", "http://purl.org/dc/elements/1.1/"_ostr);
+
+ aXmlWriter.startElement("dc:format");
+ aXmlWriter.content("application/pdf"_ostr);
+ aXmlWriter.endElement();
+
+ if (!msTitle.isEmpty())
+ {
+ // this is according to PDF/A-1, technical corrigendum 1 (2007-04-01)
+ aXmlWriter.startElement("dc:title");
+ aXmlWriter.startElement("rdf:Alt");
+ aXmlWriter.startElement("rdf:li");
+ aXmlWriter.attribute("xml:lang", "x-default"_ostr);
+ aXmlWriter.content(msTitle);
+ aXmlWriter.endElement();
+ aXmlWriter.endElement();
+ aXmlWriter.endElement();
+ }
+ if (!msAuthor.isEmpty())
+ {
+ aXmlWriter.startElement("dc:creator");
+ aXmlWriter.startElement("rdf:Seq");
+ aXmlWriter.startElement("rdf:li");
+ aXmlWriter.content(msAuthor);
+ aXmlWriter.endElement();
+ aXmlWriter.endElement();
+ aXmlWriter.endElement();
+ }
+ if (!msSubject.isEmpty())
+ {
+ aXmlWriter.startElement("dc:description");
+ aXmlWriter.startElement("rdf:Alt");
+ aXmlWriter.startElement("rdf:li");
+ aXmlWriter.attribute("xml:lang", "x-default"_ostr);
+ aXmlWriter.content(msSubject);
+ aXmlWriter.endElement();
+ aXmlWriter.endElement();
+ aXmlWriter.endElement();
+ }
+ if (!maContributor.empty())
+ {
+ aXmlWriter.startElement("dc:contributor");
+ aXmlWriter.startElement("rdf:Bag");
+ for (const OString& rContributor : maContributor)
+ {
+ aXmlWriter.startElement("rdf:li");
+ aXmlWriter.content(rContributor);
+ aXmlWriter.endElement();
+ }
+ aXmlWriter.endElement();
+ aXmlWriter.endElement();
+ }
+ if (!msCoverage.isEmpty())
+ {
+ aXmlWriter.startElement("dc:coverage");
+ aXmlWriter.content(msCoverage);
+ aXmlWriter.endElement();
+ }
+ if (!msIdentifier.isEmpty())
+ {
+ aXmlWriter.startElement("dc:identifier");
+ aXmlWriter.content(msIdentifier);
+ aXmlWriter.endElement();
+ }
+ if (!maPublisher.empty())
+ {
+ aXmlWriter.startElement("dc:publisher");
+ aXmlWriter.startElement("rdf:Bag");
+ for (const OString& rPublisher : maPublisher)
+ {
+ aXmlWriter.startElement("rdf:li");
+ aXmlWriter.content(rPublisher);
+ aXmlWriter.endElement();
+ }
+ aXmlWriter.endElement();
+ aXmlWriter.endElement();
+ }
+ if (!maRelation.empty())
+ {
+ aXmlWriter.startElement("dc:relation");
+ aXmlWriter.startElement("rdf:Bag");
+ for (const OString& rRelation : maRelation)
+ {
+ aXmlWriter.startElement("rdf:li");
+ aXmlWriter.content(rRelation);
+ aXmlWriter.endElement();
+ }
+ aXmlWriter.endElement();
+ aXmlWriter.endElement();
+ }
+ if (!msRights.isEmpty())
+ {
+ aXmlWriter.startElement("dc:rights");
+ aXmlWriter.startElement("rdf:Alt");
+ aXmlWriter.startElement("rdf:li");
+ aXmlWriter.attribute("xml:lang", "x-default"_ostr);
+ aXmlWriter.content(msRights);
+ aXmlWriter.endElement();
+ aXmlWriter.endElement();
+ aXmlWriter.endElement();
+ }
+ if (!msSource.isEmpty())
+ {
+ aXmlWriter.startElement("dc:source");
+ aXmlWriter.content(msSource);
+ aXmlWriter.endElement();
+ }
+ if (!msType.isEmpty())
+ {
+ aXmlWriter.startElement("dc:type");
+ aXmlWriter.content(msType);
+ aXmlWriter.endElement();
+ }
+ aXmlWriter.endElement();
+ }
+
+ // PDF/UA
+ if (mbPDF_UA)
+ {
+ if (mnPDF_A != 0)
+ { // tdf#157517 PDF/A extension schema is required
+ aXmlWriter.startElement("rdf:Description");
+ aXmlWriter.attribute("rdf:about", ""_ostr);
+ aXmlWriter.attribute("xmlns:pdfaExtension",
+ "http://www.aiim.org/pdfa/ns/extension/"_ostr);
+ aXmlWriter.attribute("xmlns:pdfaSchema",
+ "http://www.aiim.org/pdfa/ns/schema#"_ostr);
+ aXmlWriter.attribute("xmlns:pdfaProperty",
+ "http://www.aiim.org/pdfa/ns/property#"_ostr);
+ aXmlWriter.startElement("pdfaExtension:schemas");
+ aXmlWriter.startElement("rdf:Bag");
+ aXmlWriter.startElement("rdf:li");
+ aXmlWriter.attribute("rdf:parseType", "Resource"_ostr);
+ aXmlWriter.startElement("pdfaSchema:namespaceURI");
+ aXmlWriter.content("http://www.aiim.org/pdfua/ns/id/"_ostr);
+ aXmlWriter.endElement();
+ aXmlWriter.startElement("pdfaSchema:prefix");
+ aXmlWriter.content("pdfuaid"_ostr);
+ aXmlWriter.endElement();
+ aXmlWriter.startElement("pdfaSchema:schema");
+ aXmlWriter.content("PDF/UA identification schema"_ostr);
+ aXmlWriter.endElement();
+ aXmlWriter.startElement("pdfaSchema:property");
+ aXmlWriter.startElement("rdf:Seq");
+
+ aXmlWriter.startElement("rdf:li");
+ aXmlWriter.attribute("rdf:parseType", "Resource"_ostr);
+ aXmlWriter.startElement("pdfaProperty:category");
+ aXmlWriter.content("internal"_ostr);
+ aXmlWriter.endElement();
+ aXmlWriter.startElement("pdfaProperty:description");
+ aXmlWriter.content("PDF/UA version identifier"_ostr);
+ aXmlWriter.endElement();
+ aXmlWriter.startElement("pdfaProperty:name");
+ aXmlWriter.content("part"_ostr);
+ aXmlWriter.endElement();
+ aXmlWriter.startElement("pdfaProperty:valueType");
+ aXmlWriter.content("Integer"_ostr);
+ aXmlWriter.endElement();
+ aXmlWriter.endElement(); // rdf:li
+
+ aXmlWriter.startElement("rdf:li");
+ aXmlWriter.attribute("rdf:parseType", "Resource"_ostr);
+ aXmlWriter.startElement("pdfaProperty:category");
+ aXmlWriter.content("internal"_ostr);
+ aXmlWriter.endElement();
+ aXmlWriter.startElement("pdfaProperty:description");
+ aXmlWriter.content("PDF/UA amendment identifier"_ostr);
+ aXmlWriter.endElement();
+ aXmlWriter.startElement("pdfaProperty:name");
+ aXmlWriter.content("amd"_ostr);
+ aXmlWriter.endElement();
+ aXmlWriter.startElement("pdfaProperty:valueType");
+ aXmlWriter.content("Text"_ostr);
+ aXmlWriter.endElement();
+ aXmlWriter.endElement(); // rdf:li
+
+ aXmlWriter.startElement("rdf:li");
+ aXmlWriter.attribute("rdf:parseType", "Resource"_ostr);
+ aXmlWriter.startElement("pdfaProperty:category");
+ aXmlWriter.content("internal"_ostr);
+ aXmlWriter.endElement();
+ aXmlWriter.startElement("pdfaProperty:description");
+ aXmlWriter.content("PDF/UA corrigenda identifier"_ostr);
+ aXmlWriter.endElement();
+ aXmlWriter.startElement("pdfaProperty:name");
+ aXmlWriter.content("corr"_ostr);
+ aXmlWriter.endElement();
+ aXmlWriter.startElement("pdfaProperty:valueType");
+ aXmlWriter.content("Text"_ostr);
+ aXmlWriter.endElement();
+ aXmlWriter.endElement(); // rdf:li
+
+ aXmlWriter.endElement(); // rdf:Seq
+ aXmlWriter.endElement(); // pdfaSchema:property
+ aXmlWriter.endElement(); // rdf:li
+ aXmlWriter.endElement(); // rdf:Bag
+ aXmlWriter.endElement(); // pdfaExtension:schemas
+ aXmlWriter.endElement(); // rdf:Description
+ }
+ OString sPdfUaVersion = OString::number(1);
+ aXmlWriter.startElement("rdf:Description");
+ aXmlWriter.attribute("rdf:about", ""_ostr);
+ aXmlWriter.attribute("xmlns:pdfuaid", "http://www.aiim.org/pdfua/ns/id/"_ostr);
+
+ aXmlWriter.startElement("pdfuaid:part");
+ aXmlWriter.content(sPdfUaVersion);
+ aXmlWriter.endElement();
+
+ aXmlWriter.endElement();
+ }
+
+ // PDF properties
+ if (!msProducer.isEmpty() || !msKeywords.isEmpty() || !msPDFVersion.isEmpty())
+ {
+ aXmlWriter.startElement("rdf:Description");
+ aXmlWriter.attribute("rdf:about", ""_ostr);
+ aXmlWriter.attribute("xmlns:pdf", "http://ns.adobe.com/pdf/1.3/"_ostr);
+ if (!msProducer.isEmpty())
+ {
+ aXmlWriter.startElement("pdf:Producer");
+ aXmlWriter.content(msProducer);
+ aXmlWriter.endElement();
+ }
+ if (!msKeywords.isEmpty())
+ {
+ aXmlWriter.startElement("pdf:Keywords");
+ aXmlWriter.content(msKeywords);
+ aXmlWriter.endElement();
+ }
+ if (!msPDFVersion.isEmpty())
+ {
+ aXmlWriter.startElement("pdf:PDFVersion");
+ aXmlWriter.content(msPDFVersion);
+ aXmlWriter.endElement();
+ }
+ aXmlWriter.endElement();
+ }
+
+ // XMP Basic schema
+ aXmlWriter.startElement("rdf:Description");
+ aXmlWriter.attribute("rdf:about", ""_ostr);
+ aXmlWriter.attribute("xmlns:xmp", "http://ns.adobe.com/xap/1.0/"_ostr);
+ if (!m_sCreatorTool.isEmpty())
+ {
+ aXmlWriter.startElement("xmp:CreatorTool");
+ aXmlWriter.content(m_sCreatorTool);
+ aXmlWriter.endElement();
+ }
+ aXmlWriter.startElement("xmp:CreateDate");
+ aXmlWriter.content(m_sCreateDate);
+ aXmlWriter.endElement();
+
+ aXmlWriter.startElement("xmp:ModifyDate");
+ aXmlWriter.content(m_sCreateDate);
+ aXmlWriter.endElement();
+
+ aXmlWriter.startElement("xmp:MetadataDate");
+ aXmlWriter.content(m_sCreateDate);
+ aXmlWriter.endElement();
+
+ aXmlWriter.endElement();
+ aXmlWriter.endElement();
+ aXmlWriter.endElement();
+ aXmlWriter.endDocument();
+ }
+
+ // add padding (needed so the metadata can be changed in-place"
+ for (sal_Int32 nSpaces = 1; nSpaces <= 21; nSpaces++)
+ mpMemoryStream->WriteOString(constPadding);
+
+ mpMemoryStream->WriteOString("<?xpacket end=\"w\"?>\n");
+ mbWritten = true;
+}
+
+sal_uInt64 XmpMetadata::getSize()
+{
+ if (!mbWritten)
+ write();
+ return mpMemoryStream->GetSize();
+}
+
+const void* XmpMetadata::getData()
+{
+ if (!mbWritten)
+ write();
+ return mpMemoryStream->GetData();
+}
+
+} // end vcl::pdf
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */