tdf#145056 Delete autofilter settings when turning off autofilter
[LibreOffice.git] / vcl / source / pdf / XmpMetadata.cxx
blob0bc84404321ea337871354201fc9542fe8561715
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 */
11 #include <sal/config.h>
13 #include <string_view>
15 #include <pdf/XmpMetadata.hxx>
16 #include <tools/XmlWriter.hxx>
18 namespace vcl::pdf
20 namespace
22 constexpr const char* constPadding = " "
23 " "
24 " "
25 " "
26 " "
27 "\n";
30 XmpMetadata::XmpMetadata() = default;
32 void XmpMetadata::write()
34 mpMemoryStream = std::make_unique<SvMemoryStream>(4096 /*Initial*/, 64 /*Resize*/);
36 // Header
37 mpMemoryStream->WriteOString(std::string_view(reinterpret_cast<char const*>(
38 u8"<?xpacket begin=\"\uFEFF\" id=\"W5M0MpCehiHzreSzNTczkc9d\"?>\n")));
41 tools::XmlWriter aXmlWriter(mpMemoryStream.get());
42 aXmlWriter.startDocument(2, false);
43 aXmlWriter.startElement("x"_ostr, "xmpmeta"_ostr, "adobe:ns:meta/"_ostr);
44 aXmlWriter.startElement("rdf"_ostr, "RDF"_ostr,
45 "http://www.w3.org/1999/02/22-rdf-syntax-ns#"_ostr);
47 // PDF/A part ( ISO 19005-1:2005 - 6.7.11 )
48 if (mnPDF_A > 0)
50 OString sPdfVersion = OString::number(mnPDF_A);
52 aXmlWriter.startElement("rdf:Description");
53 aXmlWriter.attribute("rdf:about", ""_ostr);
54 aXmlWriter.attribute("xmlns:pdfaid", "http://www.aiim.org/pdfa/ns/id/"_ostr);
56 aXmlWriter.startElement("pdfaid:part");
57 aXmlWriter.content(sPdfVersion);
58 aXmlWriter.endElement();
60 if (mnPDF_A == 4)
62 aXmlWriter.startElement("pdfaid:rev");
63 aXmlWriter.content("2020"_ostr);
64 aXmlWriter.endElement();
67 if (!msConformance.isEmpty())
69 aXmlWriter.startElement("pdfaid:conformance");
70 aXmlWriter.content(msConformance);
71 aXmlWriter.endElement();
73 aXmlWriter.endElement();
76 // Dublin Core properties
77 if (!msTitle.isEmpty() || !msAuthor.isEmpty() || !msSubject.isEmpty()
78 || !maContributor.empty() || !msCoverage.isEmpty() || !msIdentifier.isEmpty()
79 || !maPublisher.empty() || !maRelation.empty() || !msRights.isEmpty()
80 || !msSource.isEmpty() || !msType.isEmpty())
82 aXmlWriter.startElement("rdf:Description");
83 aXmlWriter.attribute("rdf:about", ""_ostr);
84 aXmlWriter.attribute("xmlns:dc", "http://purl.org/dc/elements/1.1/"_ostr);
86 aXmlWriter.startElement("dc:format");
87 aXmlWriter.content("application/pdf"_ostr);
88 aXmlWriter.endElement();
90 aXmlWriter.startElement("dc:date");
91 aXmlWriter.startElement("rdf:Seq");
92 aXmlWriter.startElement("rdf:li");
93 aXmlWriter.content(m_sCreateDate);
94 aXmlWriter.endElement();
95 aXmlWriter.endElement();
96 aXmlWriter.endElement();
98 if (!msTitle.isEmpty())
100 // this is according to PDF/A-1, technical corrigendum 1 (2007-04-01)
101 aXmlWriter.startElement("dc:title");
102 aXmlWriter.startElement("rdf:Alt");
103 aXmlWriter.startElement("rdf:li");
104 aXmlWriter.attribute("xml:lang", "x-default"_ostr);
105 aXmlWriter.content(msTitle);
106 aXmlWriter.endElement();
107 aXmlWriter.endElement();
108 aXmlWriter.endElement();
110 if (!msAuthor.isEmpty())
112 aXmlWriter.startElement("dc:creator");
113 aXmlWriter.startElement("rdf:Seq");
114 aXmlWriter.startElement("rdf:li");
115 aXmlWriter.content(msAuthor);
116 aXmlWriter.endElement();
117 aXmlWriter.endElement();
118 aXmlWriter.endElement();
120 if (!msSubject.isEmpty())
122 aXmlWriter.startElement("dc:description");
123 aXmlWriter.startElement("rdf:Alt");
124 aXmlWriter.startElement("rdf:li");
125 aXmlWriter.attribute("xml:lang", "x-default"_ostr);
126 aXmlWriter.content(msSubject);
127 aXmlWriter.endElement();
128 aXmlWriter.endElement();
129 aXmlWriter.endElement();
131 if (!maContributor.empty())
133 aXmlWriter.startElement("dc:contributor");
134 aXmlWriter.startElement("rdf:Bag");
135 for (const OString& rContributor : maContributor)
137 aXmlWriter.startElement("rdf:li");
138 aXmlWriter.content(rContributor);
139 aXmlWriter.endElement();
141 aXmlWriter.endElement();
142 aXmlWriter.endElement();
144 if (!msCoverage.isEmpty())
146 aXmlWriter.startElement("dc:coverage");
147 aXmlWriter.content(msCoverage);
148 aXmlWriter.endElement();
150 if (!msIdentifier.isEmpty())
152 aXmlWriter.startElement("dc:identifier");
153 aXmlWriter.content(msIdentifier);
154 aXmlWriter.endElement();
156 if (!maPublisher.empty())
158 aXmlWriter.startElement("dc:publisher");
159 aXmlWriter.startElement("rdf:Bag");
160 for (const OString& rPublisher : maPublisher)
162 aXmlWriter.startElement("rdf:li");
163 aXmlWriter.content(rPublisher);
164 aXmlWriter.endElement();
166 aXmlWriter.endElement();
167 aXmlWriter.endElement();
169 if (!maRelation.empty())
171 aXmlWriter.startElement("dc:relation");
172 aXmlWriter.startElement("rdf:Bag");
173 for (const OString& rRelation : maRelation)
175 aXmlWriter.startElement("rdf:li");
176 aXmlWriter.content(rRelation);
177 aXmlWriter.endElement();
179 aXmlWriter.endElement();
180 aXmlWriter.endElement();
182 if (!msRights.isEmpty())
184 aXmlWriter.startElement("dc:rights");
185 aXmlWriter.startElement("rdf:Alt");
186 aXmlWriter.startElement("rdf:li");
187 aXmlWriter.attribute("xml:lang", "x-default"_ostr);
188 aXmlWriter.content(msRights);
189 aXmlWriter.endElement();
190 aXmlWriter.endElement();
191 aXmlWriter.endElement();
193 if (!msSource.isEmpty())
195 aXmlWriter.startElement("dc:source");
196 aXmlWriter.content(msSource);
197 aXmlWriter.endElement();
199 if (!msType.isEmpty())
201 aXmlWriter.startElement("dc:type");
202 aXmlWriter.content(msType);
203 aXmlWriter.endElement();
205 aXmlWriter.endElement();
208 // PDF/UA
209 if (mnPDF_UA > 0)
211 if (mnPDF_A != 0)
212 { // tdf#157517 PDF/A extension schema is required
213 aXmlWriter.startElement("rdf:Description");
214 aXmlWriter.attribute("rdf:about", ""_ostr);
215 aXmlWriter.attribute("xmlns:pdfaExtension",
216 "http://www.aiim.org/pdfa/ns/extension/"_ostr);
217 aXmlWriter.attribute("xmlns:pdfaSchema",
218 "http://www.aiim.org/pdfa/ns/schema#"_ostr);
219 aXmlWriter.attribute("xmlns:pdfaProperty",
220 "http://www.aiim.org/pdfa/ns/property#"_ostr);
221 aXmlWriter.startElement("pdfaExtension:schemas");
222 aXmlWriter.startElement("rdf:Bag");
223 aXmlWriter.startElement("rdf:li");
224 aXmlWriter.attribute("rdf:parseType", "Resource"_ostr);
225 aXmlWriter.startElement("pdfaSchema:namespaceURI");
226 aXmlWriter.content("http://www.aiim.org/pdfua/ns/id/"_ostr);
227 aXmlWriter.endElement();
228 aXmlWriter.startElement("pdfaSchema:prefix");
229 aXmlWriter.content("pdfuaid"_ostr);
230 aXmlWriter.endElement();
231 aXmlWriter.startElement("pdfaSchema:schema");
232 aXmlWriter.content("PDF/UA identification schema"_ostr);
233 aXmlWriter.endElement();
234 aXmlWriter.startElement("pdfaSchema:property");
235 aXmlWriter.startElement("rdf:Seq");
237 aXmlWriter.startElement("rdf:li");
238 aXmlWriter.attribute("rdf:parseType", "Resource"_ostr);
239 aXmlWriter.startElement("pdfaProperty:category");
240 aXmlWriter.content("internal"_ostr);
241 aXmlWriter.endElement();
242 aXmlWriter.startElement("pdfaProperty:description");
243 aXmlWriter.content("PDF/UA version identifier"_ostr);
244 aXmlWriter.endElement();
245 aXmlWriter.startElement("pdfaProperty:name");
246 aXmlWriter.content("part"_ostr);
247 aXmlWriter.endElement();
248 aXmlWriter.startElement("pdfaProperty:valueType");
249 aXmlWriter.content("Integer"_ostr);
250 aXmlWriter.endElement();
251 aXmlWriter.endElement(); // rdf:li
253 aXmlWriter.startElement("rdf:li");
254 aXmlWriter.attribute("rdf:parseType", "Resource"_ostr);
255 aXmlWriter.startElement("pdfaProperty:category");
256 aXmlWriter.content("internal"_ostr);
257 aXmlWriter.endElement();
258 aXmlWriter.startElement("pdfaProperty:description");
259 aXmlWriter.content("PDF/UA amendment identifier"_ostr);
260 aXmlWriter.endElement();
261 aXmlWriter.startElement("pdfaProperty:name");
262 aXmlWriter.content("amd"_ostr);
263 aXmlWriter.endElement();
264 aXmlWriter.startElement("pdfaProperty:valueType");
265 aXmlWriter.content("Text"_ostr);
266 aXmlWriter.endElement();
267 aXmlWriter.endElement(); // rdf:li
269 aXmlWriter.startElement("rdf:li");
270 aXmlWriter.attribute("rdf:parseType", "Resource"_ostr);
271 aXmlWriter.startElement("pdfaProperty:category");
272 aXmlWriter.content("internal"_ostr);
273 aXmlWriter.endElement();
274 aXmlWriter.startElement("pdfaProperty:description");
275 aXmlWriter.content("PDF/UA corrigenda identifier"_ostr);
276 aXmlWriter.endElement();
277 aXmlWriter.startElement("pdfaProperty:name");
278 aXmlWriter.content("corr"_ostr);
279 aXmlWriter.endElement();
280 aXmlWriter.startElement("pdfaProperty:valueType");
281 aXmlWriter.content("Text"_ostr);
282 aXmlWriter.endElement();
283 aXmlWriter.endElement(); // rdf:li
285 aXmlWriter.endElement(); // rdf:Seq
286 aXmlWriter.endElement(); // pdfaSchema:property
287 aXmlWriter.endElement(); // rdf:li
288 aXmlWriter.endElement(); // rdf:Bag
289 aXmlWriter.endElement(); // pdfaExtension:schemas
290 aXmlWriter.endElement(); // rdf:Description
292 OString sPdfUaVersion = OString::number(mnPDF_UA);
293 aXmlWriter.startElement("rdf:Description");
294 aXmlWriter.attribute("rdf:about", ""_ostr);
295 aXmlWriter.attribute("xmlns:pdfuaid", "http://www.aiim.org/pdfua/ns/id/"_ostr);
297 aXmlWriter.startElement("pdfuaid:part");
298 aXmlWriter.content(sPdfUaVersion);
299 aXmlWriter.endElement();
301 if (mnPDF_UA == 2)
303 aXmlWriter.startElement("pdfuaid:rev");
304 aXmlWriter.content("2024"_ostr);
305 aXmlWriter.endElement();
307 aXmlWriter.endElement();
310 // PDF properties
311 if (!msProducer.isEmpty() || !msKeywords.isEmpty() || !msPDFVersion.isEmpty())
313 aXmlWriter.startElement("rdf:Description");
314 aXmlWriter.attribute("rdf:about", ""_ostr);
315 aXmlWriter.attribute("xmlns:pdf", "http://ns.adobe.com/pdf/1.3/"_ostr);
316 if (!msProducer.isEmpty())
318 aXmlWriter.startElement("pdf:Producer");
319 aXmlWriter.content(msProducer);
320 aXmlWriter.endElement();
322 if (!msKeywords.isEmpty())
324 aXmlWriter.startElement("pdf:Keywords");
325 aXmlWriter.content(msKeywords);
326 aXmlWriter.endElement();
328 if (!msPDFVersion.isEmpty())
330 aXmlWriter.startElement("pdf:PDFVersion");
331 aXmlWriter.content(msPDFVersion);
332 aXmlWriter.endElement();
334 aXmlWriter.endElement();
337 // XMP Basic schema
338 aXmlWriter.startElement("rdf:Description");
339 aXmlWriter.attribute("rdf:about", ""_ostr);
340 aXmlWriter.attribute("xmlns:xmp", "http://ns.adobe.com/xap/1.0/"_ostr);
341 if (!m_sCreatorTool.isEmpty())
343 aXmlWriter.startElement("xmp:CreatorTool");
344 aXmlWriter.content(m_sCreatorTool);
345 aXmlWriter.endElement();
347 aXmlWriter.startElement("xmp:CreateDate");
348 aXmlWriter.content(m_sCreateDate);
349 aXmlWriter.endElement();
351 aXmlWriter.startElement("xmp:ModifyDate");
352 aXmlWriter.content(m_sCreateDate);
353 aXmlWriter.endElement();
355 aXmlWriter.startElement("xmp:MetadataDate");
356 aXmlWriter.content(m_sCreateDate);
357 aXmlWriter.endElement();
359 aXmlWriter.endElement();
360 aXmlWriter.endElement();
361 aXmlWriter.endElement();
362 aXmlWriter.endDocument();
365 // add padding (needed so the metadata can be changed in-place"
366 for (sal_Int32 nSpaces = 1; nSpaces <= 21; nSpaces++)
367 mpMemoryStream->WriteOString(constPadding);
369 mpMemoryStream->WriteOString("<?xpacket end=\"w\"?>\n");
370 mbWritten = true;
373 sal_uInt64 XmpMetadata::getSize()
375 if (!mbWritten)
376 write();
377 return mpMemoryStream->GetSize();
380 const void* XmpMetadata::getData()
382 if (!mbWritten)
383 write();
384 return mpMemoryStream->GetData();
387 } // end vcl::pdf
389 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */