diff --git a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfDocumentTest.cs b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfDocumentTest.cs
index ffe06e8fef..f96bf55bac 100644
--- a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfDocumentTest.cs
+++ b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfDocumentTest.cs
@@ -21,6 +21,7 @@ You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
*/
using System;
+using System.Collections.Generic;
using System.IO;
using iText.Commons.Utils;
using iText.IO.Image;
@@ -32,6 +33,7 @@ You should have received a copy of the GNU Affero General Public License
using iText.Kernel.Pdf.Annot;
using iText.Kernel.Pdf.Canvas;
using iText.Kernel.Pdf.Filespec;
+using iText.Kernel.Pdf.Layer;
using iText.Kernel.Pdf.Navigation;
using iText.Kernel.Pdf.Tagging;
using iText.Kernel.Pdf.Xobject;
@@ -530,60 +532,13 @@ public virtual void GetDefaultConformanceLevelTest() {
NUnit.Framework.Assert.IsFalse(document.GetConformance().IsPdfAOrUa());
}
- //TODO DEVSIX-8490 remove this test when implemented
[NUnit.Framework.Test]
- [LogMessage(KernelLogMessageConstant.DUPLICATE_ENTRIES_IN_ORDER_ARRAY_REMOVED)]
- public virtual void RemoveDuplicatesInOrderArrayTest() {
- String inputPdf = "removeDuplicatesInOrderArray.pdf";
- String outputPdf = "removedDuplicateInOrderArray.pdf";
- PdfDocument doc = new PdfDocument(new PdfReader(SOURCE_FOLDER + inputPdf), CompareTool.CreateTestPdfWriter
- (DESTINATION_FOLDER + outputPdf));
- //Need to update OCProperties
- doc.GetCatalog().GetOCProperties(false);
+ public virtual void OcgWithTwoParentsTest() {
+ String inputPdf = "ocgWithTwoParents.pdf";
+ PdfDocument doc = new PdfDocument(new PdfReader(SOURCE_FOLDER + inputPdf));
+ IList layerList = doc.GetCatalog().GetOCProperties(false).GetLayers();
+ NUnit.Framework.Assert.AreEqual(2, layerList[4].GetParents().Count);
doc.Close();
- NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(DESTINATION_FOLDER + outputPdf, SOURCE_FOLDER
- + "cmp_" + outputPdf, DESTINATION_FOLDER));
- }
-
- //TODO DEVSIX-8490 remove this test when implemented
- [NUnit.Framework.Test]
- [LogMessage(KernelLogMessageConstant.DUPLICATE_ENTRIES_IN_ORDER_ARRAY_REMOVED)]
- public virtual void RemoveNestedDuplicatesInOrderArrayTest() {
- String inputPdf = "removeNestedDuplicatesInOrderArray.pdf";
- String outputPdf = "removedNestedDuplicatesInOrderArray.pdf";
- PdfDocument doc = new PdfDocument(new PdfReader(SOURCE_FOLDER + inputPdf), new PdfWriter(DESTINATION_FOLDER
- + outputPdf));
- //Need to update OCProperties
- doc.GetCatalog().GetOCProperties(false);
- doc.Close();
- NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(DESTINATION_FOLDER + outputPdf, SOURCE_FOLDER
- + "cmp_" + outputPdf, DESTINATION_FOLDER));
- }
-
- //TODO DEVSIX-8490 remove this test when implemented
- [NUnit.Framework.Test]
- public virtual void RemoveDuplicatesHasChildInOrderArrayTest() {
- String inputPdf = "removeDuplicatesHasChildInOrderArray.pdf";
- String outputPdf = "removedDuplicatesHasChildInOrderArray.pdf";
- PdfDocument doc = new PdfDocument(new PdfReader(SOURCE_FOLDER + inputPdf), CompareTool.CreateTestPdfWriter
- (DESTINATION_FOLDER + outputPdf));
- PdfCatalog catalog = doc.GetCatalog();
- Exception e = NUnit.Framework.Assert.Catch(typeof(PdfException), () => catalog.GetOCProperties(false));
- NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format(KernelExceptionMessageConstant.UNABLE_TO_REMOVE_DUPLICATE_LAYER
- , "4 0 R"), e.Message);
- }
-
- //TODO DEVSIX-8490 remove this test when implemented
- [NUnit.Framework.Test]
- public virtual void RemoveNestedDuplicatesHasChildInOrderArrayTest() {
- String inputPdf = "removeNestedDuplicatesHasChildInOrderArray.pdf";
- String outputPdf = "removedNestedDuplicatesHasChildInOrderArray.pdf";
- PdfDocument doc = new PdfDocument(new PdfReader(SOURCE_FOLDER + inputPdf), CompareTool.CreateTestPdfWriter
- (DESTINATION_FOLDER + outputPdf));
- PdfCatalog catalog = doc.GetCatalog();
- Exception e = NUnit.Framework.Assert.Catch(typeof(PdfException), () => catalog.GetOCProperties(false));
- NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format(KernelExceptionMessageConstant.UNABLE_TO_REMOVE_DUPLICATE_LAYER
- , "27 0 R"), e.Message);
}
[NUnit.Framework.Test]
diff --git a/itext.tests/itext.kernel.tests/itext/kernel/pdf/layer/PdfLayerTest.cs b/itext.tests/itext.kernel.tests/itext/kernel/pdf/layer/PdfLayerTest.cs
index 7f532ececb..bfe62bf799 100644
--- a/itext.tests/itext.kernel.tests/itext/kernel/pdf/layer/PdfLayerTest.cs
+++ b/itext.tests/itext.kernel.tests/itext/kernel/pdf/layer/PdfLayerTest.cs
@@ -25,7 +25,6 @@ You should have received a copy of the GNU Affero General Public License
using iText.Commons.Utils;
using iText.IO.Font.Constants;
using iText.IO.Source;
-using iText.Kernel.Exceptions;
using iText.Kernel.Font;
using iText.Kernel.Geom;
using iText.Kernel.Pdf;
@@ -466,21 +465,69 @@ public virtual void TestReadOcgFromApAnnotation() {
}
}
- //TODO DEVSIX-8490 remove this test when implemented
[NUnit.Framework.Test]
- public virtual void AddSecondParentlayerTest() {
- using (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
- using (PdfDocument doc = new PdfDocument(new PdfWriter(outputStream))) {
- PdfLayer childLayer = new PdfLayer("childLayer", doc);
- PdfLayer parentLayer1 = new PdfLayer("firstParentLayer", doc);
- PdfLayer parentLayer2 = new PdfLayer("secondParentLayer", doc);
- parentLayer1.AddChild(childLayer);
- PdfIndirectReference @ref = childLayer.GetIndirectReference();
- Exception e = NUnit.Framework.Assert.Catch(typeof(PdfException), () => parentLayer2.AddChild(childLayer));
- NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format(KernelExceptionMessageConstant.UNABLE_TO_ADD_SECOND_PARENT_LAYER
- , @ref.ToString()), e.Message);
- }
- }
+ public virtual void NestedLayerTwoParentsTest() {
+ String outPdf = destinationFolder + "nestedLayerTwoParents.pdf";
+ String cmpPdf = sourceFolder + "cmp_nestedLayerTwoParents.pdf";
+ PdfDocument pdfDoc = new PdfDocument(CompareTool.CreateTestPdfWriter(outPdf));
+ PdfFont font = PdfFontFactory.CreateFont();
+ PdfLayer parentLayer1 = new PdfLayer("Parent layer 1", pdfDoc);
+ PdfLayer parentLayer2 = new PdfLayer("Parent layer 2", pdfDoc);
+ PdfLayer nestedLayer = new PdfLayer("Nested layer 1", pdfDoc);
+ parentLayer1.AddChild(nestedLayer);
+ parentLayer2.AddChild(nestedLayer);
+ PdfCanvas canvas = new PdfCanvas(pdfDoc.AddNewPage());
+ canvas.SetFontAndSize(font, 12);
+ PdfLayerTestUtils.AddTextInsideLayer(parentLayer1, canvas, "Parent layer 1 text", 50, 750);
+ PdfLayerTestUtils.AddTextInsideLayer(parentLayer2, canvas, "Parent layer 2 text", 50, 700);
+ PdfLayerTestUtils.AddTextInsideLayer(nestedLayer, canvas, "Nested layer 1 text", 100, 650);
+ canvas.Release();
+ pdfDoc.Close();
+ PdfLayerTestUtils.CompareLayers(outPdf, cmpPdf);
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void NestedLayerTwoParentsWithOneParentTest() {
+ String outPdf = destinationFolder + "nestedLayerTwoParentsWithOneParent.pdf";
+ String cmpPdf = sourceFolder + "cmp_nestedLayerTwoParentsWithOneParent.pdf";
+ PdfDocument pdfDoc = new PdfDocument(CompareTool.CreateTestPdfWriter(outPdf));
+ PdfFont font = PdfFontFactory.CreateFont();
+ PdfLayer parentLayer = new PdfLayer("Parent layer", pdfDoc);
+ PdfLayer layer1 = new PdfLayer("Layer 1", pdfDoc);
+ PdfLayer layer2 = new PdfLayer("Layer 2", pdfDoc);
+ PdfLayer nestedLayer = new PdfLayer("Nested layer 1", pdfDoc);
+ layer1.AddChild(nestedLayer);
+ layer2.AddChild(nestedLayer);
+ parentLayer.AddChild(layer1);
+ parentLayer.AddChild(layer2);
+ PdfCanvas canvas = new PdfCanvas(pdfDoc.AddNewPage());
+ canvas.SetFontAndSize(font, 12);
+ PdfLayerTestUtils.AddTextInsideLayer(parentLayer, canvas, "Parent layer text", 50, 750);
+ PdfLayerTestUtils.AddTextInsideLayer(layer1, canvas, "layer 1 text", 100, 700);
+ PdfLayerTestUtils.AddTextInsideLayer(layer2, canvas, "layer 2 text", 100, 650);
+ PdfLayerTestUtils.AddTextInsideLayer(nestedLayer, canvas, "Nested layer text", 150, 600);
+ canvas.Release();
+ pdfDoc.Close();
+ PdfLayerTestUtils.CompareLayers(outPdf, cmpPdf);
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void DuplicatedNestedLayersTest() {
+ String outPdf = destinationFolder + "duplicatedNestedLayers.pdf";
+ String cmpPdf = sourceFolder + "cmp_duplicatedNestedLayers.pdf";
+ PdfDocument pdfDoc = new PdfDocument(CompareTool.CreateTestPdfWriter(outPdf));
+ PdfFont font = PdfFontFactory.CreateFont();
+ PdfLayer parentLayer = new PdfLayer("Parent layer", pdfDoc);
+ PdfLayer nestedLayer1 = new PdfLayer("Nested layer", pdfDoc);
+ parentLayer.AddChild(nestedLayer1);
+ parentLayer.AddChild(nestedLayer1);
+ PdfCanvas canvas = new PdfCanvas(pdfDoc.AddNewPage());
+ canvas.SetFontAndSize(font, 12);
+ PdfLayerTestUtils.AddTextInsideLayer(parentLayer, canvas, "Parent layer text", 50, 750);
+ PdfLayerTestUtils.AddTextInsideLayer(nestedLayer1, canvas, "Nested layer text", 100, 700);
+ canvas.Release();
+ pdfDoc.Close();
+ PdfLayerTestUtils.CompareLayers(outPdf, cmpPdf);
}
}
}
diff --git a/itext.tests/itext.kernel.tests/itext/kernel/pdf/layer/PdfOCPropertiesUnitTest.cs b/itext.tests/itext.kernel.tests/itext/kernel/pdf/layer/PdfOCPropertiesUnitTest.cs
index f2a257799f..7c9fc229fc 100644
--- a/itext.tests/itext.kernel.tests/itext/kernel/pdf/layer/PdfOCPropertiesUnitTest.cs
+++ b/itext.tests/itext.kernel.tests/itext/kernel/pdf/layer/PdfOCPropertiesUnitTest.cs
@@ -20,90 +20,226 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
*/
-using System;
+using System.Collections.Generic;
using System.IO;
-using iText.Commons.Utils;
using iText.IO.Source;
-using iText.Kernel.Exceptions;
using iText.Kernel.Pdf;
namespace iText.Kernel.Pdf.Layer {
[NUnit.Framework.Category("UnitTest")]
public class PdfOCPropertiesUnitTest {
- //TODO DEVSIX-8490 remove this test when implemented
[NUnit.Framework.Test]
- public virtual void RemoveOrderDuplicatesTest() {
+ public virtual void OrderArrayOcgWithTwoParentsTest() {
byte[] docBytes;
using (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
using (PdfDocument document = new PdfDocument(new PdfWriter(outputStream))) {
- PdfDictionary ocgDic = new PdfDictionary();
- ocgDic.MakeIndirect(document);
+ PdfDictionary parentOcg1 = new PdfDictionary();
+ parentOcg1.Put(PdfName.Name, new PdfString("Parent1"));
+ parentOcg1.Put(PdfName.Type, PdfName.OCG);
+ parentOcg1.MakeIndirect(document);
PdfArray orderArray = new PdfArray();
- for (int i = 0; i < 3; i++) {
- orderArray.Add(ocgDic);
- }
- PdfDictionary ocgDic2 = new PdfDictionary();
- ocgDic.MakeIndirect(document);
- for (int i = 0; i < 3; i++) {
- PdfArray layerArray = new PdfArray();
- layerArray.Add(new PdfString("layerName" + i));
- layerArray.Add(ocgDic2);
- orderArray.Add(layerArray);
- }
+ orderArray.Add(parentOcg1);
+ PdfDictionary childOcg = new PdfDictionary();
+ childOcg.Put(PdfName.Name, new PdfString("child"));
+ childOcg.Put(PdfName.Type, PdfName.OCG);
+ childOcg.MakeIndirect(document);
+ PdfArray childArray = new PdfArray();
+ childArray.Add(childOcg);
+ orderArray.Add(childArray);
+ PdfDictionary parentOcg2 = new PdfDictionary();
+ parentOcg2.Put(PdfName.Name, new PdfString("Parent2"));
+ parentOcg2.Put(PdfName.Type, PdfName.OCG);
+ parentOcg2.MakeIndirect(document);
+ orderArray.Add(parentOcg2);
+ orderArray.Add(new PdfArray(childArray));
PdfDictionary DDictionary = new PdfDictionary();
DDictionary.Put(PdfName.Order, orderArray);
- PdfArray OCGsArray = new PdfArray();
- OCGsArray.Add(ocgDic);
- OCGsArray.Add(ocgDic2);
+ PdfArray ocgArray = new PdfArray();
+ ocgArray.Add(parentOcg1);
+ ocgArray.Add(parentOcg2);
+ ocgArray.Add(childOcg);
PdfDictionary OCPropertiesDic = new PdfDictionary();
OCPropertiesDic.Put(PdfName.D, DDictionary);
- OCPropertiesDic.Put(PdfName.OCGs, OCGsArray);
+ OCPropertiesDic.Put(PdfName.OCGs, ocgArray);
+ OCPropertiesDic.MakeIndirect(document);
document.GetCatalog().GetPdfObject().Put(PdfName.OCProperties, OCPropertiesDic);
- document.GetCatalog().GetOCProperties(false);
}
docBytes = outputStream.ToArray();
}
using (PdfDocument docReopen = new PdfDocument(new PdfReader(new MemoryStream(docBytes)))) {
- PdfArray resultArray = docReopen.GetCatalog().GetPdfObject().GetAsDictionary(PdfName.OCProperties).GetAsDictionary
- (PdfName.D).GetAsArray(PdfName.Order);
- NUnit.Framework.Assert.AreEqual(2, resultArray.Size());
+ IList layers = docReopen.GetCatalog().GetOCProperties(false).GetLayers();
+ NUnit.Framework.Assert.AreEqual(3, layers.Count);
+ NUnit.Framework.Assert.AreEqual(1, layers[0].GetChildren().Count);
+ NUnit.Framework.Assert.AreEqual(2, layers[1].GetParents().Count);
+ NUnit.Framework.Assert.AreEqual(1, layers[2].GetChildren().Count);
}
}
- //TODO DEVSIX-8490 remove this test when implemented
[NUnit.Framework.Test]
- public virtual void RemoveOrderDuplicateHasChildTest() {
+ public virtual void OrderArrayOcgWithTwoTitleParentsTest() {
+ byte[] docBytes;
using (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
using (PdfDocument document = new PdfDocument(new PdfWriter(outputStream))) {
- PdfDictionary ocgDic = new PdfDictionary();
- PdfDictionary ocgDicChild1 = new PdfDictionary();
- PdfDictionary ocgDicChild2 = new PdfDictionary();
- ocgDic.MakeIndirect(document);
+ PdfDictionary childOcg = new PdfDictionary();
+ childOcg.Put(PdfName.Name, new PdfString("child"));
+ childOcg.Put(PdfName.Type, PdfName.OCG);
+ childOcg.MakeIndirect(document);
+ PdfArray childArray = new PdfArray();
+ childArray.Add(childOcg);
+ PdfArray titleOcg1 = new PdfArray();
+ titleOcg1.Add(new PdfString("parent title layer 1"));
+ titleOcg1.Add(childArray);
PdfArray orderArray = new PdfArray();
- PdfArray childArray1 = new PdfArray();
- childArray1.Add(ocgDicChild1);
- PdfArray childArray2 = new PdfArray();
- childArray2.Add(ocgDicChild2);
- orderArray.Add(ocgDic);
- orderArray.Add(childArray1);
- orderArray.Add(ocgDic);
- orderArray.Add(childArray2);
+ orderArray.Add(titleOcg1);
+ PdfArray titleOcg2 = new PdfArray();
+ titleOcg2.Add(new PdfString("parent title 2"));
+ titleOcg2.Add(childArray);
+ orderArray.Add(titleOcg2);
PdfDictionary DDictionary = new PdfDictionary();
DDictionary.Put(PdfName.Order, orderArray);
- PdfArray OCGsArray = new PdfArray();
- OCGsArray.Add(ocgDic);
- OCGsArray.Add(ocgDicChild1);
- OCGsArray.Add(ocgDicChild2);
- PdfDictionary OCPropertiesDic = new PdfDictionary();
- OCPropertiesDic.Put(PdfName.D, DDictionary);
- OCPropertiesDic.Put(PdfName.OCGs, OCGsArray);
- document.GetCatalog().GetPdfObject().Put(PdfName.OCProperties, OCPropertiesDic);
- PdfIndirectReference @ref = ocgDic.GetIndirectReference();
- PdfCatalog catalog = document.GetCatalog();
- Exception e = NUnit.Framework.Assert.Catch(typeof(PdfException), () => catalog.GetOCProperties(false));
- NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format(KernelExceptionMessageConstant.UNABLE_TO_REMOVE_DUPLICATE_LAYER
- , @ref.ToString()), e.Message);
+ PdfArray ocgArray = new PdfArray();
+ ocgArray.Add(childOcg);
+ PdfDictionary ocPropertiesDic = new PdfDictionary();
+ ocPropertiesDic.Put(PdfName.D, DDictionary);
+ ocPropertiesDic.Put(PdfName.OCGs, ocgArray);
+ ocPropertiesDic.MakeIndirect(document);
+ document.GetCatalog().GetPdfObject().Put(PdfName.OCProperties, ocPropertiesDic);
}
+ docBytes = outputStream.ToArray();
+ }
+ using (PdfDocument docReopen = new PdfDocument(new PdfReader(new MemoryStream(docBytes)), new PdfWriter(new
+ ByteArrayOutputStream()))) {
+ IList layers = docReopen.GetCatalog().GetOCProperties(false).GetLayers();
+ NUnit.Framework.Assert.AreEqual(3, layers.Count);
+ NUnit.Framework.Assert.AreEqual(1, layers[0].GetChildren().Count);
+ NUnit.Framework.Assert.AreEqual(2, layers[1].GetParents().Count);
+ NUnit.Framework.Assert.AreEqual(1, layers[2].GetChildren().Count);
+ }
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void OrderArrayTitleOcgWithTwoParentsTest() {
+ byte[] docBytes;
+ using (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
+ using (PdfDocument document = new PdfDocument(new PdfWriter(outputStream))) {
+ PdfDictionary parentOcg1 = new PdfDictionary();
+ parentOcg1.Put(PdfName.Name, new PdfString("Parent1"));
+ parentOcg1.Put(PdfName.Type, PdfName.OCG);
+ parentOcg1.MakeIndirect(document);
+ PdfArray orderArray = new PdfArray();
+ orderArray.Add(parentOcg1);
+ PdfArray titleChildOcg = new PdfArray();
+ titleChildOcg.Add(new PdfString("child title layer"));
+ PdfArray childArray = new PdfArray();
+ childArray.Add(titleChildOcg);
+ orderArray.Add(childArray);
+ PdfDictionary parentOcg2 = new PdfDictionary();
+ parentOcg2.Put(PdfName.Name, new PdfString("Parent2"));
+ parentOcg2.Put(PdfName.Type, PdfName.OCG);
+ parentOcg2.MakeIndirect(document);
+ orderArray.Add(parentOcg2);
+ orderArray.Add(new PdfArray(childArray));
+ PdfDictionary DDictionary = new PdfDictionary();
+ DDictionary.Put(PdfName.Order, orderArray);
+ PdfArray ocgArray = new PdfArray();
+ ocgArray.Add(parentOcg1);
+ ocgArray.Add(parentOcg2);
+ PdfDictionary ocPropertiesDic = new PdfDictionary();
+ ocPropertiesDic.Put(PdfName.D, DDictionary);
+ ocPropertiesDic.Put(PdfName.OCGs, ocgArray);
+ ocPropertiesDic.MakeIndirect(document);
+ document.GetCatalog().GetPdfObject().Put(PdfName.OCProperties, ocPropertiesDic);
+ }
+ docBytes = outputStream.ToArray();
+ }
+ using (PdfDocument docReopen = new PdfDocument(new PdfReader(new MemoryStream(docBytes)), new PdfWriter(new
+ ByteArrayOutputStream()))) {
+ IList layers = docReopen.GetCatalog().GetOCProperties(false).GetLayers();
+ NUnit.Framework.Assert.AreEqual(3, layers.Count);
+ NUnit.Framework.Assert.AreEqual(1, layers[0].GetChildren().Count);
+ NUnit.Framework.Assert.AreEqual(2, layers[1].GetParents().Count);
+ NUnit.Framework.Assert.AreEqual(1, layers[2].GetChildren().Count);
+ }
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void OrderArrayDuplicatedOcgTest() {
+ byte[] docBytes;
+ using (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
+ using (PdfDocument document = new PdfDocument(new PdfWriter(outputStream))) {
+ PdfDictionary ocg = new PdfDictionary();
+ ocg.Put(PdfName.Name, new PdfString("ocg"));
+ ocg.Put(PdfName.Type, PdfName.OCG);
+ ocg.MakeIndirect(document);
+ PdfArray orderArray = new PdfArray();
+ orderArray.Add(ocg);
+ orderArray.Add(ocg);
+ orderArray.Add(ocg);
+ PdfDictionary parentOcg = new PdfDictionary();
+ parentOcg.Put(PdfName.Name, new PdfString("Parent"));
+ parentOcg.Put(PdfName.Type, PdfName.OCG);
+ parentOcg.MakeIndirect(document);
+ orderArray.Add(parentOcg);
+ orderArray.Add(new PdfArray(ocg));
+ PdfDictionary DDictionary = new PdfDictionary();
+ DDictionary.Put(PdfName.Order, orderArray);
+ PdfArray ocgArray = new PdfArray();
+ ocgArray.Add(ocg);
+ ocgArray.Add(parentOcg);
+ PdfDictionary ocPropertiesDic = new PdfDictionary();
+ ocPropertiesDic.Put(PdfName.D, DDictionary);
+ ocPropertiesDic.Put(PdfName.OCGs, ocgArray);
+ ocPropertiesDic.MakeIndirect(document);
+ document.GetCatalog().GetPdfObject().Put(PdfName.OCProperties, ocPropertiesDic);
+ }
+ docBytes = outputStream.ToArray();
+ }
+ using (PdfDocument docReopen = new PdfDocument(new PdfReader(new MemoryStream(docBytes)), new PdfWriter(new
+ ByteArrayOutputStream()))) {
+ IList layers = docReopen.GetCatalog().GetOCProperties(false).GetLayers();
+ NUnit.Framework.Assert.AreEqual(2, layers.Count);
+ NUnit.Framework.Assert.AreEqual(1, layers[0].GetParents().Count);
+ NUnit.Framework.Assert.AreEqual(1, layers[1].GetChildren().Count);
+ }
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void OrderArrayDuplicatedTitleOcgTest() {
+ byte[] docBytes;
+ using (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
+ using (PdfDocument document = new PdfDocument(new PdfWriter(outputStream))) {
+ PdfArray orderArray = new PdfArray();
+ PdfArray titleOcg = new PdfArray();
+ titleOcg.Add(new PdfString("title layer"));
+ orderArray.Add(titleOcg);
+ PdfDictionary parentOcg = new PdfDictionary();
+ parentOcg.Put(PdfName.Name, new PdfString("Parent"));
+ parentOcg.Put(PdfName.Type, PdfName.OCG);
+ parentOcg.MakeIndirect(document);
+ orderArray.Add(parentOcg);
+ PdfArray nestedOcg = new PdfArray();
+ nestedOcg.Add(titleOcg);
+ orderArray.Add(nestedOcg);
+ orderArray.Add(titleOcg);
+ PdfDictionary DDictionary = new PdfDictionary();
+ DDictionary.Put(PdfName.Order, orderArray);
+ PdfArray ocgArray = new PdfArray();
+ ocgArray.Add(parentOcg);
+ PdfDictionary ocPropertiesDic = new PdfDictionary();
+ ocPropertiesDic.Put(PdfName.D, DDictionary);
+ ocPropertiesDic.Put(PdfName.OCGs, ocgArray);
+ ocPropertiesDic.MakeIndirect(document);
+ document.GetCatalog().GetPdfObject().Put(PdfName.OCProperties, ocPropertiesDic);
+ }
+ docBytes = outputStream.ToArray();
+ }
+ using (PdfDocument docReopen = new PdfDocument(new PdfReader(new MemoryStream(docBytes)), new PdfWriter(new
+ ByteArrayOutputStream()))) {
+ IList layers = docReopen.GetCatalog().GetOCProperties(false).GetLayers();
+ NUnit.Framework.Assert.AreEqual(2, layers.Count);
+ NUnit.Framework.Assert.AreEqual("title layer", layers[0].GetTitle());
+ NUnit.Framework.Assert.AreEqual(1, layers[0].GetParents().Count);
+ NUnit.Framework.Assert.AreEqual(1, layers[1].GetChildren().Count);
}
}
}
diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfDocumentTest/cmp_removedDuplicateInOrderArray.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfDocumentTest/cmp_removedDuplicateInOrderArray.pdf
deleted file mode 100644
index 602e3a4c81..0000000000
Binary files a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfDocumentTest/cmp_removedDuplicateInOrderArray.pdf and /dev/null differ
diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfDocumentTest/cmp_removedNestedDuplicatesInOrderArray.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfDocumentTest/cmp_removedNestedDuplicatesInOrderArray.pdf
deleted file mode 100644
index 9da2248dfa..0000000000
Binary files a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfDocumentTest/cmp_removedNestedDuplicatesInOrderArray.pdf and /dev/null differ
diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfDocumentTest/removeDuplicatesInOrderArray.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfDocumentTest/ocgWithTwoParents.pdf
similarity index 75%
rename from itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfDocumentTest/removeDuplicatesInOrderArray.pdf
rename to itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfDocumentTest/ocgWithTwoParents.pdf
index 5afded545d..d5307b79dd 100644
Binary files a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfDocumentTest/removeDuplicatesInOrderArray.pdf and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfDocumentTest/ocgWithTwoParents.pdf differ
diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfDocumentTest/removeDuplicatesHasChildInOrderArray.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfDocumentTest/removeDuplicatesHasChildInOrderArray.pdf
deleted file mode 100644
index 2fa10d0386..0000000000
Binary files a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfDocumentTest/removeDuplicatesHasChildInOrderArray.pdf and /dev/null differ
diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfDocumentTest/removeNestedDuplicatesHasChildInOrderArray.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfDocumentTest/removeNestedDuplicatesHasChildInOrderArray.pdf
deleted file mode 100644
index 754950dda9..0000000000
Binary files a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfDocumentTest/removeNestedDuplicatesHasChildInOrderArray.pdf and /dev/null differ
diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfDocumentTest/removeNestedDuplicatesInOrderArray.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfDocumentTest/removeNestedDuplicatesInOrderArray.pdf
deleted file mode 100644
index 1f43c432c2..0000000000
Binary files a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfDocumentTest/removeNestedDuplicatesInOrderArray.pdf and /dev/null differ
diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/layer/PdfLayerTest/cmp_duplicatedNestedLayers.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/layer/PdfLayerTest/cmp_duplicatedNestedLayers.pdf
new file mode 100644
index 0000000000..a47f384cd3
Binary files /dev/null and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/layer/PdfLayerTest/cmp_duplicatedNestedLayers.pdf differ
diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/layer/PdfLayerTest/cmp_nestedLayerTwoParents.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/layer/PdfLayerTest/cmp_nestedLayerTwoParents.pdf
new file mode 100644
index 0000000000..528c3b9e2f
Binary files /dev/null and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/layer/PdfLayerTest/cmp_nestedLayerTwoParents.pdf differ
diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/layer/PdfLayerTest/cmp_nestedLayerTwoParentsWithOneParent.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/layer/PdfLayerTest/cmp_nestedLayerTwoParentsWithOneParent.pdf
new file mode 100644
index 0000000000..d90b760317
Binary files /dev/null and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/layer/PdfLayerTest/cmp_nestedLayerTwoParentsWithOneParent.pdf differ
diff --git a/itext/itext.kernel/itext/kernel/exceptions/KernelExceptionMessageConstant.cs b/itext/itext.kernel/itext/kernel/exceptions/KernelExceptionMessageConstant.cs
index b61ae47368..572efa886e 100644
--- a/itext/itext.kernel/itext/kernel/exceptions/KernelExceptionMessageConstant.cs
+++ b/itext/itext.kernel/itext/kernel/exceptions/KernelExceptionMessageConstant.cs
@@ -655,10 +655,10 @@ public const String WHEN_ADDING_OBJECT_REFERENCE_TO_THE_TAG_TREE_IT_MUST_BE_CONN
public const String INVALID_OBJECT_STREAM_NUMBER = "Unable to read object {0} with object stream " + "number {1} and index {2} from object stream.";
- //TODO DEVSIX-8490 remove this exception message when implemented
+ [Obsolete]
public const String UNABLE_TO_ADD_SECOND_PARENT_LAYER = "Unable to add second parent layer to " + "{0} ocg layer";
- //TODO DEVSIX-8490 remove this exception message when implemented
+ [Obsolete]
public const String UNABLE_TO_REMOVE_DUPLICATE_LAYER = "Unable to remove duplicated layer {0} " + "because it has child layers.";
public const String TYPE_SHOULD_NOT_BE_NULL = "ClassArgument type should not be null";
diff --git a/itext/itext.kernel/itext/kernel/logs/KernelLogMessageConstant.cs b/itext/itext.kernel/itext/kernel/logs/KernelLogMessageConstant.cs
index b5f35fe1c1..c9c54f6f7c 100644
--- a/itext/itext.kernel/itext/kernel/logs/KernelLogMessageConstant.cs
+++ b/itext/itext.kernel/itext/kernel/logs/KernelLogMessageConstant.cs
@@ -90,7 +90,7 @@ public sealed class KernelLogMessageConstant {
public const String XOBJECT_STRUCT_PARENT_INDEX_MISSED_AND_RECREATED = "XObject has no StructParents index in its stream, so index is recreated";
- //TODO DEVSIX-8490 remove this log message when implemented
+ [Obsolete]
public const String DUPLICATE_ENTRIES_IN_ORDER_ARRAY_REMOVED = "Duplicated entries in order array are " +
"removed";
diff --git a/itext/itext.kernel/itext/kernel/pdf/canvas/PdfCanvas.cs b/itext/itext.kernel/itext/kernel/pdf/canvas/PdfCanvas.cs
index 057d1e4272..fbc5fd86f7 100644
--- a/itext/itext.kernel/itext/kernel/pdf/canvas/PdfCanvas.cs
+++ b/itext/itext.kernel/itext/kernel/pdf/canvas/PdfCanvas.cs
@@ -1636,16 +1636,10 @@ public virtual iText.Kernel.Pdf.Canvas.PdfCanvas BeginLayer(IPdfOCG layer) {
}
else {
if (layer is PdfLayer) {
- int num = 0;
PdfLayer la = (PdfLayer)layer;
- while (la != null) {
- if (la.GetTitle() == null) {
- AddToPropertiesAndBeginLayer(la);
- num++;
- }
- la = la.GetParent();
- }
- layerDepth.Add(num);
+ ICollection layers = new HashSet();
+ int depth = BeginLayerTree(la, layers);
+ layerDepth.Add(depth);
}
else {
throw new NotSupportedException("Unsupported type for operand: layer");
@@ -2488,6 +2482,30 @@ private static bool IsIdentityMatrix(float a, float b, float c, float d, float e
&& Math.Abs(1 - d) < IDENTITY_MATRIX_EPS && Math.Abs(e) < IDENTITY_MATRIX_EPS && Math.Abs(f) < IDENTITY_MATRIX_EPS;
}
+ /// This method is used to traverse parent tree and begin all layers in it.
+ ///
+ /// This method is used to traverse parent tree and begin all layers in it.
+ /// If layer was already begun during method call, it will not be processed again.
+ ///
+ private int BeginLayerTree(PdfLayer layer, ICollection layers) {
+ if (layer == null || layers.Contains(layer)) {
+ return 0;
+ }
+ layers.Add(layer);
+ int depth = 0;
+ if (layer.GetTitle() == null) {
+ AddToPropertiesAndBeginLayer(layer);
+ depth++;
+ }
+ IList parentLayers = layer.GetParents();
+ if (parentLayers != null) {
+ foreach (PdfLayer parentLayer in parentLayers) {
+ depth += BeginLayerTree(parentLayer, layers);
+ }
+ }
+ return depth;
+ }
+
private enum CheckColorMode {
NONE,
FILL,
diff --git a/itext/itext.kernel/itext/kernel/pdf/layer/PdfLayer.cs b/itext/itext.kernel/itext/kernel/pdf/layer/PdfLayer.cs
index de5a67994a..45d2b8cbad 100644
--- a/itext/itext.kernel/itext/kernel/pdf/layer/PdfLayer.cs
+++ b/itext/itext.kernel/itext/kernel/pdf/layer/PdfLayer.cs
@@ -24,7 +24,6 @@ You should have received a copy of the GNU Affero General Public License
using System.Collections.Generic;
using iText.Commons.Utils;
using iText.IO.Font;
-using iText.Kernel.Exceptions;
using iText.Kernel.Pdf;
namespace iText.Kernel.Pdf.Layer {
@@ -53,10 +52,18 @@ public class PdfLayer : PdfObjectWrapper, IPdfOCG {
protected internal bool locked = false;
+ [Obsolete]
protected internal iText.Kernel.Pdf.Layer.PdfLayer parent;
+ // After removing deprecated parent rename to parents
+ protected internal ICollection parentLayers;
+
+ [Obsolete]
protected internal IList children;
+ // After removing deprecated children rename to children
+ protected internal ICollection childLayers;
+
/// Creates a new layer by existing dictionary, which must be an indirect object.
/// the layer dictionary, must have an indirect reference.
public PdfLayer(PdfDictionary layerDictionary)
@@ -115,23 +122,26 @@ public static void AddOCGRadioGroup(PdfDocument document, IListAdds a child layer. Nested layers can only have one parent.
/// the child layer
public virtual void AddChild(iText.Kernel.Pdf.Layer.PdfLayer childLayer) {
- //TODO DEVSIX-8490 implement multiple parent support
- if (childLayer.parent != null) {
- PdfIndirectReference @ref = childLayer.GetIndirectReference();
- throw new PdfException(MessageFormatUtil.Format(KernelExceptionMessageConstant.UNABLE_TO_ADD_SECOND_PARENT_LAYER
- , @ref.ToString()));
+ if (childLayer.parentLayers == null) {
+ childLayer.parentLayers = new LinkedHashSet();
}
- childLayer.parent = this;
- if (children == null) {
- children = new List();
+ childLayer.parentLayers.Add(this);
+ if (childLayers == null) {
+ childLayers = new LinkedHashSet();
}
- children.Add(childLayer);
+ childLayers.Add(childLayer);
}
- /// Gets the parent of this layer, be it a title layer, or a usual one.
- /// the parent of the layer, or null if it has no parent
+ /// Gets the first parent of this layer, be it a title layer, or a usual one.
+ /// the first parent of the layer, or null if it has no parent
public virtual iText.Kernel.Pdf.Layer.PdfLayer GetParent() {
- return parent;
+ return parentLayers == null ? null : new List(parentLayers)[0];
+ }
+
+ /// Gets all parents of this layer.
+ /// list of parents of the layer, or null if it has no parent
+ public virtual IList GetParents() {
+ return parentLayers == null ? null : new List(parentLayers);
}
/// Sets the name of the layer to be displayed in the Layers panel.
@@ -439,7 +449,7 @@ public virtual String GetTitle() {
///
/// the list of the current child layers, null if the layer has no children.
public virtual IList GetChildren() {
- return children == null ? null : new List(children);
+ return childLayers == null ? null : new List(childLayers);
}
protected internal override bool IsWrappedObjectMustBeIndirect() {
diff --git a/itext/itext.kernel/itext/kernel/pdf/layer/PdfOCProperties.cs b/itext/itext.kernel/itext/kernel/pdf/layer/PdfOCProperties.cs
index f61c976b11..5b455506dc 100644
--- a/itext/itext.kernel/itext/kernel/pdf/layer/PdfOCProperties.cs
+++ b/itext/itext.kernel/itext/kernel/pdf/layer/PdfOCProperties.cs
@@ -26,7 +26,6 @@ You should have received a copy of the GNU Affero General Public License
using iText.Commons;
using iText.Commons.Utils;
using iText.IO.Font;
-using iText.Kernel.Exceptions;
using iText.Kernel.Logs;
using iText.Kernel.Pdf;
@@ -52,12 +51,6 @@ public class PdfOCProperties : PdfObjectWrapper {
private IList layers = new List();
- //TODO DEVSIX-8490 remove this field when implemented
- private ICollection references;
-
- //TODO DEVSIX-8490 remove this field when implemented
- private bool isDuplicateRemoved;
-
/// Creates a new PdfOCProperties instance.
/// the document the optional content belongs to
public PdfOCProperties(PdfDocument document)
@@ -165,7 +158,7 @@ public virtual PdfObject FillDictionary(bool removeNonDocumentOcgs) {
IList docOrder = new List(layers);
for (int i = 0; i < docOrder.Count; i++) {
PdfLayer layer = docOrder[i];
- if (layer.GetParent() != null) {
+ if (layer.GetParents() != null) {
docOrder.Remove(layer);
i--;
}
@@ -413,14 +406,9 @@ private void ReadLayersFromDictionary() {
}
PdfArray orderArray = d.GetAsArray(PdfName.Order);
if (orderArray != null && !orderArray.IsEmpty()) {
- references = new HashSet();
- isDuplicateRemoved = false;
- ReadOrderFromDictionary(null, orderArray, layerMap);
- //TODO DEVSIX-8490 remove this check when implemented
- if (isDuplicateRemoved) {
- ILogger logger = ITextLogManager.GetLogger(typeof(iText.Kernel.Pdf.Layer.PdfOCProperties));
- logger.LogWarning(KernelLogMessageConstant.DUPLICATE_ENTRIES_IN_ORDER_ARRAY_REMOVED);
- }
+ ICollection layerReferences = new HashSet();
+ IDictionary titleLayers = new Dictionary();
+ ReadOrderFromDictionary(null, orderArray, layerMap, layerReferences, titleLayers);
}
}
// Add the layers which should not be displayed on the panel to the order list
@@ -433,7 +421,8 @@ private void ReadLayersFromDictionary() {
/// Reads the /Order in the /D entry and initialized the parent-child hierarchy.
private void ReadOrderFromDictionary(PdfLayer parent, PdfArray orderArray, IDictionary layerMap) {
+ , PdfLayer> layerMap, ICollection layerReferences, IDictionary titleLayers) {
for (int i = 0; i < orderArray.Size(); i++) {
PdfObject item = orderArray.Get(i);
if (item.GetObjectType() == PdfObject.DICTIONARY) {
@@ -441,33 +430,19 @@ private void ReadOrderFromDictionary(PdfLayer parent, PdfArray orderArray, IDict
if (layer == null) {
continue;
}
- //TODO DEVSIX-8490 remove this check and it statement when implemented
- if (references.Contains(layer.GetIndirectReference())) {
- //We want to check if this duplicate layer has childLayers, if it has - throw an exception,
- // else just don't add this layer.
- if (i + 1 < orderArray.Size() && orderArray.Get(i + 1).GetObjectType() == PdfObject.ARRAY) {
- PdfArray nextArray = orderArray.GetAsArray(i + 1);
- if (nextArray.Size() > 0 && nextArray.Get(0).GetObjectType() != PdfObject.STRING) {
- PdfIndirectReference @ref = layer.GetIndirectReference();
- throw new PdfException(MessageFormatUtil.Format(KernelExceptionMessageConstant.UNABLE_TO_REMOVE_DUPLICATE_LAYER
- , @ref.ToString()));
- }
- }
- isDuplicateRemoved = true;
- }
- else {
- references.Add(layer.GetIndirectReference());
+ if (!layerReferences.Contains(layer.GetIndirectReference())) {
+ layerReferences.Add(layer.GetIndirectReference());
layers.Add(layer);
layer.onPanel = true;
- if (parent != null) {
- parent.AddChild(layer);
- }
- if (i + 1 < orderArray.Size() && orderArray.Get(i + 1).GetObjectType() == PdfObject.ARRAY) {
- PdfArray nextArray = orderArray.GetAsArray(i + 1);
- if (nextArray.Size() > 0 && nextArray.Get(0).GetObjectType() != PdfObject.STRING) {
- ReadOrderFromDictionary(layer, orderArray.GetAsArray(i + 1), layerMap);
- i++;
- }
+ }
+ if (parent != null) {
+ parent.AddChild(layer);
+ }
+ if (i + 1 < orderArray.Size() && orderArray.Get(i + 1).GetObjectType() == PdfObject.ARRAY) {
+ PdfArray nextArray = orderArray.GetAsArray(i + 1);
+ if (nextArray.Size() > 0 && nextArray.Get(0).GetObjectType() != PdfObject.STRING) {
+ ReadOrderFromDictionary(layer, orderArray.GetAsArray(i + 1), layerMap, layerReferences, titleLayers);
+ i++;
}
}
}
@@ -479,16 +454,22 @@ private void ReadOrderFromDictionary(PdfLayer parent, PdfArray orderArray, IDict
}
PdfObject firstObj = subArray.Get(0);
if (firstObj.GetObjectType() == PdfObject.STRING) {
- PdfLayer titleLayer = PdfLayer.CreateTitleSilent(((PdfString)firstObj).ToUnicodeString(), GetDocument());
- titleLayer.onPanel = true;
- layers.Add(titleLayer);
+ PdfString title = (PdfString)firstObj;
+ PdfLayer titleLayer = titleLayers.Get(title);
+ if (titleLayer == null) {
+ titleLayer = PdfLayer.CreateTitleSilent(title.ToUnicodeString(), GetDocument());
+ titleLayer.onPanel = true;
+ layers.Add(titleLayer);
+ titleLayers.Put(title, titleLayer);
+ }
if (parent != null) {
parent.AddChild(titleLayer);
}
- ReadOrderFromDictionary(titleLayer, new PdfArray(subArray.SubList(1, subArray.Size())), layerMap);
+ ReadOrderFromDictionary(titleLayer, new PdfArray(subArray.SubList(1, subArray.Size())), layerMap, layerReferences
+ , titleLayers);
}
else {
- ReadOrderFromDictionary(parent, subArray, layerMap);
+ ReadOrderFromDictionary(parent, subArray, layerMap, layerReferences, titleLayers);
}
}
}
diff --git a/port-hash b/port-hash
index 54fa537fa1..1c918581c7 100644
--- a/port-hash
+++ b/port-hash
@@ -1 +1 @@
-028c9c8e959e6073cf53bfa6932a6ef882d4b82f
+a390afa1f077eb736e61e6d66d74a7f35354e0e4