Skip to content

Commit e5d41c1

Browse files
dmitry.radchukintrofog
authored andcommitted
Save XMP metadata in canonical format for PDF/A documents.
DEVSIX-6355 Autoported commit. Original commit hash: [fc7285a11] Manual files: kernel/src/main/java/com/itextpdf/kernel/xmp/impl/XMPSerializerRDF.java
1 parent 790949b commit e5d41c1

File tree

5 files changed

+61
-35
lines changed

5 files changed

+61
-35
lines changed

itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfDocumentTest.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ source product.
5454
using iText.Kernel.Pdf.Tagging;
5555
using iText.Kernel.Pdf.Xobject;
5656
using iText.Kernel.Utils;
57+
using iText.Kernel.XMP.Options;
5758
using iText.Test;
5859
using iText.Test.Attributes;
5960

@@ -510,6 +511,14 @@ public virtual void RootCannotBeReferenceFromTrailerTest() {
510511
NUnit.Framework.Assert.AreEqual(KernelExceptionMessageConstant.CORRUPTED_ROOT_ENTRY_IN_TRAILER, e.Message);
511512
}
512513

514+
[NUnit.Framework.Test]
515+
public virtual void SetSerializeOptionsTest() {
516+
PdfDocument document = new PdfDocument(new PdfWriter(new MemoryStream()));
517+
SerializeOptions options = new SerializeOptions().SetUseCanonicalFormat(true);
518+
document.SetSerializeOptions(options);
519+
NUnit.Framework.Assert.AreEqual(options, document.GetSerializeOptions());
520+
}
521+
513522
private class IgnoreTagStructurePdfDocument : PdfDocument {
514523
internal IgnoreTagStructurePdfDocument(PdfReader reader)
515524
: base(reader) {

itext.tests/itext.pdfa.tests/itext/pdfa/PdfAXmpTest.cs

Lines changed: 38 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -99,33 +99,46 @@ public virtual void KeywordsInfoTestPdfA2b() {
9999
}
100100

101101
[NUnit.Framework.Test]
102-
public virtual void SaveAndReadDocumentWithCanonicalXmpMetadata()
103-
{
102+
public virtual void SaveAndReadDocumentWithCanonicalXmpMetadata() {
104103
String outFile = destinationFolder + "saveAndReadDocumentWithCanonicalXmpMetadata.pdf";
104+
String cmpFile = cmpFolder + "cmp_saveAndReadDocumentWithCanonicalXmpMetadata.pdf";
105105
PdfAConformanceLevel conformanceLevel = PdfAConformanceLevel.PDF_A_2B;
106-
Stream @is = new FileStream(sourceFolder + "sRGB Color Space Profile.icm", FileMode.Open, FileAccess.Read);
107-
PdfOutputIntent outputIntent = new PdfOutputIntent("Custom", "", "http://www.color.org", "sRGB IEC61966-2.1"
108-
, @is);
109-
PdfADocument doc = new PdfADocument(new PdfWriter(outFile), conformanceLevel, outputIntent);
110-
doc.AddNewPage();
111-
XMPMeta xmp = XMPMetaFactory.Create();
112-
xmp.SetProperty(XMPConst.NS_PDFA_ID, XMPConst.PART, conformanceLevel.GetPart(), new PropertyOptions().SetSchemaNode(true));
113-
xmp.SetProperty(XMPConst.NS_PDFA_ID, XMPConst.CONFORMANCE, conformanceLevel.GetConformance(), new PropertyOptions().SetSchemaNode(true));
114-
var options = new SerializeOptions().SetUseCanonicalFormat(true).SetUseCompactFormat(false);
115-
doc.SetXmpMetadata(xmp, options);
116-
doc.SetTagged();
117-
doc.Close();
118-
PdfReader reader = new PdfReader(outFile);
119-
PdfDocument resultDoc = new PdfDocument(reader);
120-
PdfAConformanceLevel conformanceLevelResult = resultDoc.GetReader().GetPdfAConformanceLevel();
121-
NUnit.Framework.Assert.IsNotNull(conformanceLevelResult);
122-
NUnit.Framework.Assert.AreEqual(conformanceLevel.GetConformance(), conformanceLevelResult.GetConformance());
123-
NUnit.Framework.Assert.AreEqual(conformanceLevel.GetPart(), conformanceLevelResult.GetPart());
124-
byte[] xmpResultBytes = resultDoc.GetXmpMetadata();
125-
resultDoc.Close();
126-
NUnit.Framework.Assert.IsNotNull(xmpResultBytes);
127-
XMPMeta xmpResult = XMPMetaFactory.ParseFromBuffer(xmpResultBytes);
128-
NUnit.Framework.Assert.IsNotNull(xmpResult);
106+
PdfOutputIntent outputIntent;
107+
using (Stream @is = new FileStream(sourceFolder + "sRGB Color Space Profile.icm", FileMode.Open, FileAccess.Read
108+
)) {
109+
outputIntent = new PdfOutputIntent("Custom", "", "http://www.color.org", "sRGB IEC61966-2.1", @is);
110+
}
111+
using (PdfADocument doc = new PdfADocument(new PdfWriter(outFile), conformanceLevel, outputIntent)) {
112+
doc.AddNewPage();
113+
XMPMeta xmp = XMPMetaFactory.Create();
114+
xmp.SetProperty(XMPConst.NS_PDFA_ID, XMPConst.PART, conformanceLevel.GetPart(), new PropertyOptions().SetSchemaNode
115+
(true));
116+
xmp.SetProperty(XMPConst.NS_PDFA_ID, XMPConst.CONFORMANCE, conformanceLevel.GetConformance(), new PropertyOptions
117+
().SetSchemaNode(true));
118+
SerializeOptions options = new SerializeOptions().SetUseCanonicalFormat(true).SetUseCompactFormat(false);
119+
doc.SetXmpMetadata(xmp, options);
120+
doc.SetTagged();
121+
}
122+
// Closing document and reopening it to flush it XMP metadata ModifyDate
123+
using (PdfDocument doc_1 = new PdfDocument(new PdfReader(outFile))) {
124+
using (PdfDocument cmpDoc = new PdfDocument(new PdfReader(cmpFile))) {
125+
byte[] rdf = doc_1.GetXmpMetadata();
126+
byte[] expectedRdf = cmpDoc.GetXmpMetadata();
127+
// Comparing angle brackets, since it's the main difference between canonical and compact format.
128+
NUnit.Framework.Assert.AreEqual(Count(expectedRdf, (byte)'<'), Count(rdf, (byte)'<'));
129+
NUnit.Framework.Assert.IsNull(new CompareTool().CompareXmp(cmpFile, outFile, true));
130+
}
131+
}
132+
}
133+
134+
private int Count(byte[] array, byte b) {
135+
int counter = 0;
136+
foreach (byte each in array) {
137+
if (each == b) {
138+
counter++;
139+
}
140+
}
141+
return counter;
129142
}
130143
}
131144
}

itext/itext.kernel/itext/kernel/pdf/PdfDocument.cs

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -266,12 +266,11 @@ protected internal virtual void SetXmpMetadata(byte[] xmpMetadata) {
266266
}
267267

268268
/// <summary>Sets the XMP Metadata.</summary>
269-
/// <remarks>SerializeOptions are saved for the lifetime of PdfDocument.</remarks>
270269
/// <param name="xmpMeta">the xmpMetadata to set</param>
271-
/// <param name="options">serialization options</param>
272-
public virtual void SetXmpMetadata(XMPMeta xmpMeta, SerializeOptions options) {
273-
serializeOptions = options;
274-
SetXmpMetadata(XMPMetaFactory.SerializeToBuffer(xmpMeta, options));
270+
/// <param name="serializeOptions">serialization options</param>
271+
public virtual void SetXmpMetadata(XMPMeta xmpMeta, SerializeOptions serializeOptions) {
272+
this.serializeOptions = serializeOptions;
273+
SetXmpMetadata(XMPMetaFactory.SerializeToBuffer(xmpMeta, serializeOptions));
275274
}
276275

277276
/// <summary>Sets the XMP Metadata.</summary>
@@ -1923,10 +1922,15 @@ public virtual SequenceId GetDocumentIdWrapper() {
19231922
}
19241923

19251924
/// <summary>Sets a persistent XMP metadata serialization options.</summary>
1926-
/// <param name="options"><see cref="iText.Kernel.XMP.Options.SerializeOptions"/>.</param>
1927-
public virtual void SetSerializeOptions(SerializeOptions options)
1928-
{
1929-
serializeOptions = options;
1925+
/// <param name="serializeOptions">serialize options</param>
1926+
public virtual void SetSerializeOptions(SerializeOptions serializeOptions) {
1927+
this.serializeOptions = serializeOptions;
1928+
}
1929+
1930+
/// <summary>Gets a persistent XMP metadata serialization options.</summary>
1931+
/// <returns>serialize options</returns>
1932+
public virtual SerializeOptions GetSerializeOptions() {
1933+
return this.serializeOptions;
19301934
}
19311935

19321936
/// <summary>Gets list of indirect references.</summary>

port-hash

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1f198bd359f569b7f2ea00ccdd66ec4a2d7cde9e
1+
89de8b416485c6e009d341824fa83e2a941fceae

0 commit comments

Comments
 (0)