diff --git a/.gitattributes b/.gitattributes index fe1f05c569..0b11c80608 100644 --- a/.gitattributes +++ b/.gitattributes @@ -16,6 +16,7 @@ *.txt text eol=lf *.xfdf text eol=lf *.xml text eol=lf +port-hash text eol=lf # Declare files that will always have CRLF line endings on checkout. *.bat text eol=crlf diff --git a/.gitignore b/.gitignore index 2b6310878d..4a77e07c9d 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ *.user *.userosscache *.sln.docstates +*.sln.metaproj # User-specific files (MonoDevelop/Xamarin Studio) *.userprefs diff --git a/itext.tests/itext.barcodes.tests/Properties/AssemblyInfo.cs b/itext.tests/itext.barcodes.tests/Properties/AssemblyInfo.cs index 839cbb8cc7..845136aa5a 100644 --- a/itext.tests/itext.barcodes.tests/Properties/AssemblyInfo.cs +++ b/itext.tests/itext.barcodes.tests/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; [assembly: AssemblyTitle("iText.Barcodes.Tests")] @@ -15,5 +14,7 @@ [assembly: Guid("d015a3aa-613c-45d9-b908-7d47c4b613af")] -[assembly: AssemblyVersion("7.0.0.0")] -[assembly: AssemblyFileVersion("7.0.0.0")] +[assembly: AssemblyVersion("7.0.1.0")] +[assembly: AssemblyFileVersion("7.0.1.0")] + +[assembly: NUnit.Framework.Timeout(300000)] diff --git a/itext.tests/itext.barcodes.tests/itext.barcodes.tests.csproj b/itext.tests/itext.barcodes.tests/itext.barcodes.tests.csproj index 500ca77da7..1a6629f4e3 100644 --- a/itext.tests/itext.barcodes.tests/itext.barcodes.tests.csproj +++ b/itext.tests/itext.barcodes.tests/itext.barcodes.tests.csproj @@ -37,7 +37,7 @@ - ..\..\packages\NUnit.3.2.1\lib\net40\nunit.framework.dll + $(SolutionDir)\packages\NUnit.3.2.1\lib\net40\nunit.framework.dll diff --git a/itext.tests/itext.barcodes.tests/itext/barcodes/Barcode39Test.cs b/itext.tests/itext.barcodes.tests/itext/barcodes/Barcode39Test.cs index 2948bea3d3..9886777533 100644 --- a/itext.tests/itext.barcodes.tests/itext/barcodes/Barcode39Test.cs +++ b/itext.tests/itext.barcodes.tests/itext/barcodes/Barcode39Test.cs @@ -24,8 +24,7 @@ public static void BeforeClass() { [NUnit.Framework.Test] public virtual void Barcode01Test() { String filename = "barcode39_01.pdf"; - PdfWriter writer = new PdfWriter(destinationFolder + filename); - PdfDocument document = new PdfDocument(writer); + PdfDocument document = new PdfDocument(new PdfWriter(destinationFolder + filename)); PdfPage page = document.AddNewPage(); PdfCanvas canvas = new PdfCanvas(page); Barcode1D barcode = new Barcode39(document); @@ -43,9 +42,8 @@ public virtual void Barcode01Test() { [NUnit.Framework.Test] public virtual void Barcode02Test() { String filename = "barcode39_02.pdf"; - PdfWriter writer = new PdfWriter(destinationFolder + filename); - PdfReader reader = new PdfReader(sourceFolder + "DocumentWithTrueTypeFont1.pdf"); - PdfDocument document = new PdfDocument(reader, writer); + PdfDocument document = new PdfDocument(new PdfReader(sourceFolder + "DocumentWithTrueTypeFont1.pdf"), new + PdfWriter(destinationFolder + filename)); PdfCanvas canvas = new PdfCanvas(document.GetLastPage()); Barcode1D barcode = new Barcode39(document); barcode.SetCode("9781935182610"); @@ -58,8 +56,7 @@ public virtual void Barcode02Test() { [NUnit.Framework.Test] public virtual void Barcode03Test() { - PdfWriter writer = new PdfWriter(new ByteArrayOutputStream()); - PdfDocument document = new PdfDocument(writer); + PdfDocument document = new PdfDocument(new PdfWriter(new ByteArrayOutputStream())); Barcode39 barcode = new Barcode39(document); try { Barcode39.GetBarsCode39("9781935*182610"); diff --git a/itext.tests/itext.barcodes.tests/itext/barcodes/BarcodeQRCodeTest.cs b/itext.tests/itext.barcodes.tests/itext/barcodes/BarcodeQRCodeTest.cs index 36259b8a17..1f680e6592 100644 --- a/itext.tests/itext.barcodes.tests/itext/barcodes/BarcodeQRCodeTest.cs +++ b/itext.tests/itext.barcodes.tests/itext/barcodes/BarcodeQRCodeTest.cs @@ -56,5 +56,27 @@ public virtual void Barcode02Test() { NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(destinationFolder + filename, sourceFolder + "cmp_" + filename, destinationFolder, "diff_")); } + + /// + /// + /// + [NUnit.Framework.Test] + public virtual void BarcodeVersioningTest() { + String filename = "barcodeQRCodeVersioning.pdf"; + PdfWriter writer = new PdfWriter(destinationFolder + filename); + PdfDocument document = new PdfDocument(writer); + for (int i = -9; i < 42; i += 10) { + PdfPage page1 = document.AddNewPage(); + PdfCanvas canvas = new PdfCanvas(page1); + IDictionary hints = new Dictionary(); + hints[EncodeHintType.CHARACTER_SET] = "UTF-8"; + hints[EncodeHintType.MIN_VERSION_NR] = i; + BarcodeQRCode barcode1 = new BarcodeQRCode("дима", hints); + barcode1.PlaceBarcode(canvas, Color.GRAY, 3); + } + document.Close(); + NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(destinationFolder + filename, sourceFolder + + "cmp_" + filename, destinationFolder, "diff_")); + } } } diff --git a/itext.tests/itext.barcodes.tests/resources/itext/barcodes/cmp_barcodeQRCodeVersioning.pdf b/itext.tests/itext.barcodes.tests/resources/itext/barcodes/cmp_barcodeQRCodeVersioning.pdf new file mode 100644 index 0000000000..fec458ae47 Binary files /dev/null and b/itext.tests/itext.barcodes.tests/resources/itext/barcodes/cmp_barcodeQRCodeVersioning.pdf differ diff --git a/itext.tests/itext.forms.tests/Properties/AssemblyInfo.cs b/itext.tests/itext.forms.tests/Properties/AssemblyInfo.cs index 1069bec420..11ff3110d2 100644 --- a/itext.tests/itext.forms.tests/Properties/AssemblyInfo.cs +++ b/itext.tests/itext.forms.tests/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; [assembly: AssemblyTitle("iText.Forms.Tests")] @@ -15,5 +14,7 @@ [assembly: Guid("6fe2f714-6b3e-4b20-8c70-28bfce084ed2")] -[assembly: AssemblyVersion("7.0.0.0")] -[assembly: AssemblyFileVersion("7.0.0.0")] +[assembly: AssemblyVersion("7.0.1.0")] +[assembly: AssemblyFileVersion("7.0.1.0")] + +[assembly: NUnit.Framework.Timeout(300000)] diff --git a/itext.tests/itext.forms.tests/itext.forms.tests.csproj b/itext.tests/itext.forms.tests/itext.forms.tests.csproj index ddc1e909d8..60b5f498e2 100644 --- a/itext.tests/itext.forms.tests/itext.forms.tests.csproj +++ b/itext.tests/itext.forms.tests/itext.forms.tests.csproj @@ -36,7 +36,7 @@ - ..\..\packages\NUnit.3.2.1\lib\net40\nunit.framework.dll + $(SolutionDir)\packages\NUnit.3.2.1\lib\net40\nunit.framework.dll diff --git a/itext.tests/itext.forms.tests/itext/forms/FormFieldFlatteningTest.cs b/itext.tests/itext.forms.tests/itext/forms/FormFieldFlatteningTest.cs index 0048df9301..f5d0aa1de2 100644 --- a/itext.tests/itext.forms.tests/itext/forms/FormFieldFlatteningTest.cs +++ b/itext.tests/itext.forms.tests/itext/forms/FormFieldFlatteningTest.cs @@ -1,5 +1,5 @@ using System; -using System.IO; +using iText.Forms.Fields; using iText.Kernel.Pdf; using iText.Kernel.Utils; using iText.Test; @@ -22,8 +22,7 @@ public static void BeforeClass() { public virtual void FormFlatteningTest01() { String srcFilename = sourceFolder + "formFlatteningSource.pdf"; String filename = destinationFolder + "formFlatteningTest01.pdf"; - PdfDocument doc = new PdfDocument(new PdfReader(new FileStream(srcFilename, FileMode.Open, FileAccess.Read - )), new PdfWriter(new FileStream(filename, FileMode.Create))); + PdfDocument doc = new PdfDocument(new PdfReader(srcFilename), new PdfWriter(filename)); PdfAcroForm form = PdfAcroForm.GetAcroForm(doc, true); form.FlattenFields(); doc.Close(); @@ -34,5 +33,105 @@ public virtual void FormFlatteningTest01() { NUnit.Framework.Assert.Fail(errorMessage); } } + + /// + /// + [NUnit.Framework.Test] + public virtual void FormFlatteningTest_DefaultAppearanceGeneration_Rot0() { + String srcFilePattern = "FormFlatteningDefaultAppearance_0_"; + String destPattern = "FormFlatteningDefaultAppearance_0_"; + for (int i = 0; i < 360; i += 90) { + String src = sourceFolder + srcFilePattern + i + ".pdf"; + String dest = destinationFolder + destPattern + i + "_flattened.pdf"; + String cmp = sourceFolder + "cmp_" + srcFilePattern + i + ".pdf"; + PdfDocument doc = new PdfDocument(new PdfReader(src), new PdfWriter(dest)); + PdfAcroForm form = PdfAcroForm.GetAcroForm(doc, true); + foreach (PdfFormField field in form.GetFormFields().Values) { + field.SetValue("Test"); + } + form.FlattenFields(); + doc.Close(); + CompareTool compareTool = new CompareTool(); + String errorMessage = compareTool.CompareByContent(dest, cmp, destinationFolder, "diff_"); + if (errorMessage != null) { + NUnit.Framework.Assert.Fail(errorMessage); + } + } + } + + /// + /// + [NUnit.Framework.Test] + public virtual void FormFlatteningTest_DefaultAppearanceGeneration_Rot90() { + String srcFilePattern = "FormFlatteningDefaultAppearance_90_"; + String destPattern = "FormFlatteningDefaultAppearance_90_"; + for (int i = 0; i < 360; i += 90) { + String src = sourceFolder + srcFilePattern + i + ".pdf"; + String dest = destinationFolder + destPattern + i + "_flattened.pdf"; + String cmp = sourceFolder + "cmp_" + srcFilePattern + i + ".pdf"; + PdfDocument doc = new PdfDocument(new PdfReader(src), new PdfWriter(dest)); + PdfAcroForm form = PdfAcroForm.GetAcroForm(doc, true); + foreach (PdfFormField field in form.GetFormFields().Values) { + field.SetValue("Test"); + } + form.FlattenFields(); + doc.Close(); + CompareTool compareTool = new CompareTool(); + String errorMessage = compareTool.CompareByContent(dest, cmp, destinationFolder, "diff_"); + if (errorMessage != null) { + NUnit.Framework.Assert.Fail(errorMessage); + } + } + } + + /// + /// + [NUnit.Framework.Test] + public virtual void FormFlatteningTest_DefaultAppearanceGeneration_Rot180() { + String srcFilePattern = "FormFlatteningDefaultAppearance_180_"; + String destPattern = "FormFlatteningDefaultAppearance_180_"; + for (int i = 0; i < 360; i += 90) { + String src = sourceFolder + srcFilePattern + i + ".pdf"; + String dest = destinationFolder + destPattern + i + "_flattened.pdf"; + String cmp = sourceFolder + "cmp_" + srcFilePattern + i + ".pdf"; + PdfDocument doc = new PdfDocument(new PdfReader(src), new PdfWriter(dest)); + PdfAcroForm form = PdfAcroForm.GetAcroForm(doc, true); + foreach (PdfFormField field in form.GetFormFields().Values) { + field.SetValue("Test"); + } + form.FlattenFields(); + doc.Close(); + CompareTool compareTool = new CompareTool(); + String errorMessage = compareTool.CompareByContent(dest, cmp, destinationFolder, "diff_"); + if (errorMessage != null) { + NUnit.Framework.Assert.Fail(errorMessage); + } + } + } + + /// + /// + [NUnit.Framework.Test] + public virtual void FormFlatteningTest_DefaultAppearanceGeneration_Rot270() { + String srcFilePattern = "FormFlatteningDefaultAppearance_270_"; + String destPattern = "FormFlatteningDefaultAppearance_270_"; + for (int i = 0; i < 360; i += 90) { + String src = sourceFolder + srcFilePattern + i + ".pdf"; + String dest = destinationFolder + destPattern + i + "_flattened.pdf"; + String cmp = sourceFolder + "cmp_" + srcFilePattern + i + ".pdf"; + PdfDocument doc = new PdfDocument(new PdfReader(src), new PdfWriter(dest)); + PdfAcroForm form = PdfAcroForm.GetAcroForm(doc, true); + foreach (PdfFormField field in form.GetFormFields().Values) { + field.SetValue("Test"); + } + form.FlattenFields(); + doc.Close(); + CompareTool compareTool = new CompareTool(); + String errorMessage = compareTool.CompareByContent(dest, cmp, destinationFolder, "diff_"); + if (errorMessage != null) { + NUnit.Framework.Assert.Fail(errorMessage); + } + } + } } } diff --git a/itext.tests/itext.forms.tests/itext/forms/PdfEncryptionTest.cs b/itext.tests/itext.forms.tests/itext/forms/PdfEncryptionTest.cs index 50dcc13895..23d6536568 100644 --- a/itext.tests/itext.forms.tests/itext/forms/PdfEncryptionTest.cs +++ b/itext.tests/itext.forms.tests/itext/forms/PdfEncryptionTest.cs @@ -1,5 +1,4 @@ using System; -using System.IO; using iText.Kernel.Pdf; namespace iText.Forms { @@ -9,8 +8,8 @@ public class PdfEncryptionTest { /// [NUnit.Framework.Test] public virtual void EncryptedDocumentWithFormFields() { - PdfReader reader = new PdfReader(new FileStream(sourceFolder + "encryptedDocumentWithFormFields.pdf", FileMode.Open - , FileAccess.Read), new ReaderProperties().SetPassword("12345".GetBytes())); + PdfReader reader = new PdfReader(sourceFolder + "encryptedDocumentWithFormFields.pdf", new ReaderProperties + ().SetPassword("12345".GetBytes(iText.IO.Util.EncodingUtil.ISO_8859_1))); PdfDocument pdfDocument = new PdfDocument(reader); PdfAcroForm acroForm = PdfAcroForm.GetAcroForm(pdfDocument, false); acroForm.GetField("personal.name").GetPdfObject(); diff --git a/itext.tests/itext.forms.tests/itext/forms/PdfFormCopyTest.cs b/itext.tests/itext.forms.tests/itext/forms/PdfFormCopyTest.cs index 145dca5333..d0b660b7cc 100644 --- a/itext.tests/itext.forms.tests/itext/forms/PdfFormCopyTest.cs +++ b/itext.tests/itext.forms.tests/itext/forms/PdfFormCopyTest.cs @@ -1,5 +1,4 @@ using System; -using System.IO; using iText.IO; using iText.IO.Source; using iText.Kernel.Pdf; @@ -28,13 +27,10 @@ public virtual void CopyFieldsTest01() { String srcFilename2 = sourceFolder + "fieldsOn2-sPage.pdf"; String srcFilename3 = sourceFolder + "fieldsOn3-sPage.pdf"; String filename = destinationFolder + "copyFields01.pdf"; - PdfDocument doc1 = new PdfDocument(new PdfReader(new FileStream(srcFilename1, FileMode.Open, FileAccess.Read - ))); - PdfDocument doc2 = new PdfDocument(new PdfReader(new FileStream(srcFilename2, FileMode.Open, FileAccess.Read - ))); - PdfDocument doc3 = new PdfDocument(new PdfReader(new FileStream(srcFilename3, FileMode.Open, FileAccess.Read - ))); - PdfDocument pdfDoc = new PdfDocument(new PdfWriter(new FileStream(filename, FileMode.Create))); + PdfDocument doc1 = new PdfDocument(new PdfReader(srcFilename1)); + PdfDocument doc2 = new PdfDocument(new PdfReader(srcFilename2)); + PdfDocument doc3 = new PdfDocument(new PdfReader(srcFilename3)); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(filename)); pdfDoc.InitializeOutlines(); doc3.CopyPagesTo(1, doc3.GetNumberOfPages(), pdfDoc, new PdfPageFormCopier()); doc2.CopyPagesTo(1, doc2.GetNumberOfPages(), pdfDoc, new PdfPageFormCopier()); @@ -50,9 +46,8 @@ public virtual void CopyFieldsTest01() { public virtual void CopyFieldsTest02() { String srcFilename = sourceFolder + "hello_with_comments.pdf"; String filename = destinationFolder + "copyFields02.pdf"; - PdfDocument doc1 = new PdfDocument(new PdfReader(new FileStream(srcFilename, FileMode.Open, FileAccess.Read - ))); - PdfDocument pdfDoc = new PdfDocument(new PdfWriter(new FileStream(filename, FileMode.Create))); + PdfDocument doc1 = new PdfDocument(new PdfReader(srcFilename)); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(filename)); pdfDoc.InitializeOutlines(); doc1.CopyPagesTo(1, doc1.GetNumberOfPages(), pdfDoc, new PdfPageFormCopier()); pdfDoc.Close(); @@ -66,9 +61,8 @@ public virtual void CopyFieldsTest02() { public virtual void CopyFieldsTest03() { String srcFilename = sourceFolder + "hello2_with_comments.pdf"; String filename = destinationFolder + "copyFields03.pdf"; - PdfDocument doc1 = new PdfDocument(new PdfReader(new FileStream(srcFilename, FileMode.Open, FileAccess.Read - ))); - PdfDocument pdfDoc = new PdfDocument(new PdfWriter(new FileStream(filename, FileMode.Create))); + PdfDocument doc1 = new PdfDocument(new PdfReader(srcFilename)); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(filename)); pdfDoc.InitializeOutlines(); doc1.CopyPagesTo(1, doc1.GetNumberOfPages(), pdfDoc, new PdfPageFormCopier()); pdfDoc.Close(); @@ -85,14 +79,13 @@ public virtual void LargeFilePerformanceTest() { String srcFilename2 = sourceFolder + "largeFile.pdf"; String filename = destinationFolder + "copyLargeFile.pdf"; long timeStart = System.DateTime.Now.Ticks; - PdfDocument doc1 = new PdfDocument(new PdfReader(new FileStream(srcFilename1, FileMode.Open, FileAccess.Read - ))); - PdfDocument doc2 = new PdfDocument(new PdfReader(new FileStream(srcFilename2, FileMode.Open, FileAccess.Read - ))); - PdfDocument pdfDoc = new PdfDocument(new PdfWriter(new FileStream(filename, FileMode.Create))); + PdfDocument doc1 = new PdfDocument(new PdfReader(srcFilename1)); + PdfDocument doc2 = new PdfDocument(new PdfReader(srcFilename2)); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(filename)); pdfDoc.InitializeOutlines(); - doc1.CopyPagesTo(1, doc1.GetNumberOfPages(), pdfDoc, new PdfPageFormCopier()); - doc2.CopyPagesTo(1, doc2.GetNumberOfPages(), pdfDoc, new PdfPageFormCopier()); + PdfPageFormCopier formCopier = new PdfPageFormCopier(); + doc1.CopyPagesTo(1, doc1.GetNumberOfPages(), pdfDoc, formCopier); + doc2.CopyPagesTo(1, doc2.GetNumberOfPages(), pdfDoc, formCopier); pdfDoc.Close(); System.Console.Out.WriteLine(((System.DateTime.Now.Ticks - timeStart) / 1000 / 1000)); NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(filename, sourceFolder + "cmp_copyLargeFile.pdf" @@ -105,11 +98,11 @@ public virtual void LargeFilePerformanceTest() { [LogMessage(LogMessageConstant.DOCUMENT_ALREADY_HAS_FIELD)] public virtual void CopyFieldsTest04() { String srcFilename = sourceFolder + "srcFile1.pdf"; - PdfDocument srcDoc = new PdfDocument(new PdfReader(new FileStream(srcFilename, FileMode.Open, FileAccess.Read - ))); + PdfDocument srcDoc = new PdfDocument(new PdfReader(srcFilename)); PdfDocument destDoc = new PdfDocument(new PdfWriter(new ByteArrayOutputStream())); - srcDoc.CopyPagesTo(1, srcDoc.GetNumberOfPages(), destDoc, new PdfPageFormCopier()); - srcDoc.CopyPagesTo(1, srcDoc.GetNumberOfPages(), destDoc, new PdfPageFormCopier()); + PdfPageFormCopier formCopier = new PdfPageFormCopier(); + srcDoc.CopyPagesTo(1, srcDoc.GetNumberOfPages(), destDoc, formCopier); + srcDoc.CopyPagesTo(1, srcDoc.GetNumberOfPages(), destDoc, formCopier); PdfAcroForm form = PdfAcroForm.GetAcroForm(destDoc, false); NUnit.Framework.Assert.AreEqual(1, form.GetFields().Size()); NUnit.Framework.Assert.IsNotNull(form.GetField("Name1")); @@ -123,25 +116,86 @@ public virtual void CopyFieldsTest04() { public virtual void CopyFieldsTest05() { String srcFilename = sourceFolder + "srcFile1.pdf"; String destFilename = destinationFolder + "copyFields05.pdf"; - PdfDocument srcDoc = new PdfDocument(new PdfReader(new FileStream(srcFilename, FileMode.Open, FileAccess.Read - ))); - PdfDocument destDoc = new PdfDocument(new PdfWriter(new FileStream(destFilename, FileMode.Create))); + PdfDocument srcDoc = new PdfDocument(new PdfReader(srcFilename)); + PdfDocument destDoc = new PdfDocument(new PdfWriter(destFilename)); destDoc.AddPage(srcDoc.GetFirstPage().CopyTo(destDoc, new PdfPageFormCopier())); destDoc.Close(); NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(destFilename, sourceFolder + "cmp_copyFields05.pdf" , destinationFolder, "diff_")); } + /// + /// + [NUnit.Framework.Test] + [LogMessage(LogMessageConstant.DOCUMENT_ALREADY_HAS_FIELD, Count = 13)] + public virtual void CopyFieldsTest06() { + String srcFilename = sourceFolder + "datasheet.pdf"; + String destFilename = destinationFolder + "copyFields06.pdf"; + PdfDocument srcDoc = new PdfDocument(new PdfReader(srcFilename)); + PdfDocument destDoc = new PdfDocument(new PdfWriter(destFilename)); + PdfPageFormCopier pdfPageFormCopier = new PdfPageFormCopier(); + // copying the same page from the same document twice + for (int i = 0; i < 2; ++i) { + srcDoc.CopyPagesTo(1, 1, destDoc, pdfPageFormCopier); + } + destDoc.Close(); + srcDoc.Close(); + NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(destFilename, sourceFolder + "cmp_copyFields06.pdf" + , destinationFolder, "diff_")); + } + + /// + /// + [NUnit.Framework.Test] + [LogMessage(LogMessageConstant.DOCUMENT_ALREADY_HAS_FIELD, Count = 13)] + public virtual void CopyFieldsTest07() { + String srcFilename = sourceFolder + "datasheet.pdf"; + String destFilename = destinationFolder + "copyFields07.pdf"; + PdfDocument destDoc = new PdfDocument(new PdfWriter(destFilename)); + PdfPageFormCopier pdfPageFormCopier = new PdfPageFormCopier(); + // copying the same page from reopened document twice + for (int i = 0; i < 2; ++i) { + PdfDocument srcDoc = new PdfDocument(new PdfReader(srcFilename)); + srcDoc.CopyPagesTo(1, 1, destDoc, pdfPageFormCopier); + srcDoc.Close(); + } + destDoc.Close(); + NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(destFilename, sourceFolder + "cmp_copyFields07.pdf" + , destinationFolder, "diff_")); + } + + /// + /// + [NUnit.Framework.Test] + [LogMessage(LogMessageConstant.DOCUMENT_ALREADY_HAS_FIELD, Count = 13)] + public virtual void CopyFieldsTest08() { + String srcFilename1 = sourceFolder + "appearances1.pdf"; + String srcFilename2 = sourceFolder + "fieldsOn2-sPage.pdf"; + String srcFilename3 = sourceFolder + "fieldsOn3-sPage.pdf"; + String filename = destinationFolder + "copyFields08.pdf"; + PdfDocument doc1 = new PdfDocument(new PdfReader(srcFilename1)); + PdfDocument doc2 = new PdfDocument(new PdfReader(srcFilename2)); + PdfDocument doc3 = new PdfDocument(new PdfReader(srcFilename3)); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(filename)); + pdfDoc.InitializeOutlines(); + PdfPageFormCopier formCopier = new PdfPageFormCopier(); + doc3.CopyPagesTo(1, doc3.GetNumberOfPages(), pdfDoc, formCopier); + doc2.CopyPagesTo(1, doc2.GetNumberOfPages(), pdfDoc, formCopier); + doc1.CopyPagesTo(1, doc1.GetNumberOfPages(), pdfDoc, formCopier); + pdfDoc.Close(); + // comparing with cmp_copyFields01.pdf on purpose: result should be the same as in the first test + NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(filename, sourceFolder + "cmp_copyFields01.pdf" + , destinationFolder, "diff_")); + } + /// /// [NUnit.Framework.Test] public virtual void CopyPagesWithInheritedResources() { String sourceFile = sourceFolder + "AnnotationSampleStandard.pdf"; String destFile = destinationFolder + "AnnotationSampleStandard_copy.pdf"; - PdfReader reader = new PdfReader(new FileStream(sourceFile, FileMode.Open, FileAccess.Read)); - PdfWriter writer = new PdfWriter(destFile); - PdfDocument source = new PdfDocument(reader); - PdfDocument target = new PdfDocument(writer); + PdfDocument source = new PdfDocument(new PdfReader(sourceFile)); + PdfDocument target = new PdfDocument(new PdfWriter(destFile)); target.InitializeOutlines(); source.CopyPagesTo(1, source.GetNumberOfPages(), target, new PdfPageFormCopier()); target.Close(); diff --git a/itext.tests/itext.forms.tests/itext/forms/PdfFormFieldTest.cs b/itext.tests/itext.forms.tests/itext/forms/PdfFormFieldTest.cs index e2fd200754..c158dc88bc 100644 --- a/itext.tests/itext.forms.tests/itext/forms/PdfFormFieldTest.cs +++ b/itext.tests/itext.forms.tests/itext/forms/PdfFormFieldTest.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -using System.IO; using iText.Forms.Fields; +using iText.IO.Source; using iText.Kernel.Geom; using iText.Kernel.Pdf; using iText.Kernel.Utils; @@ -22,8 +22,7 @@ public static void BeforeClass() { /// [NUnit.Framework.Test] public virtual void FormFieldTest01() { - PdfReader reader = new PdfReader(sourceFolder + "formFieldFile.pdf"); - PdfDocument pdfDoc = new PdfDocument(reader); + PdfDocument pdfDoc = new PdfDocument(new PdfReader(sourceFolder + "formFieldFile.pdf")); PdfAcroForm form = PdfAcroForm.GetAcroForm(pdfDoc, false); IDictionary fields = form.GetFormFields(); PdfFormField field = fields.Get("Text1"); @@ -37,8 +36,7 @@ public virtual void FormFieldTest01() { [NUnit.Framework.Test] public virtual void FormFieldTest02() { String filename = destinationFolder + "formFieldTest02.pdf"; - PdfWriter writer = new PdfWriter(new FileStream(filename, FileMode.Create)); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(filename)); PdfAcroForm form = PdfAcroForm.GetAcroForm(pdfDoc, true); Rectangle rect = new Rectangle(210, 490, 150, 22); PdfTextFormField field = PdfFormField.CreateText(pdfDoc, rect, "fieldName", "some value"); @@ -56,10 +54,9 @@ public virtual void FormFieldTest02() { /// [NUnit.Framework.Test] public virtual void FormFieldTest03() { - PdfReader reader = new PdfReader(sourceFolder + "formFieldFile.pdf"); String filename = destinationFolder + "formFieldTest03.pdf"; - PdfWriter writer = new PdfWriter(new FileStream(filename, FileMode.Create)); - PdfDocument pdfDoc = new PdfDocument(reader, writer); + PdfDocument pdfDoc = new PdfDocument(new PdfReader(sourceFolder + "formFieldFile.pdf"), new PdfWriter(filename + )); PdfAcroForm form = PdfAcroForm.GetAcroForm(pdfDoc, true); PdfPage page = pdfDoc.GetFirstPage(); Rectangle rect = new Rectangle(210, 490, 150, 22); @@ -79,8 +76,7 @@ public virtual void FormFieldTest03() { [NUnit.Framework.Test] public virtual void ChoiceFieldTest01() { String filename = destinationFolder + "choiceFieldTest01.pdf"; - PdfWriter writer = new PdfWriter(new FileStream(filename, FileMode.Create)); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(filename)); PdfAcroForm form = PdfAcroForm.GetAcroForm(pdfDoc, true); Rectangle rect = new Rectangle(210, 490, 150, 20); String[] options = new String[] { "First Item", "Second Item", "Third Item", "Fourth Item" }; @@ -104,8 +100,7 @@ public virtual void ChoiceFieldTest01() { [NUnit.Framework.Test] public virtual void ButtonFieldTest01() { String filename = destinationFolder + "buttonFieldTest01.pdf"; - PdfWriter writer = new PdfWriter(new FileStream(filename, FileMode.Create)); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(filename)); PdfAcroForm form = PdfAcroForm.GetAcroForm(pdfDoc, true); Rectangle rect = new Rectangle(36, 700, 20, 20); Rectangle rect1 = new Rectangle(36, 680, 20, 20); @@ -134,7 +129,7 @@ public virtual void ButtonFieldTest01() { public virtual void ButtonFieldTest02() { String filename = destinationFolder + "buttonFieldTest02.pdf"; PdfDocument pdfDoc = new PdfDocument(new PdfReader(sourceFolder + "buttonFieldTest02_input.pdf"), new PdfWriter - (new FileStream(filename, FileMode.Create))); + (filename)); PdfAcroForm form = PdfAcroForm.GetAcroForm(pdfDoc, true); ((PdfButtonFormField)form.GetField("push")).SetImage(sourceFolder + "Desert.jpg"); pdfDoc.Close(); @@ -145,5 +140,39 @@ public virtual void ButtonFieldTest02() { NUnit.Framework.Assert.Fail(errorMessage); } } + + /// + /// + [NUnit.Framework.Test] + public virtual void RealFontSizeRegenerateAppearanceTest() { + String sourceFilename = sourceFolder + "defaultAppearanceRealFontSize.pdf"; + String destFilename = destinationFolder + "realFontSizeRegenerateAppearance.pdf"; + PdfDocument pdfDoc = new PdfDocument(new PdfReader(sourceFilename), new PdfWriter(destFilename)); + PdfAcroForm form = PdfAcroForm.GetAcroForm(pdfDoc, true); + form.GetField("fieldName").RegenerateField(); + pdfDoc.Close(); + CompareTool compareTool = new CompareTool(); + String errorMessage = compareTool.CompareByContent(destFilename, sourceFolder + "cmp_realFontSizeRegenerateAppearance.pdf" + , destinationFolder, "diff_"); + if (errorMessage != null) { + NUnit.Framework.Assert.Fail(errorMessage); + } + } + + [NUnit.Framework.Test] + public virtual void AddFieldWithKidsTest() { + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(new ByteArrayOutputStream())); + PdfAcroForm form = PdfAcroForm.GetAcroForm(pdfDoc, true); + PdfFormField root = PdfFormField.CreateEmptyField(pdfDoc); + root.SetFieldName("root"); + PdfFormField child = PdfFormField.CreateEmptyField(pdfDoc); + child.SetFieldName("child"); + root.AddKid(child); + PdfTextFormField text1 = PdfFormField.CreateText(pdfDoc, new Rectangle(100, 700, 200, 20), "text1", "test" + ); + child.AddKid(text1); + form.AddField(root); + NUnit.Framework.Assert.AreEqual(3, form.GetFormFields().Count); + } } } diff --git a/itext.tests/itext.forms.tests/itext/forms/xfa/XFAFormTest.cs b/itext.tests/itext.forms.tests/itext/forms/xfa/XFAFormTest.cs index 19cb050a5b..0f4fec3178 100644 --- a/itext.tests/itext.forms.tests/itext/forms/xfa/XFAFormTest.cs +++ b/itext.tests/itext.forms.tests/itext/forms/xfa/XFAFormTest.cs @@ -24,7 +24,7 @@ public static void BeforeClass() { public virtual void CreateEmptyXFAFormTest01() { String outFileName = destinationFolder + "createEmptyXFAFormTest01.pdf"; String cmpFileName = sourceFolder + "cmp_createEmptyXFAFormTest01.pdf"; - PdfDocument doc = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument doc = new PdfDocument(new PdfWriter(outFileName)); XfaForm xfa = new XfaForm(doc); XfaForm.SetXfaForm(xfa, doc); doc.AddNewPage(); @@ -39,7 +39,7 @@ public virtual void CreateEmptyXFAFormTest01() { public virtual void CreateEmptyXFAFormTest02() { String outFileName = destinationFolder + "createEmptyXFAFormTest02.pdf"; String cmpFileName = sourceFolder + "cmp_createEmptyXFAFormTest02.pdf"; - PdfDocument doc = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument doc = new PdfDocument(new PdfWriter(outFileName)); XfaForm xfa = new XfaForm(); XfaForm.SetXfaForm(xfa, doc); doc.AddNewPage(); @@ -54,7 +54,7 @@ public virtual void CreateEmptyXFAFormTest02() { public virtual void CreateXFAFormTest() { String outFileName = destinationFolder + "createXFAFormTest.pdf"; String cmpFileName = sourceFolder + "cmp_createXFAFormTest.pdf"; - PdfDocument doc = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument doc = new PdfDocument(new PdfWriter(outFileName)); XfaForm xfa = new XfaForm(new FileStream(XML, FileMode.Open, FileAccess.Read)); xfa.Write(doc); doc.AddNewPage(); diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/FormFlatteningDefaultAppearance_0_0.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/FormFlatteningDefaultAppearance_0_0.pdf new file mode 100644 index 0000000000..5fc89de51f Binary files /dev/null and b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/FormFlatteningDefaultAppearance_0_0.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/FormFlatteningDefaultAppearance_0_180.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/FormFlatteningDefaultAppearance_0_180.pdf new file mode 100644 index 0000000000..4bcad7ab52 Binary files /dev/null and b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/FormFlatteningDefaultAppearance_0_180.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/FormFlatteningDefaultAppearance_0_270.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/FormFlatteningDefaultAppearance_0_270.pdf new file mode 100644 index 0000000000..164bc48313 Binary files /dev/null and b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/FormFlatteningDefaultAppearance_0_270.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/FormFlatteningDefaultAppearance_0_90.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/FormFlatteningDefaultAppearance_0_90.pdf new file mode 100644 index 0000000000..e4e0c9f313 Binary files /dev/null and b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/FormFlatteningDefaultAppearance_0_90.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/FormFlatteningDefaultAppearance_180_0.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/FormFlatteningDefaultAppearance_180_0.pdf new file mode 100644 index 0000000000..a4a3a532d3 Binary files /dev/null and b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/FormFlatteningDefaultAppearance_180_0.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/FormFlatteningDefaultAppearance_180_180.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/FormFlatteningDefaultAppearance_180_180.pdf new file mode 100644 index 0000000000..418b0fa46d Binary files /dev/null and b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/FormFlatteningDefaultAppearance_180_180.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/FormFlatteningDefaultAppearance_180_270.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/FormFlatteningDefaultAppearance_180_270.pdf new file mode 100644 index 0000000000..2a6b5fba51 Binary files /dev/null and b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/FormFlatteningDefaultAppearance_180_270.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/FormFlatteningDefaultAppearance_180_90.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/FormFlatteningDefaultAppearance_180_90.pdf new file mode 100644 index 0000000000..52a7a503b8 Binary files /dev/null and b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/FormFlatteningDefaultAppearance_180_90.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/FormFlatteningDefaultAppearance_270_0.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/FormFlatteningDefaultAppearance_270_0.pdf new file mode 100644 index 0000000000..b7e109da87 Binary files /dev/null and b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/FormFlatteningDefaultAppearance_270_0.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/FormFlatteningDefaultAppearance_270_180.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/FormFlatteningDefaultAppearance_270_180.pdf new file mode 100644 index 0000000000..a0ce7d5326 Binary files /dev/null and b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/FormFlatteningDefaultAppearance_270_180.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/FormFlatteningDefaultAppearance_270_270.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/FormFlatteningDefaultAppearance_270_270.pdf new file mode 100644 index 0000000000..938c5d6b5e Binary files /dev/null and b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/FormFlatteningDefaultAppearance_270_270.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/FormFlatteningDefaultAppearance_270_90.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/FormFlatteningDefaultAppearance_270_90.pdf new file mode 100644 index 0000000000..91037f9167 Binary files /dev/null and b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/FormFlatteningDefaultAppearance_270_90.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/FormFlatteningDefaultAppearance_90_0.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/FormFlatteningDefaultAppearance_90_0.pdf new file mode 100644 index 0000000000..dbce27ec1a Binary files /dev/null and b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/FormFlatteningDefaultAppearance_90_0.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/FormFlatteningDefaultAppearance_90_180.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/FormFlatteningDefaultAppearance_90_180.pdf new file mode 100644 index 0000000000..83f4d536e0 Binary files /dev/null and b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/FormFlatteningDefaultAppearance_90_180.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/FormFlatteningDefaultAppearance_90_270.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/FormFlatteningDefaultAppearance_90_270.pdf new file mode 100644 index 0000000000..012cda6706 Binary files /dev/null and b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/FormFlatteningDefaultAppearance_90_270.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/FormFlatteningDefaultAppearance_90_90.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/FormFlatteningDefaultAppearance_90_90.pdf new file mode 100644 index 0000000000..abe863be3e Binary files /dev/null and b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/FormFlatteningDefaultAppearance_90_90.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_FormFlatteningDefaultAppearance_0_0.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_FormFlatteningDefaultAppearance_0_0.pdf new file mode 100644 index 0000000000..e2e37c2a26 Binary files /dev/null and b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_FormFlatteningDefaultAppearance_0_0.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_FormFlatteningDefaultAppearance_0_180.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_FormFlatteningDefaultAppearance_0_180.pdf new file mode 100644 index 0000000000..9cdc136ae6 Binary files /dev/null and b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_FormFlatteningDefaultAppearance_0_180.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_FormFlatteningDefaultAppearance_0_270.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_FormFlatteningDefaultAppearance_0_270.pdf new file mode 100644 index 0000000000..625fb500b6 Binary files /dev/null and b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_FormFlatteningDefaultAppearance_0_270.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_FormFlatteningDefaultAppearance_0_90.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_FormFlatteningDefaultAppearance_0_90.pdf new file mode 100644 index 0000000000..11c682435a Binary files /dev/null and b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_FormFlatteningDefaultAppearance_0_90.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_FormFlatteningDefaultAppearance_180_0.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_FormFlatteningDefaultAppearance_180_0.pdf new file mode 100644 index 0000000000..ab3649e505 Binary files /dev/null and b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_FormFlatteningDefaultAppearance_180_0.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_FormFlatteningDefaultAppearance_180_180.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_FormFlatteningDefaultAppearance_180_180.pdf new file mode 100644 index 0000000000..fe7f907f31 Binary files /dev/null and b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_FormFlatteningDefaultAppearance_180_180.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_FormFlatteningDefaultAppearance_180_270.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_FormFlatteningDefaultAppearance_180_270.pdf new file mode 100644 index 0000000000..65a6940c84 Binary files /dev/null and b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_FormFlatteningDefaultAppearance_180_270.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_FormFlatteningDefaultAppearance_180_90.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_FormFlatteningDefaultAppearance_180_90.pdf new file mode 100644 index 0000000000..92e912c187 Binary files /dev/null and b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_FormFlatteningDefaultAppearance_180_90.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_FormFlatteningDefaultAppearance_270_0.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_FormFlatteningDefaultAppearance_270_0.pdf new file mode 100644 index 0000000000..2fb0a882bb Binary files /dev/null and b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_FormFlatteningDefaultAppearance_270_0.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_FormFlatteningDefaultAppearance_270_180.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_FormFlatteningDefaultAppearance_270_180.pdf new file mode 100644 index 0000000000..8286d5d9ef Binary files /dev/null and b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_FormFlatteningDefaultAppearance_270_180.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_FormFlatteningDefaultAppearance_270_270.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_FormFlatteningDefaultAppearance_270_270.pdf new file mode 100644 index 0000000000..a112bde12d Binary files /dev/null and b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_FormFlatteningDefaultAppearance_270_270.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_FormFlatteningDefaultAppearance_270_90.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_FormFlatteningDefaultAppearance_270_90.pdf new file mode 100644 index 0000000000..f9ad4d81e8 Binary files /dev/null and b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_FormFlatteningDefaultAppearance_270_90.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_FormFlatteningDefaultAppearance_90_0.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_FormFlatteningDefaultAppearance_90_0.pdf new file mode 100644 index 0000000000..2033758bd8 Binary files /dev/null and b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_FormFlatteningDefaultAppearance_90_0.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_FormFlatteningDefaultAppearance_90_180.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_FormFlatteningDefaultAppearance_90_180.pdf new file mode 100644 index 0000000000..2f132a4654 Binary files /dev/null and b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_FormFlatteningDefaultAppearance_90_180.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_FormFlatteningDefaultAppearance_90_270.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_FormFlatteningDefaultAppearance_90_270.pdf new file mode 100644 index 0000000000..8949643821 Binary files /dev/null and b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_FormFlatteningDefaultAppearance_90_270.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_FormFlatteningDefaultAppearance_90_90.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_FormFlatteningDefaultAppearance_90_90.pdf new file mode 100644 index 0000000000..b7ae34e21f Binary files /dev/null and b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_FormFlatteningDefaultAppearance_90_90.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_formFlatteningTest01.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_formFlatteningTest01.pdf index 47e06a4317..7a91f2a916 100644 Binary files a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_formFlatteningTest01.pdf and b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldFlatteningTest/cmp_formFlatteningTest01.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldsTaggingTest/cmp_taggedPdfWithForms01.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldsTaggingTest/cmp_taggedPdfWithForms01.pdf index cdbb5c1e45..e5a0ad10e9 100644 Binary files a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldsTaggingTest/cmp_taggedPdfWithForms01.pdf and b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldsTaggingTest/cmp_taggedPdfWithForms01.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldsTaggingTest/cmp_taggedPdfWithForms02.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldsTaggingTest/cmp_taggedPdfWithForms02.pdf index 85c9d4cb45..c674e30533 100644 Binary files a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldsTaggingTest/cmp_taggedPdfWithForms02.pdf and b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldsTaggingTest/cmp_taggedPdfWithForms02.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldsTaggingTest/cmp_taggedPdfWithForms03.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldsTaggingTest/cmp_taggedPdfWithForms03.pdf index 9d7624b171..11e2190a30 100644 Binary files a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldsTaggingTest/cmp_taggedPdfWithForms03.pdf and b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldsTaggingTest/cmp_taggedPdfWithForms03.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldsTaggingTest/cmp_taggedPdfWithForms04.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldsTaggingTest/cmp_taggedPdfWithForms04.pdf index b8d902fdd5..0cf9e00f58 100644 Binary files a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldsTaggingTest/cmp_taggedPdfWithForms04.pdf and b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldsTaggingTest/cmp_taggedPdfWithForms04.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldsTaggingTest/cmp_taggedPdfWithForms05.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldsTaggingTest/cmp_taggedPdfWithForms05.pdf index 9821fa72cf..9d52c79528 100644 Binary files a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldsTaggingTest/cmp_taggedPdfWithForms05.pdf and b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldsTaggingTest/cmp_taggedPdfWithForms05.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldsTaggingTest/cmp_taggedPdfWithForms06.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldsTaggingTest/cmp_taggedPdfWithForms06.pdf index 3611653ec9..c632f5c067 100644 Binary files a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldsTaggingTest/cmp_taggedPdfWithForms06.pdf and b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldsTaggingTest/cmp_taggedPdfWithForms06.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldsTaggingTest/cmp_taggedPdfWithForms07.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldsTaggingTest/cmp_taggedPdfWithForms07.pdf index 8b69b76db5..58bc42e0de 100644 Binary files a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldsTaggingTest/cmp_taggedPdfWithForms07.pdf and b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldsTaggingTest/cmp_taggedPdfWithForms07.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldsTaggingTest/taggedDocWithFields.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldsTaggingTest/taggedDocWithFields.pdf index 46edc66e98..5d5ab01578 100644 Binary files a/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldsTaggingTest/taggedDocWithFields.pdf and b/itext.tests/itext.forms.tests/resources/itext/forms/FormFieldsTaggingTest/taggedDocWithFields.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldTest/cmp_buttonFieldTest01.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldTest/cmp_buttonFieldTest01.pdf index ed1d2e8685..eb442fa1ee 100644 Binary files a/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldTest/cmp_buttonFieldTest01.pdf and b/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldTest/cmp_buttonFieldTest01.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldTest/cmp_buttonFieldTest02.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldTest/cmp_buttonFieldTest02.pdf index 21de1b9eae..955a3f33a0 100644 Binary files a/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldTest/cmp_buttonFieldTest02.pdf and b/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldTest/cmp_buttonFieldTest02.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldTest/cmp_choiceFieldTest01.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldTest/cmp_choiceFieldTest01.pdf index 0391106b55..843d5f9a40 100644 Binary files a/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldTest/cmp_choiceFieldTest01.pdf and b/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldTest/cmp_choiceFieldTest01.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldTest/cmp_formFieldTest02.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldTest/cmp_formFieldTest02.pdf index 2d70106fed..56aa9ee31b 100644 Binary files a/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldTest/cmp_formFieldTest02.pdf and b/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldTest/cmp_formFieldTest02.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldTest/cmp_formFieldTest03.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldTest/cmp_formFieldTest03.pdf index 2d90496b57..1540d76596 100644 Binary files a/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldTest/cmp_formFieldTest03.pdf and b/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldTest/cmp_formFieldTest03.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldTest/cmp_realFontSizeRegenerateAppearance.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldTest/cmp_realFontSizeRegenerateAppearance.pdf new file mode 100644 index 0000000000..14e25d7fba Binary files /dev/null and b/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldTest/cmp_realFontSizeRegenerateAppearance.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldTest/defaultAppearanceRealFontSize.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldTest/defaultAppearanceRealFontSize.pdf new file mode 100644 index 0000000000..35af94fc9c Binary files /dev/null and b/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldTest/defaultAppearanceRealFontSize.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldsCopyTest/cmp_copyFields01.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldsCopyTest/cmp_copyFields01.pdf index 72c89d2a92..00fddcb572 100644 Binary files a/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldsCopyTest/cmp_copyFields01.pdf and b/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldsCopyTest/cmp_copyFields01.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldsCopyTest/cmp_copyFields02.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldsCopyTest/cmp_copyFields02.pdf index 62c7414ab7..fcf022f7d8 100644 Binary files a/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldsCopyTest/cmp_copyFields02.pdf and b/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldsCopyTest/cmp_copyFields02.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldsCopyTest/cmp_copyFields03.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldsCopyTest/cmp_copyFields03.pdf index 9e1bfa8dc0..a8d3a3b4e1 100644 Binary files a/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldsCopyTest/cmp_copyFields03.pdf and b/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldsCopyTest/cmp_copyFields03.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldsCopyTest/cmp_copyFields05.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldsCopyTest/cmp_copyFields05.pdf index f70544d328..f4fcd20964 100644 Binary files a/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldsCopyTest/cmp_copyFields05.pdf and b/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldsCopyTest/cmp_copyFields05.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldsCopyTest/cmp_copyFields06.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldsCopyTest/cmp_copyFields06.pdf new file mode 100644 index 0000000000..8476083b69 Binary files /dev/null and b/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldsCopyTest/cmp_copyFields06.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldsCopyTest/cmp_copyFields07.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldsCopyTest/cmp_copyFields07.pdf new file mode 100644 index 0000000000..34614f981d Binary files /dev/null and b/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldsCopyTest/cmp_copyFields07.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldsCopyTest/cmp_copyLargeFile.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldsCopyTest/cmp_copyLargeFile.pdf index e921c9c25e..afce0af3b9 100644 Binary files a/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldsCopyTest/cmp_copyLargeFile.pdf and b/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldsCopyTest/cmp_copyLargeFile.pdf differ diff --git a/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldsCopyTest/datasheet.pdf b/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldsCopyTest/datasheet.pdf new file mode 100644 index 0000000000..479bb64bff Binary files /dev/null and b/itext.tests/itext.forms.tests/resources/itext/forms/PdfFormFieldsCopyTest/datasheet.pdf differ diff --git a/itext.tests/itext.io.tests/Properties/AssemblyInfo.cs b/itext.tests/itext.io.tests/Properties/AssemblyInfo.cs index 7dbaf021a7..f9018cd9eb 100644 --- a/itext.tests/itext.io.tests/Properties/AssemblyInfo.cs +++ b/itext.tests/itext.io.tests/Properties/AssemblyInfo.cs @@ -15,5 +15,7 @@ [assembly: Guid("a53a5dd3-787b-4563-8778-1d76bdad57ba")] -[assembly: AssemblyVersion("7.0.0.0")] -[assembly: AssemblyFileVersion("7.0.0.0")] +[assembly: AssemblyVersion("7.0.1.0")] +[assembly: AssemblyFileVersion("7.0.1.0")] + +[assembly: NUnit.Framework.Timeout(300000)] diff --git a/itext.tests/itext.io.tests/itext.io.tests.csproj b/itext.tests/itext.io.tests/itext.io.tests.csproj index dadec19840..80e494d231 100644 --- a/itext.tests/itext.io.tests/itext.io.tests.csproj +++ b/itext.tests/itext.io.tests/itext.io.tests.csproj @@ -35,7 +35,7 @@ - ..\..\packages\NUnit.3.2.1\lib\net40\nunit.framework.dll + $(SolutionDir)\packages\NUnit.3.2.1\lib\net40\nunit.framework.dll diff --git a/itext.tests/itext.io.tests/itext/io/font/FontProgramTest.cs b/itext.tests/itext.io.tests/itext/io/font/FontProgramTest.cs index 60847cbe9c..e403d6cfac 100644 --- a/itext.tests/itext.io.tests/itext/io/font/FontProgramTest.cs +++ b/itext.tests/itext.io.tests/itext/io/font/FontProgramTest.cs @@ -1,13 +1,16 @@ +using System; + namespace iText.IO.Font { public class FontProgramTest { /// [NUnit.Framework.Test] public virtual void ExceptionMessageTest() { + String font = "some-font.ttf"; try { - FontProgramFactory.CreateFont("some-font.ttf"); + FontProgramFactory.CreateFont(font); } catch (iText.IO.IOException ex) { - NUnit.Framework.Assert.AreEqual("font.file some-font.ttf not.found", ex.Message); + NUnit.Framework.Assert.AreEqual(String.Format(iText.IO.IOException.FontFile1NotFound, font), ex.Message); } } diff --git a/itext.tests/itext.io.tests/itext/io/source/WriteNumbersTest.cs b/itext.tests/itext.io.tests/itext/io/source/WriteNumbersTest.cs index a27907f9ba..1fd5109bf5 100644 --- a/itext.tests/itext.io.tests/itext/io/source/WriteNumbersTest.cs +++ b/itext.tests/itext.io.tests/itext/io/source/WriteNumbersTest.cs @@ -18,7 +18,8 @@ public virtual void WriteNumber1Test() { continue; } byte[] actuals = ByteUtils.GetIsoBytes(d); - byte[] expecteds = DecimalFormatUtil.FormatNumber(d, "0.##").GetBytes(); + byte[] expecteds = DecimalFormatUtil.FormatNumber(d, "0.##").GetBytes(iText.IO.Util.EncodingUtil.ISO_8859_1 + ); String message = "Expects: " + iText.IO.Util.JavaUtil.GetStringForBytes(expecteds) + ", actual: " + iText.IO.Util.JavaUtil.GetStringForBytes (actuals) + " \\\\ " + d; NUnit.Framework.Assert.AreEqual(expecteds, actuals, message); @@ -35,7 +36,8 @@ public virtual void WriteNumber2Test() { continue; } byte[] actuals = ByteUtils.GetIsoBytes(d); - byte[] expecteds = DecimalFormatUtil.FormatNumber(d, "0.#####").GetBytes(); + byte[] expecteds = DecimalFormatUtil.FormatNumber(d, "0.#####").GetBytes(iText.IO.Util.EncodingUtil.ISO_8859_1 + ); String message = "Expects: " + iText.IO.Util.JavaUtil.GetStringForBytes(expecteds) + ", actual: " + iText.IO.Util.JavaUtil.GetStringForBytes (actuals) + " \\\\ " + d; NUnit.Framework.Assert.AreEqual(expecteds, actuals, message); @@ -52,7 +54,7 @@ public virtual void WriteNumber3Test() { } d = Round(d, 0); byte[] actuals = ByteUtils.GetIsoBytes(d); - byte[] expecteds = DecimalFormatUtil.FormatNumber(d, "0").GetBytes(); + byte[] expecteds = DecimalFormatUtil.FormatNumber(d, "0").GetBytes(iText.IO.Util.EncodingUtil.ISO_8859_1); String message = "Expects: " + iText.IO.Util.JavaUtil.GetStringForBytes(expecteds) + ", actual: " + iText.IO.Util.JavaUtil.GetStringForBytes (actuals) + " \\\\ " + d; NUnit.Framework.Assert.AreEqual(expecteds, actuals, message); diff --git a/itext.tests/itext.io.tests/itext/io/source/WriteStringsTest.cs b/itext.tests/itext.io.tests/itext/io/source/WriteStringsTest.cs index 058fbdf2bf..5c9e155e5c 100644 --- a/itext.tests/itext.io.tests/itext/io/source/WriteStringsTest.cs +++ b/itext.tests/itext.io.tests/itext/io/source/WriteStringsTest.cs @@ -6,21 +6,22 @@ public class WriteStringsTest { public virtual void WriteStringTest() { String str = "SomeString"; byte[] content = ByteUtils.GetIsoBytes(str); - NUnit.Framework.Assert.AreEqual(str.GetBytes(), content); + NUnit.Framework.Assert.AreEqual(str.GetBytes(iText.IO.Util.EncodingUtil.ISO_8859_1), content); } [NUnit.Framework.Test] public virtual void WriteNameTest() { String str = "SomeName"; byte[] content = ByteUtils.GetIsoBytes((byte)'/', str); - NUnit.Framework.Assert.AreEqual(("/" + str).GetBytes(), content); + NUnit.Framework.Assert.AreEqual(("/" + str).GetBytes(iText.IO.Util.EncodingUtil.ISO_8859_1), content); } [NUnit.Framework.Test] public virtual void WritePdfStringTest() { String str = "Some PdfString"; byte[] content = ByteUtils.GetIsoBytes((byte)'(', str, (byte)')'); - NUnit.Framework.Assert.AreEqual(("(" + str + ")").GetBytes(), content); + NUnit.Framework.Assert.AreEqual(("(" + str + ")").GetBytes(iText.IO.Util.EncodingUtil.ISO_8859_1), content + ); } } } diff --git a/itext.tests/itext.kernel.tests/Properties/AssemblyInfo.cs b/itext.tests/itext.kernel.tests/Properties/AssemblyInfo.cs index feca696c86..ff3268b635 100644 --- a/itext.tests/itext.kernel.tests/Properties/AssemblyInfo.cs +++ b/itext.tests/itext.kernel.tests/Properties/AssemblyInfo.cs @@ -15,5 +15,7 @@ [assembly: Guid("02e54061-eb72-409d-b2c0-307ce66b57e9")] -[assembly: AssemblyVersion("7.0.0.0")] -[assembly: AssemblyFileVersion("7.0.0.0")] +[assembly: AssemblyVersion("7.0.1.0")] +[assembly: AssemblyFileVersion("7.0.1.0")] + +[assembly: NUnit.Framework.Timeout(300000)] diff --git a/itext.tests/itext.kernel.tests/itext.kernel.tests.csproj b/itext.tests/itext.kernel.tests/itext.kernel.tests.csproj index 4d7f0dd728..4c8861c961 100644 --- a/itext.tests/itext.kernel.tests/itext.kernel.tests.csproj +++ b/itext.tests/itext.kernel.tests/itext.kernel.tests.csproj @@ -36,7 +36,7 @@ - ..\..\packages\NUnit.3.2.1\lib\net40\nunit.framework.dll + $(SolutionDir)\packages\NUnit.3.2.1\lib\net40\nunit.framework.dll diff --git a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfActionTest.cs b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfActionTest.cs index 80876a1620..b5e17b6caa 100644 --- a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfActionTest.cs +++ b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfActionTest.cs @@ -1,5 +1,4 @@ using System; -using System.IO; using iText.Kernel.Pdf.Action; using iText.Test; @@ -18,8 +17,7 @@ public static void BeforeClass() { /// [NUnit.Framework.Test] public virtual void ActionTest01() { - PdfWriter writer = new PdfWriter(new FileStream(destinationFolder + "actionTest01.pdf", FileMode.Create)); - PdfDocument document = CreateDocument(writer, true); + PdfDocument document = CreateDocument(new PdfWriter(destinationFolder + "actionTest01.pdf"), true); document.GetCatalog().SetOpenAction(PdfAction.CreateURI("http://itextpdf.com/")); document.Close(); System.Console.Out.WriteLine(String.Format("Please open document {0} and make sure that you're automatically redirected to {1} site." @@ -29,8 +27,7 @@ public virtual void ActionTest01() { /// [NUnit.Framework.Test] public virtual void ActionTest02() { - PdfWriter writer = new PdfWriter(new FileStream(destinationFolder + "actionTest02.pdf", FileMode.Create)); - PdfDocument document = CreateDocument(writer, false); + PdfDocument document = CreateDocument(new PdfWriter(destinationFolder + "actionTest02.pdf"), false); document.GetPage(2).SetAdditionalAction(PdfName.O, PdfAction.CreateURI("http://itextpdf.com/")); document.Close(); System.Console.Out.WriteLine(String.Format("Please open document {0} at page 2 and make sure that you're automatically redirected to {1} site." diff --git a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfAnnotationTest.cs b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfAnnotationTest.cs index 01c8fd5b62..2394573d5d 100644 --- a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfAnnotationTest.cs +++ b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfAnnotationTest.cs @@ -29,8 +29,7 @@ public static void BeforeClass() { /// [NUnit.Framework.Test] public virtual void AddLinkAnnotation01() { - PdfDocument document = new PdfDocument(new PdfWriter(new FileStream(destinationFolder + "linkAnnotation01.pdf" - , FileMode.Create))); + PdfDocument document = new PdfDocument(new PdfWriter(destinationFolder + "linkAnnotation01.pdf")); PdfPage page1 = document.AddNewPage(); PdfPage page2 = document.AddNewPage(); PdfCanvas canvas = new PdfCanvas(page1); @@ -61,8 +60,7 @@ public virtual void AddLinkAnnotation01() { /// [NUnit.Framework.Test] public virtual void AddLinkAnnotation02() { - PdfDocument document = new PdfDocument(new PdfWriter(new FileStream(destinationFolder + "linkAnnotation02.pdf" - , FileMode.Create))); + PdfDocument document = new PdfDocument(new PdfWriter(destinationFolder + "linkAnnotation02.pdf")); PdfPage page = document.AddNewPage(); PdfCanvas canvas = new PdfCanvas(page); canvas.BeginText(); @@ -83,8 +81,7 @@ public virtual void AddLinkAnnotation02() { /// [NUnit.Framework.Test] public virtual void AddAndGetLinkAnnotations() { - PdfDocument document = new PdfDocument(new PdfWriter(new FileStream(destinationFolder + "linkAnnotation03.pdf" - , FileMode.Create))); + PdfDocument document = new PdfDocument(new PdfWriter(destinationFolder + "linkAnnotation03.pdf")); PdfPage page = document.AddNewPage(); PdfCanvas canvas = new PdfCanvas(page); canvas.BeginText(); @@ -111,8 +108,7 @@ public virtual void AddAndGetLinkAnnotations() { document.Close(); NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(destinationFolder + "linkAnnotation03.pdf" , sourceFolder + "cmp_linkAnnotation03.pdf", destinationFolder, "diff_")); - document = new PdfDocument(new PdfReader(new FileStream(destinationFolder + "linkAnnotation03.pdf", FileMode.Open - , FileAccess.Read))); + document = new PdfDocument(new PdfReader(destinationFolder + "linkAnnotation03.pdf")); page = document.GetPage(1); NUnit.Framework.Assert.AreEqual(3, page.GetAnnotsSize()); IList annotations = page.GetAnnotations(); @@ -125,8 +121,7 @@ public virtual void AddAndGetLinkAnnotations() { /// [NUnit.Framework.Test] public virtual void AddTextAnnotation01() { - PdfDocument document = new PdfDocument(new PdfWriter(new FileStream(destinationFolder + "textAnnotation01.pdf" - , FileMode.Create))); + PdfDocument document = new PdfDocument(new PdfWriter(destinationFolder + "textAnnotation01.pdf")); PdfPage page = document.AddNewPage(); PdfTextAnnotation textannot = new PdfTextAnnotation(new Rectangle(100, 600, 50, 40)); textannot.SetText(new PdfString("Text Annotation 01")).SetContents(new PdfString("Some contents...")); @@ -147,10 +142,8 @@ public virtual void AddTextAnnotation01() { [NUnit.Framework.Test] public virtual void CaretTest() { String filename = destinationFolder + "caretAnnotation.pdf"; - FileStream fos1 = new FileStream(filename, FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1); - PdfDocument pdfDoc1 = new PdfDocument(writer1); - PdfPage page1 = pdfDoc1.AddNewPage(); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(filename)); + PdfPage page1 = pdfDoc.AddNewPage(); PdfCanvas canvas = new PdfCanvas(page1); canvas.SaveState().BeginText().MoveText(36, 750).SetFontAndSize(PdfFontFactory.CreateFont(FontConstants.HELVETICA ), 16).ShowText("This is a text").EndText().RestoreState(); @@ -165,7 +158,7 @@ public virtual void CaretTest() { page1.AddAnnotation(caret); page1.AddAnnotation(popup); page1.Flush(); - pdfDoc1.Close(); + pdfDoc.Close(); CompareTool compareTool = new CompareTool(); String errorMessage = compareTool.CompareByContent(filename, sourceFolder + "cmp_CaretAnnotation.pdf", destinationFolder , "diff_"); @@ -177,8 +170,7 @@ public virtual void CaretTest() { /// [NUnit.Framework.Test] public virtual void AddFreeTextAnnotation01() { - PdfDocument document = new PdfDocument(new PdfWriter(new FileStream(destinationFolder + "freeTextAnnotation01.pdf" - , FileMode.Create))); + PdfDocument document = new PdfDocument(new PdfWriter(destinationFolder + "freeTextAnnotation01.pdf")); PdfPage page = document.AddNewPage(); new PdfCanvas(page).BeginText().SetFontAndSize(PdfFontFactory.CreateFont(FontConstants.COURIER), 24).MoveText (100, 600).ShowText("Annotated text").EndText().Release(); @@ -198,8 +190,8 @@ public virtual void AddFreeTextAnnotation01() { /// [NUnit.Framework.Test] public virtual void AddSquareAndCircleAnnotations01() { - PdfDocument document = new PdfDocument(new PdfWriter(new FileStream(destinationFolder + "squareAndCircleAnnotations01.pdf" - , FileMode.Create))); + PdfDocument document = new PdfDocument(new PdfWriter(destinationFolder + "squareAndCircleAnnotations01.pdf" + )); PdfPage page = document.AddNewPage(); PdfSquareAnnotation square = new PdfSquareAnnotation(new Rectangle(100, 700, 100, 100)); square.SetInteriorColor(new float[] { 1, 0, 0 }).SetColor(new float[] { 0, 1, 0 }).SetContents("RED Square" @@ -220,18 +212,17 @@ public virtual void AddSquareAndCircleAnnotations01() { [NUnit.Framework.Test] public virtual void FileAttachmentTest() { String filename = destinationFolder + "fileAttachmentAnnotation.pdf"; - FileStream fos1 = new FileStream(filename, FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1); - writer1.SetCompressionLevel(CompressionConstants.NO_COMPRESSION); - PdfDocument pdfDoc1 = new PdfDocument(writer1); - PdfPage page1 = pdfDoc1.AddNewPage(); - PdfFileSpec spec = PdfFileSpec.CreateEmbeddedFileSpec(pdfDoc1, sourceFolder + "sample.wav", null, "sample.wav" + PdfWriter writer = new PdfWriter(filename); + writer.SetCompressionLevel(CompressionConstants.NO_COMPRESSION); + PdfDocument pdfDoc = new PdfDocument(writer); + PdfPage page1 = pdfDoc.AddNewPage(); + PdfFileSpec spec = PdfFileSpec.CreateEmbeddedFileSpec(pdfDoc, sourceFolder + "sample.wav", null, "sample.wav" , null, null, true); PdfFileAttachmentAnnotation fileAttach = new PdfFileAttachmentAnnotation(new Rectangle(100, 100), spec); fileAttach.SetIconName(PdfName.Paperclip); page1.AddAnnotation(fileAttach); page1.Flush(); - pdfDoc1.Close(); + pdfDoc.Close(); CompareTool compareTool = new CompareTool(); String errorMessage = compareTool.CompareByContent(filename, sourceFolder + "cmp_fileAttachmentAnnotation.pdf" , destinationFolder, "diff_"); @@ -245,10 +236,8 @@ public virtual void FileAttachmentTest() { [NUnit.Framework.Test] public virtual void RubberStampTest() { String filename = destinationFolder + "rubberStampAnnotation01.pdf"; - FileStream fos1 = new FileStream(filename, FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1); - PdfDocument pdfDoc1 = new PdfDocument(writer1); - PdfPage page1 = pdfDoc1.AddNewPage(); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(filename)); + PdfPage page1 = pdfDoc.AddNewPage(); PdfStampAnnotation stamp = new PdfStampAnnotation(new Rectangle(0, 0, 100, 50)); stamp.SetStampName(PdfName.Approved); PdfStampAnnotation stamp1 = new PdfStampAnnotation(new Rectangle(0, 50, 100, 50)); @@ -292,7 +281,7 @@ public virtual void RubberStampTest() { page1.AddAnnotation(stamp12); page1.AddAnnotation(stamp13); page1.Flush(); - pdfDoc1.Close(); + pdfDoc.Close(); CompareTool compareTool = new CompareTool(); String errorMessage = compareTool.CompareByContent(filename, sourceFolder + "cmp_rubberStampAnnotation01.pdf" , destinationFolder, "diff_"); @@ -306,15 +295,13 @@ public virtual void RubberStampTest() { [NUnit.Framework.Test] public virtual void RubberStampWrongStampTest() { String filename = destinationFolder + "rubberStampAnnotation02.pdf"; - FileStream fos1 = new FileStream(filename, FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1); - PdfDocument pdfDoc1 = new PdfDocument(writer1); - PdfPage page1 = pdfDoc1.AddNewPage(); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(filename)); + PdfPage page1 = pdfDoc.AddNewPage(); PdfStampAnnotation stamp = new PdfStampAnnotation(new Rectangle(0, 0, 100, 50)); stamp.SetStampName(PdfName.StrikeOut); page1.AddAnnotation(stamp); page1.Flush(); - pdfDoc1.Close(); + pdfDoc.Close(); CompareTool compareTool = new CompareTool(); String errorMessage = compareTool.CompareByContent(filename, sourceFolder + "cmp_rubberStampAnnotation02.pdf" , destinationFolder, "diff_"); @@ -328,10 +315,8 @@ public virtual void RubberStampWrongStampTest() { [NUnit.Framework.Test] public virtual void InkTest() { String filename = destinationFolder + "inkAnnotation01.pdf"; - FileStream fos1 = new FileStream(filename, FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1); - PdfDocument pdfDoc1 = new PdfDocument(writer1); - PdfPage page1 = pdfDoc1.AddNewPage(); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(filename)); + PdfPage page1 = pdfDoc.AddNewPage(); float[] array1 = new float[] { 100, 100, 100, 200, 200, 200, 300, 300 }; PdfArray firstPoint = new PdfArray(array1); PdfArray resultArray = new PdfArray(); @@ -346,7 +331,7 @@ public virtual void InkTest() { ink.SetColor(colors); page1.AddAnnotation(ink); page1.Flush(); - pdfDoc1.Close(); + pdfDoc.Close(); CompareTool compareTool = new CompareTool(); String errorMessage = compareTool.CompareByContent(filename, sourceFolder + "cmp_inkAnnotation01.pdf", destinationFolder , "diff_"); @@ -360,10 +345,8 @@ public virtual void InkTest() { [NUnit.Framework.Test] public virtual void TextMarkupTest01() { String filename = destinationFolder + "textMarkupAnnotation01.pdf"; - FileStream fos1 = new FileStream(filename, FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1); - PdfDocument pdfDoc1 = new PdfDocument(writer1); - PdfPage page1 = pdfDoc1.AddNewPage(); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(filename)); + PdfPage page1 = pdfDoc.AddNewPage(); PdfCanvas canvas = new PdfCanvas(page1); //Initialize canvas and write text to it canvas.SaveState().BeginText().MoveText(36, 750).SetFontAndSize(PdfFontFactory.CreateFont(FontConstants.HELVETICA @@ -376,7 +359,7 @@ public virtual void TextMarkupTest01() { markup.SetColor(colors); page1.AddAnnotation(markup); page1.Flush(); - pdfDoc1.Close(); + pdfDoc.Close(); CompareTool compareTool = new CompareTool(); String errorMessage = compareTool.CompareByContent(filename, sourceFolder + "cmp_textMarkupAnnotation01.pdf" , destinationFolder, "diff_"); @@ -390,10 +373,8 @@ public virtual void TextMarkupTest01() { [NUnit.Framework.Test] public virtual void TextMarkupTest02() { String filename = destinationFolder + "textMarkupAnnotation02.pdf"; - FileStream fos1 = new FileStream(filename, FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1); - PdfDocument pdfDoc1 = new PdfDocument(writer1); - PdfPage page1 = pdfDoc1.AddNewPage(); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(filename)); + PdfPage page1 = pdfDoc.AddNewPage(); PdfCanvas canvas = new PdfCanvas(page1); //Initialize canvas and write text to it canvas.SaveState().BeginText().MoveText(36, 750).SetFontAndSize(PdfFontFactory.CreateFont(FontConstants.HELVETICA @@ -406,7 +387,7 @@ public virtual void TextMarkupTest02() { markup.SetColor(colors); page1.AddAnnotation(markup); page1.Flush(); - pdfDoc1.Close(); + pdfDoc.Close(); CompareTool compareTool = new CompareTool(); String errorMessage = compareTool.CompareByContent(filename, sourceFolder + "cmp_textMarkupAnnotation02.pdf" , destinationFolder, "diff_"); @@ -420,10 +401,8 @@ public virtual void TextMarkupTest02() { [NUnit.Framework.Test] public virtual void TextMarkupTest03() { String filename = destinationFolder + "textMarkupAnnotation03.pdf"; - FileStream fos1 = new FileStream(filename, FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1); - PdfDocument pdfDoc1 = new PdfDocument(writer1); - PdfPage page1 = pdfDoc1.AddNewPage(); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(filename)); + PdfPage page1 = pdfDoc.AddNewPage(); PdfCanvas canvas = new PdfCanvas(page1); //Initialize canvas and write text to it canvas.SaveState().BeginText().MoveText(36, 750).SetFontAndSize(PdfFontFactory.CreateFont(FontConstants.HELVETICA @@ -436,7 +415,7 @@ public virtual void TextMarkupTest03() { markup.SetColor(colors); page1.AddAnnotation(markup); page1.Flush(); - pdfDoc1.Close(); + pdfDoc.Close(); CompareTool compareTool = new CompareTool(); String errorMessage = compareTool.CompareByContent(filename, sourceFolder + "cmp_textMarkupAnnotation03.pdf" , destinationFolder, "diff_"); @@ -450,10 +429,8 @@ public virtual void TextMarkupTest03() { [NUnit.Framework.Test] public virtual void TextMarkupTest04() { String filename = destinationFolder + "textMarkupAnnotation04.pdf"; - FileStream fos1 = new FileStream(filename, FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1); - PdfDocument pdfDoc1 = new PdfDocument(writer1); - PdfPage page1 = pdfDoc1.AddNewPage(); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(filename)); + PdfPage page1 = pdfDoc.AddNewPage(); PdfCanvas canvas = new PdfCanvas(page1); //Initialize canvas and write text to it canvas.SaveState().BeginText().MoveText(36, 750).SetFontAndSize(PdfFontFactory.CreateFont(FontConstants.HELVETICA @@ -466,7 +443,7 @@ public virtual void TextMarkupTest04() { markup.SetColor(colors); page1.AddAnnotation(markup); page1.Flush(); - pdfDoc1.Close(); + pdfDoc.Close(); CompareTool compareTool = new CompareTool(); String errorMessage = compareTool.CompareByContent(filename, sourceFolder + "cmp_textMarkupAnnotation04.pdf" , destinationFolder, "diff_"); @@ -480,21 +457,19 @@ public virtual void TextMarkupTest04() { [NUnit.Framework.Test] public virtual void PrinterMarkText() { String filename = destinationFolder + "printerMarkAnnotation01.pdf"; - FileStream fos1 = new FileStream(filename, FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1); - PdfDocument pdfDoc1 = new PdfDocument(writer1); - PdfPage page1 = pdfDoc1.AddNewPage(); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(filename)); + PdfPage page1 = pdfDoc.AddNewPage(); PdfCanvas canvasText = new PdfCanvas(page1); canvasText.SaveState().BeginText().MoveText(36, 790).SetFontAndSize(PdfFontFactory.CreateFont(FontConstants .HELVETICA), 16).ShowText("This is Printer Mark annotation:").EndText().RestoreState(); PdfFormXObject form = new PdfFormXObject(PageSize.A4); - PdfCanvas canvas = new PdfCanvas(form, pdfDoc1); + PdfCanvas canvas = new PdfCanvas(form, pdfDoc); canvas.SaveState().Circle(265, 795, 5).SetColor(Color.GREEN, true).Fill().RestoreState(); canvas.Release(); PdfPrinterMarkAnnotation printer = new PdfPrinterMarkAnnotation(PageSize.A4, form); page1.AddAnnotation(printer); page1.Flush(); - pdfDoc1.Close(); + pdfDoc.Close(); CompareTool compareTool = new CompareTool(); String errorMessage = compareTool.CompareByContent(filename, sourceFolder + "cmp_printerMarkAnnotation01.pdf" , destinationFolder, "diff_"); @@ -508,22 +483,20 @@ public virtual void PrinterMarkText() { [NUnit.Framework.Test] public virtual void TrapNetworkText() { String filename = destinationFolder + "trapNetworkAnnotation01.pdf"; - FileStream fos1 = new FileStream(filename, FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1); - PdfDocument pdfDoc1 = new PdfDocument(writer1); - PdfPage page = pdfDoc1.AddNewPage(); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(filename)); + PdfPage page = pdfDoc.AddNewPage(); PdfCanvas canvasText = new PdfCanvas(page); canvasText.SaveState().BeginText().MoveText(36, 790).SetFontAndSize(PdfFontFactory.CreateFont(FontConstants .HELVETICA), 16).ShowText("This is Trap Network annotation:").EndText().RestoreState(); PdfFormXObject form = new PdfFormXObject(PageSize.A4); - PdfCanvas canvas = new PdfCanvas(form, pdfDoc1); + PdfCanvas canvas = new PdfCanvas(form, pdfDoc); canvas.SaveState().Circle(272, 795, 5).SetColor(Color.GREEN, true).Fill().RestoreState(); canvas.Release(); form.SetProcessColorModel(PdfName.DeviceN); PdfTrapNetworkAnnotation trap = new PdfTrapNetworkAnnotation(PageSize.A4, form); page.AddAnnotation(trap); page.Flush(); - pdfDoc1.Close(); + pdfDoc.Close(); CompareTool compareTool = new CompareTool(); String errorMessage = compareTool.CompareByContent(filename, sourceFolder + "cmp_trapNetworkAnnotation01.pdf" , destinationFolder, "diff_"); @@ -539,10 +512,8 @@ public virtual void TrapNetworkText() { public virtual void SoundTestAif() { String filename = destinationFolder + "soundAnnotation02.pdf"; String audioFile = sourceFolder + "sample.aif"; - FileStream fos1 = new FileStream(filename, FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1); - PdfDocument pdfDoc1 = new PdfDocument(writer1); - PdfPage page1 = pdfDoc1.AddNewPage(); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(filename)); + PdfPage page1 = pdfDoc.AddNewPage(); Stream @is = new FileStream(audioFile, FileMode.Open, FileAccess.Read); String @string = ""; for (int i = 0; i < 4; i++) { @@ -555,7 +526,7 @@ public virtual void SoundTestAif() { else { @is = new FileStream(audioFile, FileMode.Open, FileAccess.Read); } - PdfStream sound1 = new PdfStream(pdfDoc1, @is); + PdfStream sound1 = new PdfStream(pdfDoc, @is); sound1.Put(PdfName.R, new PdfNumber(32117)); sound1.Put(PdfName.E, PdfName.Signed); sound1.Put(PdfName.B, new PdfNumber(16)); @@ -563,7 +534,7 @@ public virtual void SoundTestAif() { PdfSoundAnnotation sound = new PdfSoundAnnotation(new Rectangle(100, 100, 100, 100), sound1); page1.AddAnnotation(sound); page1.Flush(); - pdfDoc1.Close(); + pdfDoc.Close(); CompareTool compareTool = new CompareTool(); String errorMessage = compareTool.CompareByContent(filename, sourceFolder + "cmp_soundAnnotation02.pdf", destinationFolder , "diff_"); @@ -578,10 +549,8 @@ public virtual void SoundTestAif() { public virtual void SoundTestAiff() { String filename = destinationFolder + "soundAnnotation03.pdf"; String audioFile = sourceFolder + "sample.aiff"; - FileStream fos1 = new FileStream(filename, FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1); - PdfDocument pdfDoc1 = new PdfDocument(writer1); - PdfPage page1 = pdfDoc1.AddNewPage(); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(filename)); + PdfPage page1 = pdfDoc.AddNewPage(); Stream @is = new FileStream(audioFile, FileMode.Open, FileAccess.Read); String @string = ""; for (int i = 0; i < 4; i++) { @@ -594,7 +563,7 @@ public virtual void SoundTestAiff() { else { @is = new FileStream(audioFile, FileMode.Open, FileAccess.Read); } - PdfStream sound1 = new PdfStream(pdfDoc1, @is); + PdfStream sound1 = new PdfStream(pdfDoc, @is); sound1.Put(PdfName.R, new PdfNumber(44100)); sound1.Put(PdfName.E, PdfName.Signed); sound1.Put(PdfName.B, new PdfNumber(16)); @@ -602,7 +571,7 @@ public virtual void SoundTestAiff() { PdfSoundAnnotation sound = new PdfSoundAnnotation(new Rectangle(100, 100, 100, 100), sound1); page1.AddAnnotation(sound); page1.Flush(); - pdfDoc1.Close(); + pdfDoc.Close(); CompareTool compareTool = new CompareTool(); String errorMessage = compareTool.CompareByContent(filename, sourceFolder + "cmp_soundAnnotation03.pdf", destinationFolder , "diff_"); @@ -618,16 +587,14 @@ public virtual void SoundTestAiff() { public virtual void SoundTestSnd() { String filename = destinationFolder + "soundAnnotation04.pdf"; String audioFile = sourceFolder + "sample.snd"; - FileStream fos1 = new FileStream(filename, FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1); - PdfDocument pdfDoc1 = new PdfDocument(writer1); - PdfPage page1 = pdfDoc1.AddNewPage(); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(filename)); + PdfPage page1 = pdfDoc.AddNewPage(); Stream @is = new FileStream(audioFile, FileMode.Open, FileAccess.Read); - PdfSoundAnnotation sound = new PdfSoundAnnotation(pdfDoc1, new Rectangle(100, 100, 100, 100), @is, 44100, - PdfName.Signed, 2, 16); + PdfSoundAnnotation sound = new PdfSoundAnnotation(pdfDoc, new Rectangle(100, 100, 100, 100), @is, 44100, PdfName + .Signed, 2, 16); page1.AddAnnotation(sound); page1.Flush(); - pdfDoc1.Close(); + pdfDoc.Close(); CompareTool compareTool = new CompareTool(); String errorMessage = compareTool.CompareByContent(filename, sourceFolder + "cmp_soundAnnotation04.pdf", destinationFolder , "diff_"); @@ -643,16 +610,14 @@ public virtual void SoundTestSnd() { public virtual void SoundTestWav() { String filename = destinationFolder + "soundAnnotation01.pdf"; String audioFile = sourceFolder + "sample.wav"; - FileStream fos1 = new FileStream(filename, FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1); - PdfDocument pdfDoc1 = new PdfDocument(writer1); - PdfPage page1 = pdfDoc1.AddNewPage(); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(filename)); + PdfPage page1 = pdfDoc.AddNewPage(); Stream @is = new FileStream(audioFile, FileMode.Open, FileAccess.Read); - PdfSoundAnnotation sound = new PdfSoundAnnotation(pdfDoc1, new Rectangle(100, 100, 100, 100), @is, 48000, - PdfName.Signed, 2, 16); + PdfSoundAnnotation sound = new PdfSoundAnnotation(pdfDoc, new Rectangle(100, 100, 100, 100), @is, 48000, PdfName + .Signed, 2, 16); page1.AddAnnotation(sound); page1.Flush(); - pdfDoc1.Close(); + pdfDoc.Close(); CompareTool compareTool = new CompareTool(); String errorMessage = compareTool.CompareByContent(filename, sourceFolder + "cmp_soundAnnotation01.pdf", destinationFolder , "diff_"); @@ -668,10 +633,8 @@ public virtual void SoundTestWav() { public virtual void SoundTestWav01() { String filename = destinationFolder + "soundAnnotation05.pdf"; String audioFile = sourceFolder + "sample.wav"; - FileStream fos1 = new FileStream(filename, FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1); - PdfDocument pdfDoc1 = new PdfDocument(writer1); - PdfPage page1 = pdfDoc1.AddNewPage(); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(filename)); + PdfPage page1 = pdfDoc.AddNewPage(); Stream @is = new FileStream(audioFile, FileMode.Open, FileAccess.Read); String header = ""; for (int i = 0; i < 4; i++) { @@ -684,7 +647,7 @@ public virtual void SoundTestWav01() { else { @is = new FileStream(audioFile, FileMode.Open, FileAccess.Read); } - PdfStream soundStream = new PdfStream(pdfDoc1, @is); + PdfStream soundStream = new PdfStream(pdfDoc, @is); soundStream.Put(PdfName.R, new PdfNumber(48000)); soundStream.Put(PdfName.E, PdfName.Signed); soundStream.Put(PdfName.B, new PdfNumber(16)); @@ -692,7 +655,7 @@ public virtual void SoundTestWav01() { PdfSoundAnnotation sound = new PdfSoundAnnotation(new Rectangle(100, 100, 100, 100), soundStream); page1.AddAnnotation(sound); page1.Flush(); - pdfDoc1.Close(); + pdfDoc.Close(); CompareTool compareTool = new CompareTool(); String errorMessage = compareTool.CompareByContent(filename, sourceFolder + "cmp_soundAnnotation05.pdf", destinationFolder , "diff_"); @@ -706,48 +669,53 @@ public virtual void SoundTestWav01() { [NUnit.Framework.Test] public virtual void ScreenTestExternalWavFile() { String filename = destinationFolder + "screenAnnotation01.pdf"; - FileStream fos1 = new FileStream(filename, FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1); - PdfDocument pdfDoc1 = new PdfDocument(writer1); - PdfPage page1 = pdfDoc1.AddNewPage(); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(filename)); + PdfPage page1 = pdfDoc.AddNewPage(); PdfCanvas canvas = new PdfCanvas(page1); canvas.SaveState().BeginText().MoveText(36, 105).SetFontAndSize(PdfFontFactory.CreateFont(FontConstants.HELVETICA ), 16).ShowText("Click on the area below to play a sound.").EndText().RestoreState(); PdfScreenAnnotation screen = new PdfScreenAnnotation(new Rectangle(100, 100)); - PdfFileSpec spec = PdfFileSpec.CreateExternalFileSpec(pdfDoc1, "c:\\morph\\itext6\\itextpdf\\canvas\\src\\test\\resources\\com\\itextpdf\\canvas\\PdfAnnotationTest\\" - + "sample.wav", true); - PdfAction action = PdfAction.CreateRendition(sourceFolder + "sample.wav", spec, "audio/x-wav", screen); + FileStream fos = new FileStream(destinationFolder + "sample.wav", FileMode.Create); + FileStream fis = new FileStream(sourceFolder + "sample.wav", FileMode.Open, FileAccess.Read); + byte[] buffer = new byte[1024]; + int length; + while ((length = fis.Read(buffer)) > 0) { + fos.Write(buffer, 0, length); + } + fos.Close(); + fis.Close(); + PdfFileSpec spec = PdfFileSpec.CreateExternalFileSpec(pdfDoc, "sample.wav", true); + PdfAction action = PdfAction.CreateRendition("sample.wav", spec, "audio/x-wav", screen); screen.SetAction(action); page1.AddAnnotation(screen); page1.Flush(); - pdfDoc1.Close(); + pdfDoc.Close(); + CompareTool compareTool = new CompareTool(); + String errorMessage = compareTool.CompareByContent(filename, sourceFolder + "cmp_screenAnnotation01.pdf", + destinationFolder, "diff_"); + if (errorMessage != null) { + NUnit.Framework.Assert.Fail(errorMessage); + } } - // CompareTool compareTool = new CompareTool(); - // String errorMessage = compareTool.compareByContent(filename, sourceFolder + "cmp_screenAnnotation01.pdf", destinationFolder, "diff_"); - // if (errorMessage != null) { - // Assert.fail(errorMessage); - // } /// /// [NUnit.Framework.Test] public virtual void ScreenTestEmbeddedWavFile01() { String filename = destinationFolder + "screenAnnotation02.pdf"; - FileStream fos1 = new FileStream(filename, FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1); - PdfDocument pdfDoc1 = new PdfDocument(writer1); - PdfPage page1 = pdfDoc1.AddNewPage(); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(filename)); + PdfPage page1 = pdfDoc.AddNewPage(); PdfCanvas canvas = new PdfCanvas(page1); canvas.SaveState().BeginText().MoveText(36, 105).SetFontAndSize(PdfFontFactory.CreateFont(FontConstants.HELVETICA ), 16).ShowText("Click on the area below to play a sound.").EndText().RestoreState(); PdfScreenAnnotation screen = new PdfScreenAnnotation(new Rectangle(100, 100)); - PdfFileSpec spec = PdfFileSpec.CreateEmbeddedFileSpec(pdfDoc1, sourceFolder + "sample.wav", null, "sample.wav" + PdfFileSpec spec = PdfFileSpec.CreateEmbeddedFileSpec(pdfDoc, sourceFolder + "sample.wav", null, "sample.wav" , null, null, true); PdfAction action = PdfAction.CreateRendition(sourceFolder + "sample.wav", spec, "audio/x-wav", screen); screen.SetAction(action); page1.AddAnnotation(screen); page1.Flush(); - pdfDoc1.Close(); + pdfDoc.Close(); } // CompareTool compareTool = new CompareTool(); @@ -760,21 +728,19 @@ public virtual void ScreenTestEmbeddedWavFile01() { [NUnit.Framework.Test] public virtual void ScreenTestEmbeddedWavFile02() { String filename = destinationFolder + "screenAnnotation03.pdf"; - FileStream fos1 = new FileStream(filename, FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1); - PdfDocument pdfDoc1 = new PdfDocument(writer1); - PdfPage page1 = pdfDoc1.AddNewPage(); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(filename)); + PdfPage page1 = pdfDoc.AddNewPage(); PdfCanvas canvas = new PdfCanvas(page1); canvas.SaveState().BeginText().MoveText(36, 105).SetFontAndSize(PdfFontFactory.CreateFont(FontConstants.HELVETICA ), 16).ShowText("Click on the area below to play a sound.").EndText().RestoreState(); PdfScreenAnnotation screen = new PdfScreenAnnotation(new Rectangle(100, 100)); - PdfFileSpec spec = PdfFileSpec.CreateEmbeddedFileSpec(pdfDoc1, new FileStream(sourceFolder + "sample.wav", + PdfFileSpec spec = PdfFileSpec.CreateEmbeddedFileSpec(pdfDoc, new FileStream(sourceFolder + "sample.wav", FileMode.Open, FileAccess.Read), null, "sample.wav", null, null, true); PdfAction action = PdfAction.CreateRendition(sourceFolder + "sample.wav", spec, "audio/x-wav", screen); screen.SetAction(action); page1.AddAnnotation(screen); page1.Flush(); - pdfDoc1.Close(); + pdfDoc.Close(); } // CompareTool compareTool = new CompareTool(); @@ -787,10 +753,8 @@ public virtual void ScreenTestEmbeddedWavFile02() { [NUnit.Framework.Test] public virtual void ScreenTestEmbeddedWavFile03() { String filename = destinationFolder + "screenAnnotation04.pdf"; - FileStream fos1 = new FileStream(filename, FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1); - PdfDocument pdfDoc1 = new PdfDocument(writer1); - PdfPage page1 = pdfDoc1.AddNewPage(); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(filename)); + PdfPage page1 = pdfDoc.AddNewPage(); PdfCanvas canvas = new PdfCanvas(page1); canvas.SaveState().BeginText().MoveText(36, 105).SetFontAndSize(PdfFontFactory.CreateFont(FontConstants.HELVETICA ), 16).ShowText("Click on the area below to play a sound.").EndText().RestoreState(); @@ -802,13 +766,13 @@ public virtual void ScreenTestEmbeddedWavFile03() { baos.Write(reads); reads = @is.Read(); } - PdfFileSpec spec = PdfFileSpec.CreateEmbeddedFileSpec(pdfDoc1, baos.ToArray(), null, "sample.wav", null, null + PdfFileSpec spec = PdfFileSpec.CreateEmbeddedFileSpec(pdfDoc, baos.ToArray(), null, "sample.wav", null, null , null, true); PdfAction action = PdfAction.CreateRendition(sourceFolder + "sample.wav", spec, "audio/x-wav", screen); screen.SetAction(action); page1.AddAnnotation(screen); page1.Flush(); - pdfDoc1.Close(); + pdfDoc.Close(); } // CompareTool compareTool = new CompareTool(); @@ -821,10 +785,8 @@ public virtual void ScreenTestEmbeddedWavFile03() { [NUnit.Framework.Test] public virtual void WaterMarkTest() { String filename = destinationFolder + "waterMarkAnnotation01.pdf"; - FileStream fos1 = new FileStream(filename, FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1); - PdfDocument pdfDoc1 = new PdfDocument(writer1); - PdfPage page1 = pdfDoc1.AddNewPage(); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(filename)); + PdfPage page1 = pdfDoc.AddNewPage(); PdfWatermarkAnnotation watermark = new PdfWatermarkAnnotation(new Rectangle(400, 400, 200, 200)); float[] arr = new float[] { 1, 0, 0, 1, 0, 0 }; PdfFixedPrint fixedPrint = new PdfFixedPrint(); @@ -833,14 +795,14 @@ public virtual void WaterMarkTest() { fixedPrint.SetVerticalTranslation(0); watermark.SetFixedPrint(fixedPrint); PdfFormXObject form = new PdfFormXObject(new Rectangle(200, 200)); - PdfCanvas canvas = new PdfCanvas(form, pdfDoc1); + PdfCanvas canvas = new PdfCanvas(form, pdfDoc); canvas.SaveState().Circle(100, 100, 50).SetColor(Color.BLACK, true).Fill().RestoreState(); canvas.Release(); watermark.SetNormalAppearance(form.GetPdfObject()); watermark.SetFlags(PdfAnnotation.PRINT); page1.AddAnnotation(watermark); page1.Flush(); - pdfDoc1.Close(); + pdfDoc.Close(); CompareTool compareTool = new CompareTool(); String errorMessage = compareTool.CompareByContent(filename, sourceFolder + "cmp_watermarkAnnotation01.pdf" , destinationFolder, "diff_"); @@ -854,28 +816,26 @@ public virtual void WaterMarkTest() { [NUnit.Framework.Test] public virtual void RedactionTest() { String filename = destinationFolder + "redactionAnnotation01.pdf"; - FileStream fos1 = new FileStream(filename, FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1); - PdfDocument pdfDoc1 = new PdfDocument(writer1); - PdfPage page1 = pdfDoc1.AddNewPage(); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(filename)); + PdfPage page1 = pdfDoc.AddNewPage(); float[] rgb = new float[] { 0, 0, 0 }; float[] rgb1 = new float[] { 1, 0, 0 }; PdfRedactAnnotation redact = new PdfRedactAnnotation(new Rectangle(180, 531, 120, 49)); PdfFormXObject formD = new PdfFormXObject(new Rectangle(180, 531, 120, 49)); - PdfCanvas canvasD = new PdfCanvas(formD, pdfDoc1); + PdfCanvas canvasD = new PdfCanvas(formD, pdfDoc); canvasD.SetFillColorGray(0).Rectangle(180, 531, 120, 48).Fill(); redact.SetDownAppearance(formD.GetPdfObject()); PdfFormXObject formN = new PdfFormXObject(new Rectangle(179, 530, 122, 51)); - PdfCanvas canvasN = new PdfCanvas(formN, pdfDoc1); + PdfCanvas canvasN = new PdfCanvas(formN, pdfDoc); canvasN.SetColor(Color.RED, true).SetLineWidth(1.5f).SetLineCapStyle(PdfCanvasConstants.LineCapStyle.PROJECTING_SQUARE ).Rectangle(180, 531, 120, 48).Stroke().Rectangle(181, 532, 118, 47).ClosePath(); redact.SetNormalAppearance(formN.GetPdfObject()); PdfFormXObject formR = new PdfFormXObject(new Rectangle(180, 531, 120, 49)); - PdfCanvas canvasR = new PdfCanvas(formR, pdfDoc1); + PdfCanvas canvasR = new PdfCanvas(formR, pdfDoc); canvasR.SaveState().Rectangle(180, 531, 120, 48).Fill().RestoreState().Release(); redact.SetRolloverAppearance(formR.GetPdfObject()); PdfFormXObject formRO = new PdfFormXObject(new Rectangle(180, 531, 120, 49)); - PdfCanvas canvasRO = new PdfCanvas(formRO, pdfDoc1); + PdfCanvas canvasRO = new PdfCanvas(formRO, pdfDoc); canvasRO.SaveState().Rectangle(180, 531, 120, 48).Fill().RestoreState().Release(); redact.SetRedactRolloverAppearance(formRO.GetPdfObject()); redact.Put(PdfName.OC, new PdfArray(rgb1)); @@ -883,7 +843,7 @@ public virtual void RedactionTest() { redact.SetInteriorColor(rgb); page1.AddAnnotation(redact); page1.Flush(); - pdfDoc1.Close(); + pdfDoc.Close(); CompareTool compareTool = new CompareTool(); String errorMessage = compareTool.CompareByContent(filename, sourceFolder + "cmp_redactionAnnotation01.pdf" , destinationFolder, "diff_"); diff --git a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfArrayTest.cs b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfArrayTest.cs new file mode 100644 index 0000000000..9bfd0e6982 --- /dev/null +++ b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfArrayTest.cs @@ -0,0 +1,158 @@ +using iText.IO.Source; + +namespace iText.Kernel.Pdf { + public class PdfArrayTest { + [NUnit.Framework.Test] + public virtual void TestValuesIndirectContains() { + PdfDocument doc = new PdfDocument(new PdfWriter(new ByteArrayOutputStream())); + PdfArray array = new PdfArray(); + array.Add(((PdfNumber)new PdfNumber(0).MakeIndirect(doc)).GetIndirectReference()); + array.Add(((PdfNumber)new PdfNumber(1).MakeIndirect(doc)).GetIndirectReference()); + array.Add(((PdfNumber)new PdfNumber(2).MakeIndirect(doc))); + array.Add(((PdfNumber)new PdfNumber(3).MakeIndirect(doc))); + array.Add(new PdfNumber(4)); + array.Add(new PdfNumber(5)); + NUnit.Framework.Assert.IsTrue(array.Contains(array.Get(0, false))); + NUnit.Framework.Assert.IsTrue(array.Contains(array.Get(1, false))); + NUnit.Framework.Assert.IsTrue(array.Contains(array.Get(2).GetIndirectReference())); + NUnit.Framework.Assert.IsTrue(array.Contains(array.Get(3).GetIndirectReference())); + NUnit.Framework.Assert.IsTrue(array.Contains(array.Get(4))); + NUnit.Framework.Assert.IsTrue(array.Contains(array.Get(5))); + } + + [NUnit.Framework.Test] + public virtual void TestValuesIndirectRemove() { + PdfDocument doc = new PdfDocument(new PdfWriter(new ByteArrayOutputStream())); + PdfArray array = new PdfArray(); + array.Add(((PdfNumber)new PdfNumber(1).MakeIndirect(doc)).GetIndirectReference()); + array.Add(((PdfNumber)new PdfNumber(2).MakeIndirect(doc)).GetIndirectReference()); + array.Add(((PdfNumber)new PdfNumber(3).MakeIndirect(doc))); + array.Add(((PdfNumber)new PdfNumber(4).MakeIndirect(doc))); + array.Add(new PdfNumber(5)); + array.Add(new PdfNumber(6)); + array.Remove(array.Get(0, false)); + array.Remove(array.Get(0, false)); + array.Remove(array.Get(0).GetIndirectReference()); + array.Remove(array.Get(0).GetIndirectReference()); + array.Remove(array.Get(0)); + array.Remove(array.Get(0)); + NUnit.Framework.Assert.AreEqual(0, array.Size()); + } + + [NUnit.Framework.Test] + public virtual void TestContains() { + PdfDocument doc = new PdfDocument(new PdfWriter(new ByteArrayOutputStream())); + PdfArray array = new PdfArray(); + array.Add(((PdfNumber)new PdfNumber(1).MakeIndirect(doc)).GetIndirectReference()); + array.Add(((PdfNumber)new PdfNumber(2).MakeIndirect(doc)).GetIndirectReference()); + array.Add(((PdfNumber)new PdfNumber(3).MakeIndirect(doc))); + array.Add(((PdfNumber)new PdfNumber(4).MakeIndirect(doc))); + array.Add(new PdfNumber(5)); + array.Add(new PdfNumber(6)); + PdfArray array2 = new PdfArray(); + array2.Add(((PdfNumber)new PdfNumber(1).MakeIndirect(doc)).GetIndirectReference()); + array2.Add(((PdfNumber)new PdfNumber(2).MakeIndirect(doc)).GetIndirectReference()); + array2.Add(((PdfNumber)new PdfNumber(3).MakeIndirect(doc))); + array2.Add(((PdfNumber)new PdfNumber(4).MakeIndirect(doc))); + array2.Add(new PdfNumber(5)); + array2.Add(new PdfNumber(6)); + foreach (PdfObject obj in array2) { + NUnit.Framework.Assert.IsTrue(array.Contains(obj)); + } + for (int i = 0; i < array2.Size(); i++) { + NUnit.Framework.Assert.IsTrue(array.Contains(array2.Get(i))); + } + } + + [NUnit.Framework.Test] + public virtual void TestRemove() { + PdfDocument doc = new PdfDocument(new PdfWriter(new ByteArrayOutputStream())); + PdfArray array = new PdfArray(); + array.Add(((PdfNumber)new PdfNumber(1).MakeIndirect(doc)).GetIndirectReference()); + array.Add(((PdfNumber)new PdfNumber(2).MakeIndirect(doc)).GetIndirectReference()); + array.Add(((PdfNumber)new PdfNumber(3).MakeIndirect(doc))); + array.Add(((PdfNumber)new PdfNumber(4).MakeIndirect(doc))); + array.Add(new PdfNumber(5)); + array.Add(new PdfNumber(6)); + PdfArray array2 = new PdfArray(); + array2.Add(((PdfNumber)new PdfNumber(1).MakeIndirect(doc)).GetIndirectReference()); + array2.Add(((PdfNumber)new PdfNumber(2).MakeIndirect(doc)).GetIndirectReference()); + array2.Add(((PdfNumber)new PdfNumber(3).MakeIndirect(doc))); + array2.Add(((PdfNumber)new PdfNumber(4).MakeIndirect(doc))); + array2.Add(new PdfNumber(5)); + array2.Add(new PdfNumber(6)); + foreach (PdfObject obj in array2) { + array.Remove(obj); + } + NUnit.Framework.Assert.AreEqual(0, array.Size()); + } + + [NUnit.Framework.Test] + public virtual void TestRemove2() { + PdfDocument doc = new PdfDocument(new PdfWriter(new ByteArrayOutputStream())); + PdfArray array = new PdfArray(); + array.Add(((PdfNumber)new PdfNumber(1).MakeIndirect(doc)).GetIndirectReference()); + array.Add(((PdfNumber)new PdfNumber(2).MakeIndirect(doc)).GetIndirectReference()); + array.Add(((PdfNumber)new PdfNumber(3).MakeIndirect(doc))); + array.Add(((PdfNumber)new PdfNumber(4).MakeIndirect(doc))); + array.Add(new PdfNumber(5)); + array.Add(new PdfNumber(6)); + PdfArray array2 = new PdfArray(); + array2.Add(((PdfNumber)new PdfNumber(1).MakeIndirect(doc)).GetIndirectReference()); + array2.Add(((PdfNumber)new PdfNumber(2).MakeIndirect(doc)).GetIndirectReference()); + array2.Add(((PdfNumber)new PdfNumber(3).MakeIndirect(doc))); + array2.Add(((PdfNumber)new PdfNumber(4).MakeIndirect(doc))); + array2.Add(new PdfNumber(5)); + array2.Add(new PdfNumber(6)); + for (int i = 0; i < array2.Size(); i++) { + array.Remove(array2.Get(i)); + } + NUnit.Framework.Assert.AreEqual(0, array.Size()); + } + + [NUnit.Framework.Test] + public virtual void TestIndexOf() { + PdfDocument doc = new PdfDocument(new PdfWriter(new ByteArrayOutputStream())); + PdfArray array = new PdfArray(); + array.Add(((PdfNumber)new PdfNumber(1).MakeIndirect(doc)).GetIndirectReference()); + array.Add(((PdfNumber)new PdfNumber(2).MakeIndirect(doc)).GetIndirectReference()); + array.Add(((PdfNumber)new PdfNumber(3).MakeIndirect(doc))); + array.Add(((PdfNumber)new PdfNumber(4).MakeIndirect(doc))); + array.Add(new PdfNumber(5)); + array.Add(new PdfNumber(6)); + PdfArray array2 = new PdfArray(); + array2.Add(((PdfNumber)new PdfNumber(1).MakeIndirect(doc)).GetIndirectReference()); + array2.Add(((PdfNumber)new PdfNumber(2).MakeIndirect(doc)).GetIndirectReference()); + array2.Add(((PdfNumber)new PdfNumber(3).MakeIndirect(doc))); + array2.Add(((PdfNumber)new PdfNumber(4).MakeIndirect(doc))); + array2.Add(new PdfNumber(5)); + array2.Add(new PdfNumber(6)); + int i = 0; + foreach (PdfObject obj in array2) { + NUnit.Framework.Assert.AreEqual(i++, array.IndexOf(obj)); + } + } + + [NUnit.Framework.Test] + public virtual void TestIndexOf2() { + PdfDocument doc = new PdfDocument(new PdfWriter(new ByteArrayOutputStream())); + PdfArray array = new PdfArray(); + array.Add(((PdfNumber)new PdfNumber(1).MakeIndirect(doc)).GetIndirectReference()); + array.Add(((PdfNumber)new PdfNumber(2).MakeIndirect(doc)).GetIndirectReference()); + array.Add(((PdfNumber)new PdfNumber(3).MakeIndirect(doc))); + array.Add(((PdfNumber)new PdfNumber(4).MakeIndirect(doc))); + array.Add(new PdfNumber(5)); + array.Add(new PdfNumber(6)); + PdfArray array2 = new PdfArray(); + array2.Add(((PdfNumber)new PdfNumber(1).MakeIndirect(doc)).GetIndirectReference()); + array2.Add(((PdfNumber)new PdfNumber(2).MakeIndirect(doc)).GetIndirectReference()); + array2.Add(((PdfNumber)new PdfNumber(3).MakeIndirect(doc))); + array2.Add(((PdfNumber)new PdfNumber(4).MakeIndirect(doc))); + array2.Add(new PdfNumber(5)); + array2.Add(new PdfNumber(6)); + for (int i = 0; i < array2.Size(); i++) { + NUnit.Framework.Assert.AreEqual(i, array.IndexOf(array2.Get(i))); + } + } + } +} diff --git a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfCanvasTest.cs b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfCanvasTest.cs index b7cfe8ae14..697d265af1 100644 --- a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfCanvasTest.cs +++ b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfCanvasTest.cs @@ -40,9 +40,7 @@ public virtual void CreateSimpleCanvas() { String author = "Alexander Chingarev"; String creator = "iText 6"; String title = "Empty iText 6 Document"; - FileStream fos = new FileStream(destinationFolder + "simpleCanvas.pdf", FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(destinationFolder + "simpleCanvas.pdf")); pdfDoc.GetDocumentInfo().SetAuthor(author).SetCreator(creator).SetTitle(title); PdfPage page1 = pdfDoc.AddNewPage(); PdfCanvas canvas = new PdfCanvas(page1); @@ -69,9 +67,7 @@ public virtual void CreateSimpleCanvasWithDrawing() { String author = "Alexander Chingarev"; String creator = "iText 6"; String title = "Empty iText 6 Document"; - FileStream fos = new FileStream(destinationFolder + fileName, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(destinationFolder + fileName)); pdfDoc.GetDocumentInfo().SetAuthor(author).SetCreator(creator).SetTitle(title); PdfPage page1 = pdfDoc.AddNewPage(); PdfCanvas canvas = new PdfCanvas(page1); @@ -95,7 +91,7 @@ public virtual void CreateSimpleCanvasWithDrawing() { NUnit.Framework.Assert.AreEqual(1, pdfDocument.GetNumberOfPages(), "Page count"); PdfDictionary page = pdfDocument.GetPage(1).GetPdfObject(); NUnit.Framework.Assert.AreEqual(PdfName.Page, page.Get(PdfName.Type)); - reader.Close(); + pdfDocument.Close(); } /// @@ -105,9 +101,7 @@ public virtual void CreateSimpleCanvasWithText() { String author = "Alexander Chingarev"; String creator = "iText 6"; String title = "Empty iText 6 Document"; - FileStream fos = new FileStream(destinationFolder + fileName, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(destinationFolder + fileName)); pdfDoc.GetDocumentInfo().SetAuthor(author).SetCreator(creator).SetTitle(title); PdfPage page1 = pdfDoc.AddNewPage(); PdfCanvas canvas = new PdfCanvas(page1); @@ -136,7 +130,7 @@ public virtual void CreateSimpleCanvasWithText() { NUnit.Framework.Assert.AreEqual(1, pdfDocument.GetNumberOfPages(), "Page count"); PdfDictionary page = pdfDocument.GetPage(1).GetPdfObject(); NUnit.Framework.Assert.AreEqual(PdfName.Page, page.Get(PdfName.Type)); - reader.Close(); + pdfDocument.Close(); } /// @@ -145,9 +139,7 @@ public virtual void CreateSimpleCanvasWithPageFlush() { String author = "Alexander Chingarev"; String creator = "iText 6"; String title = "Empty iText 6 Document"; - FileStream fos = new FileStream(destinationFolder + "simpleCanvasWithPageFlush.pdf", FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(destinationFolder + "simpleCanvasWithPageFlush.pdf")); pdfDoc.GetDocumentInfo().SetAuthor(author).SetCreator(creator).SetTitle(title); PdfPage page1 = pdfDoc.AddNewPage(); PdfCanvas canvas = new PdfCanvas(page1); @@ -165,7 +157,7 @@ public virtual void CreateSimpleCanvasWithPageFlush() { NUnit.Framework.Assert.AreEqual(1, pdfDocument.GetNumberOfPages(), "Page count"); PdfDictionary page = pdfDocument.GetPage(1).GetPdfObject(); NUnit.Framework.Assert.AreEqual(PdfName.Page, page.Get(PdfName.Type)); - reader.Close(); + pdfDocument.Close(); } /// @@ -174,9 +166,8 @@ public virtual void CreateSimpleCanvasWithFullCompression() { String author = "Alexander Chingarev"; String creator = "iText 6"; String title = "Empty iText 6 Document"; - FileStream fos = new FileStream(destinationFolder + "simpleCanvasWithFullCompression.pdf", FileMode.Create - ); - PdfWriter writer = new PdfWriter(fos, new WriterProperties().SetFullCompressionMode(true)); + PdfWriter writer = new PdfWriter(destinationFolder + "simpleCanvasWithFullCompression.pdf", new WriterProperties + ().SetFullCompressionMode(true)); PdfDocument pdfDoc = new PdfDocument(writer); pdfDoc.GetDocumentInfo().SetAuthor(author).SetCreator(creator).SetTitle(title); PdfPage page1 = pdfDoc.AddNewPage(); @@ -194,7 +185,7 @@ public virtual void CreateSimpleCanvasWithFullCompression() { NUnit.Framework.Assert.AreEqual(1, pdfDocument.GetNumberOfPages(), "Page count"); PdfDictionary page = pdfDocument.GetPage(1).GetPdfObject(); NUnit.Framework.Assert.AreEqual(PdfName.Page, page.Get(PdfName.Type)); - reader.Close(); + pdfDocument.Close(); } /// @@ -203,9 +194,8 @@ public virtual void CreateSimpleCanvasWithPageFlushAndFullCompression() { String author = "Alexander Chingarev"; String creator = "iText 6"; String title = "Empty iText 6 Document"; - FileStream fos = new FileStream(destinationFolder + "simpleCanvasWithPageFlushAndFullCompression.pdf", FileMode.Create - ); - PdfWriter writer = new PdfWriter(fos, new WriterProperties().SetFullCompressionMode(true)); + PdfWriter writer = new PdfWriter(destinationFolder + "simpleCanvasWithPageFlushAndFullCompression.pdf", new + WriterProperties().SetFullCompressionMode(true)); PdfDocument pdfDoc = new PdfDocument(writer); pdfDoc.GetDocumentInfo().SetAuthor(author).SetCreator(creator).SetTitle(title); PdfPage page1 = pdfDoc.AddNewPage(); @@ -224,7 +214,7 @@ public virtual void CreateSimpleCanvasWithPageFlushAndFullCompression() { NUnit.Framework.Assert.AreEqual(1, pdfDocument.GetNumberOfPages(), "Page count"); PdfDictionary page = pdfDocument.GetPage(1).GetPdfObject(); NUnit.Framework.Assert.AreEqual(PdfName.Page, page.Get(PdfName.Type)); - reader.Close(); + pdfDocument.Close(); } /// @@ -235,9 +225,7 @@ public virtual void Create1000PagesDocument() { String author = "Alexander Chingarev"; String creator = "iText 6"; String title = "Empty iText 6 Document"; - FileStream fos = new FileStream(filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(filename)); pdfDoc.GetDocumentInfo().SetAuthor(author).SetCreator(creator).SetTitle(title); for (int i = 0; i < pageCount; i++) { PdfPage page = pdfDoc.AddNewPage(); @@ -261,7 +249,7 @@ public virtual void Create1000PagesDocument() { PdfDictionary page = pdfDocument.GetPage(i_1).GetPdfObject(); NUnit.Framework.Assert.AreEqual(PdfName.Page, page.Get(PdfName.Type)); } - reader.Close(); + pdfDocument.Close(); } /// @@ -272,9 +260,7 @@ public virtual void Create100PagesDocument() { String author = "Alexander Chingarev"; String creator = "iText 6"; String title = "Empty iText 6 Document"; - FileStream fos = new FileStream(filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(filename)); pdfDoc.GetDocumentInfo().SetAuthor(author).SetCreator(creator).SetTitle(title); for (int i = 0; i < pageCount; i++) { PdfPage page = pdfDoc.AddNewPage(); @@ -298,7 +284,7 @@ public virtual void Create100PagesDocument() { PdfDictionary page = pdfDocument.GetPage(i_1).GetPdfObject(); NUnit.Framework.Assert.AreEqual(PdfName.Page, page.Get(PdfName.Type)); } - reader.Close(); + pdfDocument.Close(); } /// @@ -309,9 +295,7 @@ public virtual void Create10PagesDocument() { String author = "Alexander Chingarev"; String creator = "iText 6"; String title = "Empty iText 6 Document"; - FileStream fos = new FileStream(filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(filename)); pdfDoc.GetDocumentInfo().SetAuthor(author).SetCreator(creator).SetTitle(title); for (int i = 0; i < pageCount; i++) { PdfPage page = pdfDoc.AddNewPage(); @@ -335,7 +319,7 @@ public virtual void Create10PagesDocument() { PdfDictionary page = pdfDocument.GetPage(i_1).GetPdfObject(); NUnit.Framework.Assert.AreEqual(PdfName.Page, page.Get(PdfName.Type)); } - reader.Close(); + pdfDocument.Close(); } /// @@ -346,9 +330,7 @@ public virtual void Create1000PagesDocumentWithText() { String author = "Alexander Chingarev"; String creator = "iText 6"; String title = "Empty iText 6 Document"; - FileStream fos = new FileStream(filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(filename)); pdfDoc.GetDocumentInfo().SetAuthor(author).SetCreator(creator).SetTitle(title); for (int i = 0; i < pageCount; i++) { PdfPage page = pdfDoc.AddNewPage(); @@ -372,7 +354,7 @@ public virtual void Create1000PagesDocumentWithText() { PdfDictionary page = pdfDocument.GetPage(i_1).GetPdfObject(); NUnit.Framework.Assert.AreEqual(PdfName.Page, page.Get(PdfName.Type)); } - reader.Close(); + pdfDocument.Close(); } /// @@ -383,8 +365,7 @@ public virtual void Create1000PagesDocumentWithFullCompression() { String author = "Alexander Chingarev"; String creator = "iText 6"; String title = "Empty iText 6 Document"; - FileStream fos = new FileStream(filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos, new WriterProperties().SetFullCompressionMode(true)); + PdfWriter writer = new PdfWriter(filename, new WriterProperties().SetFullCompressionMode(true)); PdfDocument pdfDoc = new PdfDocument(writer); pdfDoc.GetDocumentInfo().SetAuthor(author).SetCreator(creator).SetTitle(title); for (int i = 0; i < pageCount; i++) { @@ -409,7 +390,7 @@ public virtual void Create1000PagesDocumentWithFullCompression() { PdfDictionary page = pdfDocument.GetPage(i_1).GetPdfObject(); NUnit.Framework.Assert.AreEqual(PdfName.Page, page.Get(PdfName.Type)); } - reader.Close(); + pdfDocument.Close(); } /// @@ -420,8 +401,7 @@ public virtual void Create100PagesDocumentWithFullCompression() { String author = "Alexander Chingarev"; String creator = "iText 6"; String title = "Empty iText 6 Document"; - FileStream fos = new FileStream(filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos, new WriterProperties().SetFullCompressionMode(true)); + PdfWriter writer = new PdfWriter(filename, new WriterProperties().SetFullCompressionMode(true)); PdfDocument pdfDoc = new PdfDocument(writer); pdfDoc.GetDocumentInfo().SetAuthor(author).SetCreator(creator).SetTitle(title); for (int i = 0; i < pageCount; i++) { @@ -446,7 +426,7 @@ public virtual void Create100PagesDocumentWithFullCompression() { PdfDictionary page = pdfDocument.GetPage(i_1).GetPdfObject(); NUnit.Framework.Assert.AreEqual(PdfName.Page, page.Get(PdfName.Type)); } - reader.Close(); + pdfDocument.Close(); } /// @@ -457,8 +437,7 @@ public virtual void Create197PagesDocumentWithFullCompression() { String author = "Alexander Chingarev"; String creator = "iText 6"; String title = "Empty iText 6 Document"; - FileStream fos = new FileStream(filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos, new WriterProperties().SetFullCompressionMode(true)); + PdfWriter writer = new PdfWriter(filename, new WriterProperties().SetFullCompressionMode(true)); PdfDocument pdfDoc = new PdfDocument(writer); pdfDoc.GetDocumentInfo().SetAuthor(author).SetCreator(creator).SetTitle(title); for (int i = 0; i < pageCount; i++) { @@ -483,7 +462,7 @@ public virtual void Create197PagesDocumentWithFullCompression() { PdfDictionary page = pdfDocument.GetPage(i_1).GetPdfObject(); NUnit.Framework.Assert.AreEqual(PdfName.Page, page.Get(PdfName.Type)); } - reader.Close(); + pdfDocument.Close(); } /// @@ -494,8 +473,7 @@ public virtual void Create10PagesDocumentWithFullCompression() { String author = "Alexander Chingarev"; String creator = "iText 6"; String title = "Empty iText 6 Document"; - FileStream fos = new FileStream(filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos, new WriterProperties().SetFullCompressionMode(true)); + PdfWriter writer = new PdfWriter(filename, new WriterProperties().SetFullCompressionMode(true)); PdfDocument pdfDoc = new PdfDocument(writer); pdfDoc.GetDocumentInfo().SetAuthor(author).SetCreator(creator).SetTitle(title); for (int i = 0; i < pageCount; i++) { @@ -520,7 +498,7 @@ public virtual void Create10PagesDocumentWithFullCompression() { PdfDictionary page = pdfDocument.GetPage(i_1).GetPdfObject(); NUnit.Framework.Assert.AreEqual(PdfName.Page, page.Get(PdfName.Type)); } - reader.Close(); + pdfDocument.Close(); } /// @@ -529,8 +507,7 @@ public virtual void Create10PagesDocumentWithFullCompression() { public virtual void CopyPagesTest1() { String file1 = destinationFolder + "copyPages1_1.pdf"; String file2 = destinationFolder + "copyPages1_2.pdf"; - PdfWriter writer1 = new PdfWriter(new FileStream(file1, FileMode.Create)); - PdfDocument pdfDoc1 = new PdfDocument(writer1); + PdfDocument pdfDoc1 = new PdfDocument(new PdfWriter(file1)); PdfPage page1 = pdfDoc1.AddNewPage(); PdfCanvas canvas = new PdfCanvas(page1); canvas.Rectangle(100, 600, 100, 100); @@ -543,12 +520,9 @@ public virtual void CopyPagesTest1() { canvas.Release(); page1.Flush(); pdfDoc1.Close(); - PdfReader reader1 = new PdfReader(new FileStream(file1, FileMode.Open, FileAccess.Read)); - pdfDoc1 = new PdfDocument(reader1); + pdfDoc1 = new PdfDocument(new PdfReader(file1)); page1 = pdfDoc1.GetPage(1); - FileStream fos2 = new FileStream(file2, FileMode.Create); - PdfWriter writer2 = new PdfWriter(fos2); - PdfDocument pdfDoc2 = new PdfDocument(writer2); + PdfDocument pdfDoc2 = new PdfDocument(new PdfWriter(file2)); PdfPage page2 = page1.CopyTo(pdfDoc2); pdfDoc2.AddPage(page2); page2.Flush(); @@ -563,7 +537,7 @@ public virtual void CopyPagesTest1() { NUnit.Framework.Assert.AreEqual(false, reader.HasRebuiltXref(), "Rebuilt"); PdfDictionary page_1 = pdfDocument.GetPage(1).GetPdfObject(); NUnit.Framework.Assert.IsNotNull(page_1.Get(PdfName.Parent)); - reader.Close(); + pdfDocument.Close(); NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(file1, file2, destinationFolder, "diff_") ); } @@ -574,8 +548,7 @@ public virtual void CopyPagesTest1() { public virtual void CopyPagesTest2() { String file1 = destinationFolder + "copyPages2_1.pdf"; String file2 = destinationFolder + "copyPages2_2.pdf"; - PdfWriter writer1 = new PdfWriter(new FileStream(file1, FileMode.Create)); - PdfDocument pdfDoc1 = new PdfDocument(writer1); + PdfDocument pdfDoc1 = new PdfDocument(new PdfWriter(file1)); for (int i = 0; i < 10; i++) { PdfPage page1 = pdfDoc1.AddNewPage(); PdfCanvas canvas = new PdfCanvas(page1); @@ -590,9 +563,8 @@ public virtual void CopyPagesTest2() { page1.Flush(); } pdfDoc1.Close(); - pdfDoc1 = new PdfDocument(new PdfReader(new FileStream(file1, FileMode.Open, FileAccess.Read))); - PdfWriter writer2 = new PdfWriter(new FileStream(file2, FileMode.Create)); - PdfDocument pdfDoc2 = new PdfDocument(writer2); + pdfDoc1 = new PdfDocument(new PdfReader(file1)); + PdfDocument pdfDoc2 = new PdfDocument(new PdfWriter(file2)); for (int i_1 = 9; i_1 >= 0; i_1--) { PdfPage page2 = pdfDoc1.GetPage(i_1 + 1).CopyTo(pdfDoc2); pdfDoc2.AddPage(page2); @@ -604,7 +576,7 @@ public virtual void CopyPagesTest2() { NUnit.Framework.Assert.AreEqual(false, reader.HasRebuiltXref(), "Rebuilt"); PdfDictionary page = pdfDocument.GetPage(1).GetPdfObject(); NUnit.Framework.Assert.IsNotNull(page.Get(PdfName.Parent)); - reader.Close(); + pdfDocument.Close(); CompareTool cmpTool = new CompareTool(); PdfDocument doc1 = new PdfDocument(new PdfReader(file1)); PdfDocument doc2 = new PdfDocument(new PdfReader(file2)); @@ -623,8 +595,7 @@ public virtual void CopyPagesTest2() { public virtual void CopyPagesTest3() { String file1 = destinationFolder + "copyPages3_1.pdf"; String file2 = destinationFolder + "copyPages3_2.pdf"; - PdfWriter writer1 = new PdfWriter(new FileStream(file1, FileMode.Create)); - PdfDocument pdfDoc1 = new PdfDocument(writer1); + PdfDocument pdfDoc1 = new PdfDocument(new PdfWriter(file1)); PdfPage page1 = pdfDoc1.AddNewPage(); PdfCanvas canvas = new PdfCanvas(page1); canvas.Rectangle(100, 600, 100, 100); @@ -637,10 +608,9 @@ public virtual void CopyPagesTest3() { canvas.Release(); page1.Flush(); pdfDoc1.Close(); - pdfDoc1 = new PdfDocument(new PdfReader(new FileStream(file1, FileMode.Open, FileAccess.Read))); + pdfDoc1 = new PdfDocument(new PdfReader(file1)); page1 = pdfDoc1.GetPage(1); - PdfWriter writer2 = new PdfWriter(new FileStream(file2, FileMode.Create)); - PdfDocument pdfDoc2 = new PdfDocument(writer2); + PdfDocument pdfDoc2 = new PdfDocument(new PdfWriter(file2)); for (int i = 0; i < 10; i++) { PdfPage page2 = page1.CopyTo(pdfDoc2); pdfDoc2.AddPage(page2); @@ -671,9 +641,7 @@ public virtual void CopyPagesTest3() { [NUnit.Framework.Test] public virtual void CopyPagesTest4() { String file1 = destinationFolder + "copyPages4_1.pdf"; - FileStream fos1 = new FileStream(file1, FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1); - PdfDocument pdfDoc1 = new PdfDocument(writer1); + PdfDocument pdfDoc1 = new PdfDocument(new PdfWriter(file1)); for (int i = 0; i < 5; i++) { PdfPage page1 = pdfDoc1.AddNewPage(); PdfCanvas canvas = new PdfCanvas(page1); @@ -687,12 +655,10 @@ public virtual void CopyPagesTest4() { canvas.Release(); } pdfDoc1.Close(); - pdfDoc1 = new PdfDocument(new PdfReader(new FileStream(file1, FileMode.Open, FileAccess.Read))); + pdfDoc1 = new PdfDocument(new PdfReader(file1)); for (int i_1 = 0; i_1 < 5; i_1++) { - FileStream fos2 = new FileStream(destinationFolder + String.Format("copyPages4_{0}.pdf", i_1 + 2), FileMode.Create - ); - PdfWriter writer2 = new PdfWriter(fos2); - PdfDocument pdfDoc2 = new PdfDocument(writer2); + PdfDocument pdfDoc2 = new PdfDocument(new PdfWriter(destinationFolder + String.Format("copyPages4_{0}.pdf" + , i_1 + 2))); PdfPage page2 = pdfDoc1.GetPage(i_1 + 1).CopyTo(pdfDoc2); pdfDoc2.AddPage(page2); pdfDoc2.Close(); @@ -719,10 +685,8 @@ public virtual void CopyPagesTest4() { public virtual void CopyPagesTest5() { int documentCount = 3; for (int i = 0; i < documentCount; i++) { - FileStream fos1 = new FileStream(destinationFolder + String.Format("copyPages5_{0}.pdf", i + 1), FileMode.Create - ); - PdfWriter writer1 = new PdfWriter(fos1); - PdfDocument pdfDoc1 = new PdfDocument(writer1); + PdfDocument pdfDoc1 = new PdfDocument(new PdfWriter(destinationFolder + String.Format("copyPages5_{0}.pdf" + , i + 1))); PdfPage page1 = pdfDoc1.AddNewPage(); PdfCanvas canvas = new PdfCanvas(page1); canvas.Rectangle(100, 600, 100, 100); @@ -737,14 +701,11 @@ public virtual void CopyPagesTest5() { } IList docs = new List(); for (int i_1 = 0; i_1 < documentCount; i_1++) { - FileStream fos1 = new FileStream(destinationFolder + String.Format("copyPages5_{0}.pdf", i_1 + 1), FileMode.Open - , FileAccess.Read); - PdfDocument pdfDoc1 = new PdfDocument(new PdfReader(fos1)); + PdfDocument pdfDoc1 = new PdfDocument(new PdfReader(destinationFolder + String.Format("copyPages5_{0}.pdf" + , i_1 + 1))); docs.Add(pdfDoc1); } - FileStream fos2 = new FileStream(destinationFolder + "copyPages5_4.pdf", FileMode.Create); - PdfWriter writer2 = new PdfWriter(fos2); - PdfDocument pdfDoc2 = new PdfDocument(writer2); + PdfDocument pdfDoc2 = new PdfDocument(new PdfWriter(destinationFolder + "copyPages5_4.pdf")); for (int i_2 = 0; i_2 < 3; i_2++) { pdfDoc2.AddPage(docs[i_2].GetPage(1).CopyTo(pdfDoc2)); } @@ -776,9 +737,7 @@ public virtual void CopyPagesTest6() { String file2 = destinationFolder + "copyPages6_2.pdf"; String file3 = destinationFolder + "copyPages6_3.pdf"; String file1_upd = destinationFolder + "copyPages6_1_upd.pdf"; - FileStream fos1 = new FileStream(file1, FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1); - PdfDocument pdfDoc1 = new PdfDocument(writer1); + PdfDocument pdfDoc1 = new PdfDocument(new PdfWriter(file1)); PdfPage page1 = pdfDoc1.AddNewPage(); PdfCanvas canvas = new PdfCanvas(page1); canvas.Rectangle(100, 600, 100, 100); @@ -790,22 +749,17 @@ public virtual void CopyPagesTest6() { canvas.EndText(); canvas.Release(); pdfDoc1.Close(); - pdfDoc1 = new PdfDocument(new PdfReader(new FileStream(file1, FileMode.Open, FileAccess.Read))); - FileStream fos2 = new FileStream(file2, FileMode.Create); - PdfWriter writer2 = new PdfWriter(fos2); - PdfDocument pdfDoc2 = new PdfDocument(writer2); + pdfDoc1 = new PdfDocument(new PdfReader(file1)); + PdfDocument pdfDoc2 = new PdfDocument(new PdfWriter(file2)); pdfDoc2.AddPage(pdfDoc1.GetPage(1).CopyTo(pdfDoc2)); pdfDoc2.Close(); - pdfDoc2 = new PdfDocument(new PdfReader(new FileStream(file2, FileMode.Open, FileAccess.Read))); - FileStream fos3 = new FileStream(file3, FileMode.Create); - PdfWriter writer3 = new PdfWriter(fos3); - PdfDocument pdfDoc3 = new PdfDocument(writer3); + pdfDoc2 = new PdfDocument(new PdfReader(file2)); + PdfDocument pdfDoc3 = new PdfDocument(new PdfWriter(file3)); pdfDoc3.AddPage(pdfDoc2.GetPage(1).CopyTo(pdfDoc3)); pdfDoc3.Close(); - pdfDoc3 = new PdfDocument(new PdfReader(new FileStream(file3, FileMode.Open, FileAccess.Read))); + pdfDoc3 = new PdfDocument(new PdfReader(file3)); pdfDoc1.Close(); - pdfDoc1 = new PdfDocument(new PdfReader(new FileStream(file1, FileMode.Open, FileAccess.Read)), new PdfWriter - (new FileStream(file1_upd, FileMode.Create))); + pdfDoc1 = new PdfDocument(new PdfReader(file1), new PdfWriter(file1_upd)); pdfDoc1.AddPage(pdfDoc3.GetPage(1).CopyTo(pdfDoc1)); pdfDoc1.Close(); pdfDoc2.Close(); @@ -841,9 +795,7 @@ public virtual void CopyPagesTest6() { [NUnit.Framework.Test] public virtual void MarkedContentTest1() { String message = ""; - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - PdfWriter writer = new PdfWriter(baos); - PdfDocument document = new PdfDocument(writer); + PdfDocument document = new PdfDocument(new PdfWriter(new ByteArrayOutputStream())); PdfPage page = document.AddNewPage(); PdfCanvas canvas = new PdfCanvas(page); canvas.BeginMarkedContent(new PdfName("Tag1")); @@ -862,9 +814,7 @@ public virtual void MarkedContentTest1() { /// [NUnit.Framework.Test] public virtual void MarkedContentTest2() { - FileStream fos = new FileStream(destinationFolder + "markedContentTest2.pdf", FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument document = new PdfDocument(writer); + PdfDocument document = new PdfDocument(new PdfWriter(destinationFolder + "markedContentTest2.pdf")); PdfPage page = document.AddNewPage(); PdfCanvas canvas = new PdfCanvas(page); Dictionary tmpMap = new Dictionary(); @@ -885,9 +835,7 @@ public virtual void MarkedContentTest2() { /// [NUnit.Framework.Test] public virtual void GraphicsStateTest1() { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - PdfWriter writer = new PdfWriter(baos); - PdfDocument document = new PdfDocument(writer); + PdfDocument document = new PdfDocument(new PdfWriter(new ByteArrayOutputStream())); PdfPage page = document.AddNewPage(); PdfCanvas canvas = new PdfCanvas(page); canvas.SetLineWidth(3); @@ -907,9 +855,7 @@ public virtual void GraphicsStateTest1() { /// [NUnit.Framework.Test] public virtual void ColorTest01() { - FileStream fos = new FileStream(destinationFolder + "colorTest01.pdf", FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument document = new PdfDocument(writer); + PdfDocument document = new PdfDocument(new PdfWriter(destinationFolder + "colorTest01.pdf")); PdfPage page = document.AddNewPage(); PdfCanvas canvas = new PdfCanvas(page); canvas.SetFillColor(DeviceRgb.RED).Rectangle(50, 500, 50, 50).Fill(); @@ -929,8 +875,7 @@ public virtual void ColorTest01() { /// [NUnit.Framework.Test] public virtual void ColorTest02() { - FileStream fos = new FileStream(destinationFolder + "colorTest02.pdf", FileMode.Create); - PdfWriter writer = new PdfWriter(fos); + PdfWriter writer = new PdfWriter(destinationFolder + "colorTest02.pdf"); writer.SetCompressionLevel(CompressionConstants.NO_COMPRESSION); PdfDocument document = new PdfDocument(writer); PdfPage page = document.AddNewPage(); @@ -961,8 +906,7 @@ public virtual void ColorTest02() { /// [NUnit.Framework.Test] public virtual void ColorTest03() { - FileStream fos = new FileStream(destinationFolder + "colorTest03.pdf", FileMode.Create); - PdfWriter writer = new PdfWriter(fos); + PdfWriter writer = new PdfWriter(destinationFolder + "colorTest03.pdf"); writer.SetCompressionLevel(CompressionConstants.NO_COMPRESSION); PdfDocument document = new PdfDocument(writer); PdfPage page = document.AddNewPage(); @@ -1012,8 +956,7 @@ public virtual void ColorTest04() { byte[] bytes = baos.ToArray(); PdfReader reader = new PdfReader(new MemoryStream(bytes)); document = new PdfDocument(reader); - FileStream fos = new FileStream(destinationFolder + "colorTest04.pdf", FileMode.Create); - writer = new PdfWriter(fos); + writer = new PdfWriter(destinationFolder + "colorTest04.pdf"); PdfDocument newDocument = new PdfDocument(writer); newDocument.AddPage(document.GetPage(1).CopyTo(newDocument)); newDocument.Close(); @@ -1025,9 +968,7 @@ public virtual void ColorTest04() { /// [NUnit.Framework.Test] public virtual void ColorTest05() { - FileStream fos = new FileStream(destinationFolder + "colorTest05.pdf", FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument document = new PdfDocument(writer); + PdfDocument document = new PdfDocument(new PdfWriter(destinationFolder + "colorTest05.pdf")); PdfPage page = document.AddNewPage(); FileStream streamGray = new FileStream(sourceFolder + "BlackWhite.icc", FileMode.Open, FileAccess.Read); FileStream streamRgb = new FileStream(sourceFolder + "CIERGB.icc", FileMode.Open, FileAccess.Read); @@ -1059,8 +1000,7 @@ public virtual void ColorTest06() { bytes[k++] = (byte)i; bytes[k++] = (byte)i; } - FileStream fos = new FileStream(destinationFolder + "colorTest06.pdf", FileMode.Create); - PdfWriter writer = new PdfWriter(fos); + PdfWriter writer = new PdfWriter(destinationFolder + "colorTest06.pdf"); writer.SetCompressionLevel(CompressionConstants.NO_COMPRESSION); PdfDocument document = new PdfDocument(writer); PdfPage page = document.AddNewPage(); @@ -1079,13 +1019,12 @@ public virtual void ColorTest06() { /// [NUnit.Framework.Test] public virtual void ColorTest07() { - FileStream fos = new FileStream(destinationFolder + "colorTest07.pdf", FileMode.Create); - PdfWriter writer = new PdfWriter(fos); + PdfWriter writer = new PdfWriter(destinationFolder + "colorTest07.pdf"); writer.SetCompressionLevel(CompressionConstants.NO_COMPRESSION); PdfDocument document = new PdfDocument(writer); PdfPage page = document.AddNewPage(); PdfFunction.Type4 function = new PdfFunction.Type4(new PdfArray(new float[] { 0, 1 }), new PdfArray(new float - [] { 0, 1, 0, 1, 0, 1 }), "{0 0}".GetBytes()); + [] { 0, 1, 0, 1, 0, 1 }), "{0 0}".GetBytes(iText.IO.Util.EncodingUtil.ISO_8859_1)); PdfSpecialCs.Separation separation = new PdfSpecialCs.Separation("MyRed", new PdfDeviceCs.Rgb(), function); PdfCanvas canvas = new PdfCanvas(page); canvas.SetFillColor(new Separation(separation, 0.25f)).Rectangle(50, 500, 50, 50).Fill(); @@ -1100,13 +1039,12 @@ public virtual void ColorTest07() { /// [NUnit.Framework.Test] public virtual void ColorTest08() { - FileStream fos = new FileStream(destinationFolder + "colorTest08.pdf", FileMode.Create); - PdfWriter writer = new PdfWriter(fos); + PdfWriter writer = new PdfWriter(destinationFolder + "colorTest08.pdf"); writer.SetCompressionLevel(CompressionConstants.NO_COMPRESSION); PdfDocument document = new PdfDocument(writer); PdfPage page = document.AddNewPage(); PdfFunction.Type4 function = new PdfFunction.Type4(new PdfArray(new float[] { 0, 1, 0, 1 }), new PdfArray( - new float[] { 0, 1, 0, 1, 0, 1 }), "{0}".GetBytes()); + new float[] { 0, 1, 0, 1, 0, 1 }), "{0}".GetBytes(iText.IO.Util.EncodingUtil.ISO_8859_1)); List tmpArray = new List(2); tmpArray.Add("MyRed"); tmpArray.Add("MyGreen"); @@ -1125,9 +1063,7 @@ public virtual void ColorTest08() { /// [NUnit.Framework.Test] public virtual void WmfImageTest01() { - FileStream fos = new FileStream(destinationFolder + "wmfImageTest01.pdf", FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument document = new PdfDocument(writer); + PdfDocument document = new PdfDocument(new PdfWriter(destinationFolder + "wmfImageTest01.pdf")); PdfPage page = document.AddNewPage(); PdfCanvas canvas = new PdfCanvas(page); ImageData img = new WmfImageData(sourceFolder + "example.wmf"); @@ -1141,9 +1077,7 @@ public virtual void WmfImageTest01() { /// [NUnit.Framework.Test] public virtual void WmfImageTest02() { - FileStream fos = new FileStream(destinationFolder + "wmfImageTest02.pdf", FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument document = new PdfDocument(writer); + PdfDocument document = new PdfDocument(new PdfWriter(destinationFolder + "wmfImageTest02.pdf")); PdfPage page = document.AddNewPage(); PdfCanvas canvas = new PdfCanvas(page); ImageData img = new WmfImageData(sourceFolder + "butterfly.wmf"); @@ -1157,9 +1091,7 @@ public virtual void WmfImageTest02() { /// [NUnit.Framework.Test] public virtual void WmfImageTest03() { - FileStream fos = new FileStream(destinationFolder + "wmfImageTest03.pdf", FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument document = new PdfDocument(writer); + PdfDocument document = new PdfDocument(new PdfWriter(destinationFolder + "wmfImageTest03.pdf")); PdfPage page = document.AddNewPage(); PdfCanvas canvas = new PdfCanvas(page); ImageData img = new WmfImageData(sourceFolder + "type1.wmf"); @@ -1173,9 +1105,7 @@ public virtual void WmfImageTest03() { /// [NUnit.Framework.Test] public virtual void WmfImageTest04() { - FileStream fos = new FileStream(destinationFolder + "wmfImageTest04.pdf", FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument document = new PdfDocument(writer); + PdfDocument document = new PdfDocument(new PdfWriter(destinationFolder + "wmfImageTest04.pdf")); PdfPage page = document.AddNewPage(); PdfCanvas canvas = new PdfCanvas(page); ImageData img = new WmfImageData(sourceFolder + "type0.wmf"); @@ -1189,9 +1119,7 @@ public virtual void WmfImageTest04() { /// [NUnit.Framework.Test] public virtual void GifImageTest01() { - FileStream fos = new FileStream(destinationFolder + "gifImageTest01.pdf", FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument document = new PdfDocument(writer); + PdfDocument document = new PdfDocument(new PdfWriter(destinationFolder + "gifImageTest01.pdf")); PdfPage page = document.AddNewPage(); PdfCanvas canvas = new PdfCanvas(page); ImageData img = ImageDataFactory.Create(sourceFolder + "2-frames.gif"); @@ -1205,9 +1133,7 @@ public virtual void GifImageTest01() { /// [NUnit.Framework.Test] public virtual void GifImageTest02() { - FileStream fos = new FileStream(destinationFolder + "gifImageTest02.pdf", FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument document = new PdfDocument(writer); + PdfDocument document = new PdfDocument(new PdfWriter(destinationFolder + "gifImageTest02.pdf")); PdfPage page = document.AddNewPage(); Stream @is = new FileStream(sourceFolder + "2-frames.gif", FileMode.Open, FileAccess.Read); ByteArrayOutputStream baos = new ByteArrayOutputStream(); @@ -1228,9 +1154,7 @@ public virtual void GifImageTest02() { /// [NUnit.Framework.Test] public virtual void GifImageTest03() { - FileStream fos = new FileStream(destinationFolder + "gifImageTest03.pdf", FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument document = new PdfDocument(writer); + PdfDocument document = new PdfDocument(new PdfWriter(destinationFolder + "gifImageTest03.pdf")); PdfPage page = document.AddNewPage(); Stream @is = new FileStream(sourceFolder + "2-frames.gif", FileMode.Open, FileAccess.Read); ByteArrayOutputStream baos = new ByteArrayOutputStream(); @@ -1251,9 +1175,7 @@ public virtual void GifImageTest03() { /// [NUnit.Framework.Test] public virtual void GifImageTest04() { - FileStream fos = new FileStream(destinationFolder + "gifImageTest04.pdf", FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument document = new PdfDocument(writer); + PdfDocument document = new PdfDocument(new PdfWriter(destinationFolder + "gifImageTest04.pdf")); PdfPage page = document.AddNewPage(); Stream @is = new FileStream(sourceFolder + "2-frames.gif", FileMode.Open, FileAccess.Read); ByteArrayOutputStream baos = new ByteArrayOutputStream(); @@ -1275,9 +1197,7 @@ public virtual void GifImageTest04() { /// [NUnit.Framework.Test] public virtual void GifImageTest05() { - FileStream fos = new FileStream(destinationFolder + "gifImageTest05.pdf", FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument document = new PdfDocument(writer); + PdfDocument document = new PdfDocument(new PdfWriter(destinationFolder + "gifImageTest05.pdf")); PdfPage page = document.AddNewPage(); Stream @is = new FileStream(sourceFolder + "animated_fox_dog.gif", FileMode.Open, FileAccess.Read); ByteArrayOutputStream baos = new ByteArrayOutputStream(); @@ -1318,7 +1238,7 @@ public virtual void GifImageTest05() { /*@Test public void ccittImageTest01() throws IOException, InterruptedException { String filename = "ccittImage01.pdf"; - PdfWriter writer = new PdfWriter(new FileOutputStream(destinationFolder + filename)); + PdfWriter writer = new PdfWriter(destinationFolder + filename); PdfDocument document = new PdfDocument(writer); PdfPage page = document.addNewPage(); @@ -1351,8 +1271,7 @@ public void ccittImageTest01() throws IOException, InterruptedException { [LogMessage(LogMessageConstant.IMAGE_SIZE_CANNOT_BE_MORE_4KB)] public virtual void InlineImagesTest01() { String filename = "inlineImages01.pdf"; - PdfWriter writer = new PdfWriter(new FileStream(destinationFolder + filename, FileMode.Create)); - PdfDocument document = new PdfDocument(writer); + PdfDocument document = new PdfDocument(new PdfWriter(destinationFolder + filename)); PdfPage page = document.AddNewPage(); PdfCanvas canvas = new PdfCanvas(page); canvas.AddImage(ImageDataFactory.Create(sourceFolder + "Desert.jpg"), 36, 700, 100, true); @@ -1376,8 +1295,7 @@ public virtual void InlineImagesTest01() { [LogMessage(LogMessageConstant.IMAGE_SIZE_CANNOT_BE_MORE_4KB)] public virtual void InlineImagesTest02() { String filename = "inlineImages02.pdf"; - PdfWriter writer = new PdfWriter(new FileStream(destinationFolder + filename, FileMode.Create)); - PdfDocument document = new PdfDocument(writer); + PdfDocument document = new PdfDocument(new PdfWriter(destinationFolder + filename)); PdfPage page = document.AddNewPage(); PdfCanvas canvas = new PdfCanvas(page); Stream stream = UrlUtil.OpenStream(UrlUtil.ToURL(sourceFolder + "Desert.jpg")); diff --git a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfCopyTest.cs b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfCopyTest.cs index cf530c032e..da46300169 100644 --- a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfCopyTest.cs +++ b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfCopyTest.cs @@ -1,5 +1,4 @@ using System; -using System.IO; using iText.IO; using iText.IO.Source; using iText.Kernel.Utils; @@ -23,11 +22,8 @@ public static void BeforeClass() { [LogMessage(LogMessageConstant.SOURCE_DOCUMENT_HAS_ACROFORM_DICTIONARY)] [LogMessage(LogMessageConstant.MAKE_COPY_OF_CATALOG_DICTIONARY_IS_FORBIDDEN)] public virtual void CopySignedDocuments() { - FileStream fis1 = new FileStream(sourceFolder + "hello_signed.pdf", FileMode.Open, FileAccess.Read); - PdfReader reader1 = new PdfReader(fis1); - PdfDocument pdfDoc1 = new PdfDocument(reader1); - FileStream fos2 = new FileStream(destinationFolder + "copySignedDocuments.pdf", FileMode.Create); - PdfDocument pdfDoc2 = new PdfDocument(new PdfWriter(fos2)); + PdfDocument pdfDoc1 = new PdfDocument(new PdfReader(sourceFolder + "hello_signed.pdf")); + PdfDocument pdfDoc2 = new PdfDocument(new PdfWriter(destinationFolder + "copySignedDocuments.pdf")); pdfDoc1.CopyPagesTo(1, 1, pdfDoc2); pdfDoc2.Close(); pdfDoc1.Close(); @@ -41,21 +37,15 @@ public virtual void CopySignedDocuments() { /// [NUnit.Framework.Test] public virtual void Copying1() { - FileStream fos1 = new FileStream(destinationFolder + "copying1_1.pdf", FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1); - PdfDocument pdfDoc1 = new PdfDocument(writer1); + PdfDocument pdfDoc1 = new PdfDocument(new PdfWriter(destinationFolder + "copying1_1.pdf")); pdfDoc1.GetDocumentInfo().SetAuthor("Alexander Chingarev").SetCreator("iText 6").SetTitle("Empty iText 6 Document" ); pdfDoc1.GetCatalog().Put(new PdfName("a"), ((PdfName)new PdfName("b").MakeIndirect(pdfDoc1))); PdfPage page1 = pdfDoc1.AddNewPage(); page1.Flush(); pdfDoc1.Close(); - FileStream fis1 = new FileStream(destinationFolder + "copying1_1.pdf", FileMode.Open, FileAccess.Read); - PdfReader reader1 = new PdfReader(fis1); - pdfDoc1 = new PdfDocument(reader1); - FileStream fos2 = new FileStream(destinationFolder + "copying1_2.pdf", FileMode.Create); - PdfWriter writer2 = new PdfWriter(fos2); - PdfDocument pdfDoc2 = new PdfDocument(writer2); + pdfDoc1 = new PdfDocument(new PdfReader(destinationFolder + "copying1_1.pdf")); + PdfDocument pdfDoc2 = new PdfDocument(new PdfWriter(destinationFolder + "copying1_2.pdf")); pdfDoc2.AddNewPage(); pdfDoc2.GetDocumentInfo().GetPdfObject().Put(new PdfName("a"), pdfDoc1.GetCatalog().GetPdfObject().Get(new PdfName("a")).CopyTo(pdfDoc2)); @@ -68,15 +58,13 @@ public virtual void Copying1() { PdfDictionary info = trailer.GetAsDictionary(PdfName.Info); PdfName b = info.GetAsName(new PdfName("a")); NUnit.Framework.Assert.AreEqual("/b", b.ToString()); - reader.Close(); + pdfDocument.Close(); } /// [NUnit.Framework.Test] public virtual void Copying2() { - FileStream fos1 = new FileStream(destinationFolder + "copying2_1.pdf", FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1); - PdfDocument pdfDoc1 = new PdfDocument(writer1); + PdfDocument pdfDoc1 = new PdfDocument(new PdfWriter(destinationFolder + "copying2_1.pdf")); for (int i = 0; i < 10; i++) { PdfPage page1 = pdfDoc1.AddNewPage(); page1.GetContentStream(0).GetOutputStream().Write(ByteUtils.GetIsoBytes("%page " + (i + 1).ToString() + "\n" @@ -84,12 +72,8 @@ public virtual void Copying2() { page1.Flush(); } pdfDoc1.Close(); - FileStream fis1 = new FileStream(destinationFolder + "copying2_1.pdf", FileMode.Open, FileAccess.Read); - PdfReader reader1 = new PdfReader(fis1); - pdfDoc1 = new PdfDocument(reader1); - FileStream fos2 = new FileStream(destinationFolder + "copying2_2.pdf", FileMode.Create); - PdfWriter writer2 = new PdfWriter(fos2); - PdfDocument pdfDoc2 = new PdfDocument(writer2); + pdfDoc1 = new PdfDocument(new PdfReader(destinationFolder + "copying2_1.pdf")); + PdfDocument pdfDoc2 = new PdfDocument(new PdfWriter(destinationFolder + "copying2_2.pdf")); for (int i_1 = 0; i_1 < 10; i_1++) { if (i_1 % 2 == 0) { pdfDoc2.AddPage(pdfDoc1.GetPage(i_1 + 1).CopyTo(pdfDoc2)); @@ -105,15 +89,13 @@ public virtual void Copying2() { NUnit.Framework.Assert.AreEqual("%page " + (i_2 * 2 + 1).ToString() + "\n", iText.IO.Util.JavaUtil.GetStringForBytes (bytes)); } - reader.Close(); + pdfDocument.Close(); } /// [NUnit.Framework.Test] public virtual void Copying3() { - FileStream fos = new FileStream(destinationFolder + "copying3_1.pdf", FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(destinationFolder + "copying3_1.pdf")); PdfDictionary helloWorld = ((PdfDictionary)new PdfDictionary().MakeIndirect(pdfDoc)); PdfDictionary helloWorld1 = ((PdfDictionary)new PdfDictionary().MakeIndirect(pdfDoc)); helloWorld.Put(new PdfName("Hello"), new PdfString("World")); @@ -152,7 +134,7 @@ public virtual void Copying3() { GetGenNumber()); NUnit.Framework.Assert.AreEqual(dic12.GetIndirectReference().GetObjNumber(), 5); NUnit.Framework.Assert.AreEqual(dic12.GetIndirectReference().GetGenNumber(), 0); - reader.Close(); + pdfDoc.Close(); } /// @@ -161,16 +143,30 @@ public virtual void Copying3() { [LogMessage(LogMessageConstant.SOURCE_DOCUMENT_HAS_ACROFORM_DICTIONARY)] public virtual void CopyDocumentsWithFormFieldsTest() { String filename = sourceFolder + "fieldsOn2-sPage.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); - FileStream fos = new FileStream(destinationFolder + "copyDocumentsWithFormFields.pdf", FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument sourceDoc = new PdfDocument(reader); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument sourceDoc = new PdfDocument(new PdfReader(filename)); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(destinationFolder + "copyDocumentsWithFormFields.pdf")); sourceDoc.InitializeOutlines(); sourceDoc.CopyPagesTo(1, sourceDoc.GetNumberOfPages(), pdfDoc); + sourceDoc.Close(); pdfDoc.Close(); NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(destinationFolder + "copyDocumentsWithFormFields.pdf" , sourceFolder + "cmp_copyDocumentsWithFormFields.pdf", destinationFolder, "diff_")); } + + /// + /// + [NUnit.Framework.Test] + public virtual void CopySamePageWithAnnotationsSeveralTimes() { + String filename = sourceFolder + "rotated_annotation.pdf"; + PdfDocument sourceDoc = new PdfDocument(new PdfReader(filename)); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(destinationFolder + "copySamePageWithAnnotationsSeveralTimes.pdf" + )); + sourceDoc.InitializeOutlines(); + sourceDoc.CopyPagesTo(iText.IO.Util.JavaUtil.ArraysAsList(1, 1, 1), pdfDoc); + sourceDoc.Close(); + pdfDoc.Close(); + NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(destinationFolder + "copySamePageWithAnnotationsSeveralTimes.pdf" + , sourceFolder + "cmp_copySamePageWithAnnotationsSeveralTimes.pdf", destinationFolder, "diff_")); + } } } diff --git a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfDictionaryTest.cs b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfDictionaryTest.cs new file mode 100644 index 0000000000..236235a866 --- /dev/null +++ b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfDictionaryTest.cs @@ -0,0 +1,154 @@ +using System; +using System.Collections.Generic; +using iText.IO.Source; + +namespace iText.Kernel.Pdf { + public class PdfDictionaryTest { + [NUnit.Framework.Test] + public virtual void TestEntrySet() { + PdfDocument doc = new PdfDocument(new PdfWriter(new ByteArrayOutputStream())); + PdfDictionary dict = new PdfDictionary(); + dict.Put(new PdfName("1"), ((PdfNumber)new PdfNumber(1).MakeIndirect(doc)).GetIndirectReference()); + dict.Put(new PdfName("2"), ((PdfNumber)new PdfNumber(2).MakeIndirect(doc)).GetIndirectReference()); + dict.Put(new PdfName("3"), ((PdfNumber)new PdfNumber(3).MakeIndirect(doc))); + dict.Put(new PdfName("4"), ((PdfNumber)new PdfNumber(4).MakeIndirect(doc))); + dict.Put(new PdfName("5"), new PdfNumber(5)); + dict.Put(new PdfName("6"), new PdfNumber(6)); + IList nums = new List(iText.IO.Util.JavaUtil.ArraysAsList(1, 2, 3, 4, 5, 6)); + foreach (KeyValuePair e in dict.EntrySet()) { + NUnit.Framework.Assert.AreEqual(e.Key.ToString(), "/" + e.Value); + if (!nums.Remove(((PdfNumber)e.Value).IntValue())) { + NUnit.Framework.Assert.Fail("Element not found"); + } + } + } + + [NUnit.Framework.Test] + public virtual void TestEntrySetContains() { + PdfDocument doc = new PdfDocument(new PdfWriter(new ByteArrayOutputStream())); + PdfDictionary dict = new PdfDictionary(); + dict.Put(new PdfName("1"), ((PdfNumber)new PdfNumber(1).MakeIndirect(doc)).GetIndirectReference()); + dict.Put(new PdfName("2"), ((PdfNumber)new PdfNumber(2).MakeIndirect(doc)).GetIndirectReference()); + dict.Put(new PdfName("3"), ((PdfNumber)new PdfNumber(3).MakeIndirect(doc))); + dict.Put(new PdfName("4"), ((PdfNumber)new PdfNumber(4).MakeIndirect(doc))); + dict.Put(new PdfName("5"), new PdfNumber(5)); + dict.Put(new PdfName("6"), new PdfNumber(6)); + foreach (KeyValuePair e in dict.EntrySet()) { + NUnit.Framework.Assert.IsTrue(dict.EntrySet().Contains(e)); + } + } + + [NUnit.Framework.Test] + public virtual void TestEntrySetRemove() { + PdfDocument doc = new PdfDocument(new PdfWriter(new ByteArrayOutputStream())); + PdfDictionary dict = new PdfDictionary(); + dict.Put(new PdfName("1"), ((PdfNumber)new PdfNumber(1).MakeIndirect(doc)).GetIndirectReference()); + dict.Put(new PdfName("2"), ((PdfNumber)new PdfNumber(2).MakeIndirect(doc)).GetIndirectReference()); + dict.Put(new PdfName("3"), ((PdfNumber)new PdfNumber(3).MakeIndirect(doc))); + dict.Put(new PdfName("4"), ((PdfNumber)new PdfNumber(4).MakeIndirect(doc))); + dict.Put(new PdfName("5"), new PdfNumber(5)); + dict.Put(new PdfName("6"), new PdfNumber(6)); + IList> toRemove = new List>(); + foreach (KeyValuePair e in dict.EntrySet()) { + toRemove.Add(e); + } + foreach (KeyValuePair e_1 in toRemove) { + NUnit.Framework.Assert.IsTrue(dict.EntrySet().Remove(e_1)); + } + NUnit.Framework.Assert.AreEqual(0, dict.EntrySet().Count); + NUnit.Framework.Assert.AreEqual(0, dict.Values().Count); + NUnit.Framework.Assert.AreEqual(0, dict.Size()); + } + + [NUnit.Framework.Test] + public virtual void TestEntrySetRemove2() { + PdfDocument doc = new PdfDocument(new PdfWriter(new ByteArrayOutputStream())); + PdfDictionary dict = new PdfDictionary(); + dict.Put(new PdfName("1"), ((PdfNumber)new PdfNumber(1).MakeIndirect(doc)).GetIndirectReference()); + dict.Put(new PdfName("2"), ((PdfNumber)new PdfNumber(2).MakeIndirect(doc)).GetIndirectReference()); + dict.Put(new PdfName("3"), ((PdfNumber)new PdfNumber(3).MakeIndirect(doc))); + dict.Put(new PdfName("4"), ((PdfNumber)new PdfNumber(4).MakeIndirect(doc))); + dict.Put(new PdfName("5"), new PdfNumber(5)); + dict.Put(new PdfName("6"), new PdfNumber(6)); + PdfDictionary dict2 = new PdfDictionary(); + dict2.Put(new PdfName("1"), ((PdfNumber)new PdfNumber(1).MakeIndirect(doc)).GetIndirectReference()); + dict2.Put(new PdfName("2"), ((PdfNumber)new PdfNumber(2).MakeIndirect(doc)).GetIndirectReference()); + dict2.Put(new PdfName("3"), ((PdfNumber)new PdfNumber(3).MakeIndirect(doc))); + dict2.Put(new PdfName("4"), ((PdfNumber)new PdfNumber(4).MakeIndirect(doc))); + dict2.Put(new PdfName("5"), new PdfNumber(5)); + dict2.Put(new PdfName("6"), new PdfNumber(6)); + foreach (KeyValuePair e in dict2.EntrySet()) { + NUnit.Framework.Assert.IsTrue(dict.EntrySet().Remove(e)); + } + NUnit.Framework.Assert.AreEqual(0, dict.EntrySet().Count); + NUnit.Framework.Assert.AreEqual(0, dict.Values().Count); + NUnit.Framework.Assert.AreEqual(0, dict.Size()); + } + + [NUnit.Framework.Test] + public virtual void TestEntrySetClear() { + PdfDocument doc = new PdfDocument(new PdfWriter(new ByteArrayOutputStream())); + PdfDictionary dict = new PdfDictionary(); + dict.Put(new PdfName("1"), ((PdfNumber)new PdfNumber(1).MakeIndirect(doc)).GetIndirectReference()); + dict.Put(new PdfName("2"), ((PdfNumber)new PdfNumber(2).MakeIndirect(doc)).GetIndirectReference()); + dict.Put(new PdfName("3"), ((PdfNumber)new PdfNumber(3).MakeIndirect(doc))); + dict.Put(new PdfName("4"), ((PdfNumber)new PdfNumber(4).MakeIndirect(doc))); + dict.Put(new PdfName("5"), new PdfNumber(5)); + dict.Put(new PdfName("6"), new PdfNumber(6)); + dict.EntrySet().Clear(); + NUnit.Framework.Assert.AreEqual(0, dict.EntrySet().Count); + NUnit.Framework.Assert.AreEqual(0, dict.Values().Count); + NUnit.Framework.Assert.AreEqual(0, dict.Size()); + } + + [NUnit.Framework.Test] + public virtual void TestValues() { + PdfDocument doc = new PdfDocument(new PdfWriter(new ByteArrayOutputStream())); + PdfDictionary dict = new PdfDictionary(); + dict.Put(new PdfName("1"), ((PdfNumber)new PdfNumber(1).MakeIndirect(doc)).GetIndirectReference()); + dict.Put(new PdfName("2"), ((PdfNumber)new PdfNumber(2).MakeIndirect(doc)).GetIndirectReference()); + dict.Put(new PdfName("3"), ((PdfNumber)new PdfNumber(3).MakeIndirect(doc))); + dict.Put(new PdfName("4"), ((PdfNumber)new PdfNumber(4).MakeIndirect(doc))); + dict.Put(new PdfName("5"), new PdfNumber(5)); + dict.Put(new PdfName("6"), new PdfNumber(6)); + IList nums = new List(iText.IO.Util.JavaUtil.ArraysAsList(1, 2, 3, 4, 5, 6)); + foreach (KeyValuePair e in dict.EntrySet()) { + NUnit.Framework.Assert.AreEqual(e.Key.ToString(), "/" + e.Value); + if (!nums.Remove(((PdfNumber)e.Value).IntValue())) { + NUnit.Framework.Assert.Fail("Element not found"); + } + } + } + + [NUnit.Framework.Test] + public virtual void TestValuesContains() { + PdfDocument doc = new PdfDocument(new PdfWriter(new ByteArrayOutputStream())); + PdfDictionary dict = new PdfDictionary(); + dict.Put(new PdfName("1"), ((PdfNumber)new PdfNumber(1).MakeIndirect(doc)).GetIndirectReference()); + dict.Put(new PdfName("2"), ((PdfNumber)new PdfNumber(2).MakeIndirect(doc)).GetIndirectReference()); + dict.Put(new PdfName("3"), ((PdfNumber)new PdfNumber(3).MakeIndirect(doc))); + dict.Put(new PdfName("4"), ((PdfNumber)new PdfNumber(4).MakeIndirect(doc))); + dict.Put(new PdfName("5"), new PdfNumber(5)); + dict.Put(new PdfName("6"), new PdfNumber(6)); + foreach (PdfObject v in dict.Values()) { + NUnit.Framework.Assert.IsTrue(dict.Values().Contains(v)); + } + } + + [NUnit.Framework.Test] + public virtual void TestValuesIndirectContains() { + PdfDocument doc = new PdfDocument(new PdfWriter(new ByteArrayOutputStream())); + PdfDictionary dict = new PdfDictionary(); + dict.Put(new PdfName("1"), ((PdfNumber)new PdfNumber(1).MakeIndirect(doc)).GetIndirectReference()); + dict.Put(new PdfName("2"), ((PdfNumber)new PdfNumber(2).MakeIndirect(doc)).GetIndirectReference()); + dict.Put(new PdfName("3"), ((PdfNumber)new PdfNumber(3).MakeIndirect(doc))); + dict.Put(new PdfName("4"), ((PdfNumber)new PdfNumber(4).MakeIndirect(doc))); + dict.Put(new PdfName("5"), new PdfNumber(5)); + dict.Put(new PdfName("6"), new PdfNumber(6)); + NUnit.Framework.Assert.IsTrue(dict.Values().Contains(dict.Get(new PdfName("1"), false))); + NUnit.Framework.Assert.IsTrue(dict.Values().Contains(dict.Get(new PdfName("2"), false))); + NUnit.Framework.Assert.IsTrue(dict.Values().Contains(dict.Get(new PdfName("3")).GetIndirectReference())); + NUnit.Framework.Assert.IsTrue(dict.Values().Contains(dict.Get(new PdfName("4")).GetIndirectReference())); + } + } +} 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 501b3d2924..13bb1f18dd 100644 --- a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfDocumentTest.cs +++ b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfDocumentTest.cs @@ -39,12 +39,9 @@ public virtual void WritingVersionTest01() { /// [NUnit.Framework.Test] public virtual void AddOutlinesWithNamedDestinations01() { - PdfReader reader = new PdfReader(new FileStream(sourceFolder + "iphone_user_guide.pdf", FileMode.Open, FileAccess.Read - )); String filename = destinationFolder + "outlinesWithNamedDestinations01.pdf"; - FileStream fos = new FileStream(filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument pdfDoc = new PdfDocument(reader, writer); + PdfDocument pdfDoc = new PdfDocument(new PdfReader(sourceFolder + "iphone_user_guide.pdf"), new PdfWriter( + filename)); PdfArray array1 = new PdfArray(); array1.Add(pdfDoc.GetPage(2).GetPdfObject()); array1.Add(PdfName.XYZ); @@ -94,8 +91,7 @@ public virtual void FreeReferencesInObjectStream() { [NUnit.Framework.Test] public virtual void RemoveUnusedObjectsInWriterModeTest() { String filename = "removeUnusedObjectsInWriter.pdf"; - PdfWriter writer = new PdfWriter(new FileStream(destinationFolder + filename, FileMode.Create)); - PdfDocument pdfDocument = new PdfDocument(writer); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(destinationFolder + filename)); pdfDocument.AddNewPage(); PdfDictionary unusedDictionary = new PdfDictionary(); PdfArray unusedArray = ((PdfArray)new PdfArray().MakeIndirect(pdfDocument)); @@ -105,8 +101,7 @@ public virtual void RemoveUnusedObjectsInWriterModeTest() { NUnit.Framework.Assert.AreEqual(pdfDocument.GetXref().Size(), 8); //on closing, all unused objects shall not be written to resultant document pdfDocument.Close(); - PdfReader testerReader = new PdfReader(destinationFolder + filename); - PdfDocument testerDocument = new PdfDocument(testerReader); + PdfDocument testerDocument = new PdfDocument(new PdfReader(destinationFolder + filename)); NUnit.Framework.Assert.AreEqual(testerDocument.GetXref().Size(), 6); testerDocument.Close(); } @@ -117,8 +112,7 @@ public virtual void RemoveUnusedObjectsInWriterModeTest() { public virtual void RemoveUnusedObjectsInStampingModeTest() { String filenameIn = "docWithUnusedObjects_1.pdf"; String filenameOut = "removeUnusedObjectsInStamping.pdf"; - PdfWriter writer = new PdfWriter(new FileStream(destinationFolder + filenameIn, FileMode.Create)); - PdfDocument pdfDocument = new PdfDocument(writer); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(destinationFolder + filenameIn)); pdfDocument.AddNewPage(); PdfDictionary unusedDictionary = new PdfDictionary(); PdfArray unusedArray = ((PdfArray)new PdfArray().MakeIndirect(pdfDocument)); @@ -126,14 +120,12 @@ public virtual void RemoveUnusedObjectsInStampingModeTest() { unusedDictionary.Put(new PdfName("testName"), unusedArray); ((PdfDictionary)unusedDictionary.MakeIndirect(pdfDocument)).Flush(); pdfDocument.Close(); - PdfReader reader = new PdfReader(destinationFolder + filenameIn); - PdfDocument doc = new PdfDocument(reader, new PdfWriter(new FileStream(destinationFolder + filenameOut, FileMode.Create - ))); + PdfDocument doc = new PdfDocument(new PdfReader(destinationFolder + filenameIn), new PdfWriter(destinationFolder + + filenameOut)); NUnit.Framework.Assert.AreEqual(doc.GetXref().Size(), 8); //on closing, all unused objects shall not be written to resultant document doc.Close(); - PdfReader testerReader = new PdfReader(destinationFolder + filenameOut); - PdfDocument testerDocument = new PdfDocument(testerReader); + PdfDocument testerDocument = new PdfDocument(new PdfReader(destinationFolder + filenameOut)); NUnit.Framework.Assert.AreEqual(testerDocument.GetXref().Size(), 6); testerDocument.Close(); } @@ -143,8 +135,7 @@ public virtual void RemoveUnusedObjectsInStampingModeTest() { [NUnit.Framework.Test] public virtual void AddUnusedObjectsInWriterModeTest() { String filename = "addUnusedObjectsInWriter.pdf"; - PdfWriter writer = new PdfWriter(new FileStream(destinationFolder + filename, FileMode.Create)); - PdfDocument pdfDocument = new PdfDocument(writer); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(destinationFolder + filename)); pdfDocument.AddNewPage(); PdfDictionary unusedDictionary = new PdfDictionary(); PdfArray unusedArray = ((PdfArray)new PdfArray().MakeIndirect(pdfDocument)); @@ -154,8 +145,7 @@ public virtual void AddUnusedObjectsInWriterModeTest() { NUnit.Framework.Assert.AreEqual(pdfDocument.GetXref().Size(), 8); pdfDocument.SetFlushUnusedObjects(true); pdfDocument.Close(); - PdfReader testerReader = new PdfReader(destinationFolder + filename); - PdfDocument testerDocument = new PdfDocument(testerReader); + PdfDocument testerDocument = new PdfDocument(new PdfReader(destinationFolder + filename)); NUnit.Framework.Assert.AreEqual(testerDocument.GetXref().Size(), 8); testerDocument.Close(); } @@ -166,8 +156,7 @@ public virtual void AddUnusedObjectsInWriterModeTest() { public virtual void AddUnusedObjectsInStampingModeTest() { String filenameIn = "docWithUnusedObjects_2.pdf"; String filenameOut = "addUnusedObjectsInStamping.pdf"; - PdfWriter writer = new PdfWriter(new FileStream(destinationFolder + filenameIn, FileMode.Create)); - PdfDocument pdfDocument = new PdfDocument(writer); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(destinationFolder + filenameIn)); pdfDocument.AddNewPage(); PdfDictionary unusedDictionary = new PdfDictionary(); PdfArray unusedArray = ((PdfArray)new PdfArray().MakeIndirect(pdfDocument)); @@ -175,14 +164,12 @@ public virtual void AddUnusedObjectsInStampingModeTest() { unusedDictionary.Put(new PdfName("testName"), unusedArray); ((PdfDictionary)unusedDictionary.MakeIndirect(pdfDocument)).Flush(); pdfDocument.Close(); - PdfReader reader = new PdfReader(destinationFolder + filenameIn); - PdfDocument doc = new PdfDocument(reader, new PdfWriter(new FileStream(destinationFolder + filenameOut, FileMode.Create - ))); + PdfDocument doc = new PdfDocument(new PdfReader(destinationFolder + filenameIn), new PdfWriter(destinationFolder + + filenameOut)); NUnit.Framework.Assert.AreEqual(doc.GetXref().Size(), 8); doc.SetFlushUnusedObjects(true); doc.Close(); - PdfReader testerReader = new PdfReader(destinationFolder + filenameOut); - PdfDocument testerDocument = new PdfDocument(testerReader); + PdfDocument testerDocument = new PdfDocument(new PdfReader(destinationFolder + filenameOut)); NUnit.Framework.Assert.AreEqual(testerDocument.GetXref().Size(), 8); testerDocument.Close(); } @@ -192,8 +179,7 @@ public virtual void AddUnusedObjectsInStampingModeTest() { [NUnit.Framework.Test] public virtual void AddUnusedStreamObjectsTest() { String filenameIn = "docWithUnusedObjects_3.pdf"; - PdfWriter writer = new PdfWriter(new FileStream(destinationFolder + filenameIn, FileMode.Create)); - PdfDocument pdfDocument = new PdfDocument(writer); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(destinationFolder + filenameIn)); pdfDocument.AddNewPage(); PdfDictionary unusedDictionary = new PdfDictionary(); PdfArray unusedArray = ((PdfArray)new PdfArray().MakeIndirect(pdfDocument)); @@ -204,8 +190,7 @@ public virtual void AddUnusedStreamObjectsTest() { ((PdfDictionary)unusedDictionary.MakeIndirect(pdfDocument)).Flush(); pdfDocument.SetFlushUnusedObjects(true); pdfDocument.Close(); - PdfReader testerReader = new PdfReader(destinationFolder + filenameIn); - PdfDocument testerDocument = new PdfDocument(testerReader); + PdfDocument testerDocument = new PdfDocument(new PdfReader(destinationFolder + filenameIn)); NUnit.Framework.Assert.AreEqual(testerDocument.GetXref().Size(), 9); testerDocument.Close(); } @@ -249,11 +234,10 @@ public virtual void TestFreeReference() { /// [NUnit.Framework.Test] public virtual void CheckAndResolveCircularReferences() { - PdfReader pdfReader = new PdfReader(sourceFolder + "datasheet.pdf"); - PdfDocument pdfDocument = new PdfDocument(pdfReader, new PdfWriter(destinationFolder + "datasheet_mode.pdf" - )); + PdfDocument pdfDocument = new PdfDocument(new PdfReader(sourceFolder + "datasheet.pdf"), new PdfWriter(destinationFolder + + "datasheet_mode.pdf")); PdfDictionary pdfObject = (PdfDictionary)pdfDocument.GetPdfObject(53); - pdfDocument.GetPage(1).GetResources().AddForm(pdfObject); + pdfDocument.GetPage(1).GetResources().AddForm((PdfStream)pdfObject); pdfDocument.Close(); NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(destinationFolder + "datasheet_mode.pdf", sourceFolder + "cmp_datasheet_mode.pdf", "d:/", "diff_")); @@ -262,8 +246,8 @@ public virtual void CheckAndResolveCircularReferences() { /// [NUnit.Framework.Test] public virtual void ReadEncryptedDocumentWithFullCompression() { - PdfReader reader = new PdfReader(new FileStream(sourceFolder + "source.pdf", FileMode.Open, FileAccess.Read - ), new ReaderProperties().SetPassword("123".GetBytes())); + PdfReader reader = new PdfReader(sourceFolder + "source.pdf", new ReaderProperties().SetPassword("123".GetBytes + ())); PdfDocument pdfDocument = new PdfDocument(reader); PdfDictionary form = pdfDocument.GetCatalog().GetPdfObject().GetAsDictionary(PdfName.AcroForm); PdfDictionary field = form.GetAsArray(PdfName.Fields).GetAsDictionary(0); diff --git a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfEncryptionTest.cs b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfEncryptionTest.cs index 12327ee467..8094e66269 100644 --- a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfEncryptionTest.cs +++ b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfEncryptionTest.cs @@ -1,30 +1,61 @@ using System; using System.IO; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.X509; using iText.IO.Font; +using iText.Kernel; +using iText.Kernel.Crypto; using iText.Kernel.Font; using iText.Kernel.Utils; using iText.Test; namespace iText.Kernel.Pdf { + /// + /// Due to import control restrictions by the governments of a few countries, + /// the encryption libraries shipped by default with the Java SDK restrict the + /// length, and as a result the strength, of encryption keys. + /// + /// + /// Due to import control restrictions by the governments of a few countries, + /// the encryption libraries shipped by default with the Java SDK restrict the + /// length, and as a result the strength, of encryption keys. Be aware that in + /// this test by using + /// + /// we + /// remove cryptography restrictions via reflection for testing purposes. + ///
+ /// For more conventional way of solving this problem you need to replace the + /// default security JARs in your Java installation with the Java Cryptography + /// Extension (JCE) Unlimited Strength Jurisdiction Policy Files. These JARs + /// are available for download from http://java.oracle.com/ in eligible countries. + ///
public class PdfEncryptionTest : ExtendedITextTest { /// User password. - public static byte[] USER = "Hello".GetBytes(); + public static byte[] USER = "Hello".GetBytes(iText.IO.Util.EncodingUtil.ISO_8859_1); /// Owner password. - public static byte[] OWNER = "World".GetBytes(); + public static byte[] OWNER = "World".GetBytes(iText.IO.Util.EncodingUtil.ISO_8859_1); internal const String author = "Alexander Chingarev"; - internal const String creator = "iText 6"; + internal const String creator = "iText 7"; public static readonly String destinationFolder = NUnit.Framework.TestContext.CurrentContext.TestDirectory + "/test/itext/kernel/pdf/PdfEncryptionTest/"; public static readonly String sourceFolder = NUnit.Framework.TestContext.CurrentContext.TestDirectory + "/../../resources/itext/kernel/pdf/PdfEncryptionTest/"; + public static readonly String CERT = sourceFolder + "test.cer"; + + public static readonly String PRIVATE_KEY = sourceFolder + "test.p12"; + + public static readonly char[] PRIVATE_KEY_PASS = "kspass".ToCharArray(); + + private ICipherParameters privateKey; + [NUnit.Framework.TestFixtureSetUp] public static void BeforeClass() { - CreateDestinationFolder(destinationFolder); + CreateOrClearDestinationFolder(destinationFolder); } /// @@ -107,37 +138,275 @@ public virtual void EncryptWithPasswordAes256NoCompression() { EncryptWithPassword(filename, encryptionType, CompressionConstants.NO_COMPRESSION); } + /// + /// + /// + /// + [NUnit.Framework.Test] + public virtual void EncryptWithCertificateStandard128() { + String filename = "encryptWithCertificateStandard128.pdf"; + int encryptionType = EncryptionConstants.STANDARD_ENCRYPTION_128; + EncryptWithCertificate(filename, encryptionType, CompressionConstants.DEFAULT_COMPRESSION); + } + + /// + /// + /// + /// + [NUnit.Framework.Test] + public virtual void EncryptWithCertificateStandard40() { + String filename = "encryptWithCertificateStandard40.pdf"; + int encryptionType = EncryptionConstants.STANDARD_ENCRYPTION_40; + EncryptWithCertificate(filename, encryptionType, CompressionConstants.DEFAULT_COMPRESSION); + } + + /// + /// + /// + /// + [NUnit.Framework.Test] + public virtual void EncryptWithCertificateStandard128NoCompression() { + String filename = "encryptWithCertificateStandard128NoCompression.pdf"; + int encryptionType = EncryptionConstants.STANDARD_ENCRYPTION_128; + EncryptWithCertificate(filename, encryptionType, CompressionConstants.NO_COMPRESSION); + } + + /// + /// + /// + /// + [NUnit.Framework.Test] + public virtual void EncryptWithCertificateStandard40NoCompression() { + String filename = "encryptWithCertificateStandard40NoCompression.pdf"; + int encryptionType = EncryptionConstants.STANDARD_ENCRYPTION_40; + EncryptWithCertificate(filename, encryptionType, CompressionConstants.NO_COMPRESSION); + } + + /// + /// + /// + /// + [NUnit.Framework.Test] + public virtual void EncryptWithCertificateAes128() { + String filename = "encryptWithCertificateAes128.pdf"; + int encryptionType = EncryptionConstants.ENCRYPTION_AES_128; + EncryptWithCertificate(filename, encryptionType, CompressionConstants.DEFAULT_COMPRESSION); + } + + /// + /// + /// + /// + [NUnit.Framework.Test] + public virtual void EncryptWithCertificateAes256() { + String filename = "encryptWithCertificateAes256.pdf"; + int encryptionType = EncryptionConstants.ENCRYPTION_AES_256; + EncryptWithCertificate(filename, encryptionType, CompressionConstants.DEFAULT_COMPRESSION); + } + + /// + /// + /// + /// + [NUnit.Framework.Test] + public virtual void EncryptWithCertificateAes128NoCompression() { + String filename = "encryptWithCertificateAes128NoCompression.pdf"; + int encryptionType = EncryptionConstants.ENCRYPTION_AES_128; + EncryptWithCertificate(filename, encryptionType, CompressionConstants.NO_COMPRESSION); + } + + /// + /// + /// + /// + [NUnit.Framework.Test] + public virtual void EncryptWithCertificateAes256NoCompression() { + String filename = "encryptWithCertificateAes256NoCompression.pdf"; + int encryptionType = EncryptionConstants.ENCRYPTION_AES_256; + EncryptWithCertificate(filename, encryptionType, CompressionConstants.NO_COMPRESSION); + } + + /// + [NUnit.Framework.Test] + public virtual void OpenEncryptedDocWithoutPassword() { + NUnit.Framework.Assert.That(() => { + PdfDocument doc = new PdfDocument(new PdfReader(sourceFolder + "encryptedWithPasswordStandard40.pdf")); + doc.Close(); + } + , NUnit.Framework.Throws.TypeOf().With.Message.EqualTo(BadPasswordException.BadUserPassword)); +; + } + + /// + [NUnit.Framework.Test] + public virtual void OpenEncryptedDocWithWrongPassword() { + NUnit.Framework.Assert.That(() => { + PdfReader reader = new PdfReader(sourceFolder + "encryptedWithPasswordStandard40.pdf", new ReaderProperties + ().SetPassword("wrong_password".GetBytes(iText.IO.Util.EncodingUtil.ISO_8859_1))); + PdfDocument doc = new PdfDocument(reader); + doc.Close(); + } + , NUnit.Framework.Throws.TypeOf().With.Message.EqualTo(BadPasswordException.BadUserPassword)); +; + } + + /// + [NUnit.Framework.Test] + public virtual void OpenEncryptedDocWithoutCertificate() { + NUnit.Framework.Assert.That(() => { + PdfDocument doc = new PdfDocument(new PdfReader(sourceFolder + "encryptedWithCertificateAes128.pdf")); + doc.Close(); + } + , NUnit.Framework.Throws.TypeOf().With.Message.EqualTo(PdfException.CertificateIsNotProvidedDocumentIsEncryptedWithPublicKeyCertificate)); +; + } + + /// + /// + [NUnit.Framework.Test] + public virtual void OpenEncryptedDocWithoutPrivateKey() { + NUnit.Framework.Assert.That(() => { + PdfReader reader = new PdfReader(sourceFolder + "encryptedWithCertificateAes128.pdf", new ReaderProperties + ().SetPublicKeySecurityParams(GetPublicCertificate(sourceFolder + "wrong.cer"), null)); + PdfDocument doc = new PdfDocument(reader); + doc.Close(); + } + , NUnit.Framework.Throws.TypeOf().With.Message.EqualTo(PdfException.BadCertificateAndKey)); +; + } + + /// + /// + [NUnit.Framework.Test] + public virtual void OpenEncryptedDocWithWrongCertificate() { + NUnit.Framework.Assert.That(() => { + PdfReader reader = new PdfReader(sourceFolder + "encryptedWithCertificateAes128.pdf", new ReaderProperties + ().SetPublicKeySecurityParams(GetPublicCertificate(sourceFolder + "wrong.cer"), GetPrivateKey())); + PdfDocument doc = new PdfDocument(reader); + doc.Close(); + } + , NUnit.Framework.Throws.TypeOf().With.Message.EqualTo(PdfException.BadCertificateAndKey)); +; + } + + /// + /// + [NUnit.Framework.Test] + public virtual void OpenEncryptedDocWithWrongPrivateKey() { + NUnit.Framework.Assert.That(() => { + PdfReader reader = new PdfReader(sourceFolder + "encryptedWithCertificateAes128.pdf", new ReaderProperties + ().SetPublicKeySecurityParams(GetPublicCertificate(CERT), iText.Kernel.Crypto.CryptoUtil.ReadPrivateKeyFromPkcs12KeyStore + (new FileStream(sourceFolder + "wrong.p12", FileMode.Open, FileAccess.Read), "demo", "password".ToCharArray + ()))); + PdfDocument doc = new PdfDocument(reader); + doc.Close(); + } + , NUnit.Framework.Throws.TypeOf().With.Message.EqualTo(PdfException.PdfDecryption)); +; + } + + /// + /// + [NUnit.Framework.Test] + public virtual void OpenEncryptedDocWithWrongCertificateAndPrivateKey() { + NUnit.Framework.Assert.That(() => { + PdfReader reader = new PdfReader(sourceFolder + "encryptedWithCertificateAes128.pdf", new ReaderProperties + ().SetPublicKeySecurityParams(GetPublicCertificate(sourceFolder + "wrong.cer"), iText.Kernel.Crypto.CryptoUtil.ReadPrivateKeyFromPkcs12KeyStore + (new FileStream(sourceFolder + "wrong.p12", FileMode.Open, FileAccess.Read), "demo", "password".ToCharArray + ()))); + PdfDocument doc = new PdfDocument(reader); + doc.Close(); + } + , NUnit.Framework.Throws.TypeOf().With.Message.EqualTo(PdfException.BadCertificateAndKey)); +; + } + /// /// /// public virtual void EncryptWithPassword(String filename, int encryptionType, int compression) { String outFileName = destinationFolder + filename; int permissions = EncryptionConstants.ALLOW_SCREENREADERS; - PdfWriter writer = new PdfWriter(new FileStream(outFileName, FileMode.Create), new WriterProperties().SetStandardEncryption - (USER, OWNER, permissions, encryptionType).AddXmpMetadata()); + PdfWriter writer = new PdfWriter(outFileName, new WriterProperties().SetStandardEncryption(USER, OWNER, permissions + , encryptionType).AddXmpMetadata()); writer.SetCompressionLevel(compression); PdfDocument document = new PdfDocument(writer); document.GetDocumentInfo().SetAuthor(author).SetCreator(creator); PdfPage page = document.AddNewPage(); - page.GetFirstContentStream().GetOutputStream().WriteBytes(("q\n" + "BT\n" + "36 706 Td\n" + "0 0 Td\n" + "/F1 24 Tf\n" - + "(Hello world!)Tj\n" + "0 0 Td\n" + "ET\n" + "Q ").GetBytes()); - page.GetResources().AddFont(document, PdfFontFactory.CreateFont(FontConstants.HELVETICA)); + String textContent = "Hello world!"; + WriteTextBytesOnPageContent(page, textContent); page.Flush(); document.Close(); + CheckDecryptedWithPasswordContent(filename, OWNER, textContent); + CheckDecryptedWithPasswordContent(filename, USER, textContent); CompareTool compareTool = new CompareTool().EnableEncryptionCompare(); String compareResult = compareTool.CompareByContent(outFileName, sourceFolder + "cmp_" + filename, destinationFolder , "diff_", USER, USER); if (compareResult != null) { NUnit.Framework.Assert.Fail(compareResult); } - CheckDecryptedContent(filename, OWNER, "(Hello world!)"); - CheckDecryptedContent(filename, USER, "(Hello world!)"); - CheckDocumentStamping(filename, OWNER); - CheckDocumentAppending(filename, OWNER); + CheckEncryptedWithPasswordDocumentStamping(filename, OWNER); + CheckEncryptedWithPasswordDocumentAppending(filename, OWNER); } + /// /// - public virtual void CheckDecryptedContent(String filename, byte[] password, String pageContent) { + /// + /// + public virtual void EncryptWithCertificate(String filename, int encryptionType, int compression) { + String outFileName = destinationFolder + filename; + int permissions = EncryptionConstants.ALLOW_SCREENREADERS; + X509Certificate cert = GetPublicCertificate(CERT); + PdfWriter writer = new PdfWriter(outFileName, new WriterProperties().SetPublicKeyEncryption(new X509Certificate + [] { cert }, new int[] { permissions }, encryptionType).AddXmpMetadata()); + writer.SetCompressionLevel(compression); + PdfDocument document = new PdfDocument(writer); + document.GetDocumentInfo().SetAuthor(author).SetCreator(creator); + PdfPage page = document.AddNewPage(); + String textContent = "Hello world!"; + WriteTextBytesOnPageContent(page, textContent); + page.Flush(); + document.Close(); + CheckDecryptedWithCertificateContent(filename, cert, textContent); + CompareTool compareTool = new CompareTool().EnableEncryptionCompare(); + compareTool.GetOutReaderProperties().SetPublicKeySecurityParams(cert, GetPrivateKey()); + compareTool.GetCmpReaderProperties().SetPublicKeySecurityParams(cert, GetPrivateKey()); + String compareResult = compareTool.CompareByContent(outFileName, sourceFolder + "cmp_" + filename, destinationFolder + , "diff_"); + if (compareResult != null) { + NUnit.Framework.Assert.Fail(compareResult); + } + CheckEncryptedWithCertificateDocumentStamping(filename, cert); + CheckEncryptedWithCertificateDocumentAppending(filename, cert); + } + + /// + private void WriteTextBytesOnPageContent(PdfPage page, String text) { + page.GetFirstContentStream().GetOutputStream().WriteBytes(("q\n" + "BT\n" + "36 706 Td\n" + "0 0 Td\n" + "/F1 24 Tf\n" + + "(" + text + ")Tj\n" + "0 0 Td\n" + "ET\n" + "Q ").GetBytes(iText.IO.Util.EncodingUtil.ISO_8859_1)); + page.GetResources().AddFont(page.GetDocument(), PdfFontFactory.CreateFont(FontConstants.HELVETICA)); + } + + /// + /// + public virtual X509Certificate GetPublicCertificate(String path) { + FileStream @is = new FileStream(path, FileMode.Open, FileAccess.Read); + return iText.Kernel.Crypto.CryptoUtil.ReadPublicCertificate(@is); + } + + /// + /// + public virtual ICipherParameters GetPrivateKey() { + if (privateKey == null) { + privateKey = iText.Kernel.Crypto.CryptoUtil.ReadPrivateKeyFromPkcs12KeyStore(new FileStream(PRIVATE_KEY, FileMode.Open + , FileAccess.Read), "sandbox", PRIVATE_KEY_PASS); + } + return privateKey; + } + + /// + public virtual void CheckDecryptedWithPasswordContent(String filename, byte[] password, String pageContent + ) { String src = destinationFolder + filename; PdfReader reader = new PdfReader(src, new ReaderProperties().SetPassword(password)); PdfDocument document = new PdfDocument(reader); @@ -149,9 +418,26 @@ public virtual void CheckDecryptedContent(String filename, byte[] password, Stri document.Close(); } + /// + /// + public virtual void CheckDecryptedWithCertificateContent(String filename, X509Certificate certificate, String + pageContent) { + String src = destinationFolder + filename; + PdfReader reader = new PdfReader(src, new ReaderProperties().SetPublicKeySecurityParams(certificate, GetPrivateKey + ())); + PdfDocument document = new PdfDocument(reader); + PdfPage page = document.GetPage(1); + String s = iText.IO.Util.JavaUtil.GetStringForBytes(page.GetStreamBytes(0)); + NUnit.Framework.Assert.IsTrue(s.Contains(pageContent), "Expected content: \n" + pageContent); + NUnit.Framework.Assert.AreEqual(author, document.GetDocumentInfo().GetAuthor(), "Encrypted author"); + NUnit.Framework.Assert.AreEqual(creator, document.GetDocumentInfo().GetCreator(), "Encrypted creator"); + document.Close(); + } + + // basically this is comparing content of decrypted by itext document with content of encrypted document /// /// - public virtual void CheckDocumentStamping(String filename, byte[] password) { + public virtual void CheckEncryptedWithPasswordDocumentStamping(String filename, byte[] password) { String srcFileName = destinationFolder + filename; String outFileName = destinationFolder + "stamped_" + filename; PdfReader reader = new PdfReader(srcFileName, new ReaderProperties().SetPassword(password)); @@ -165,9 +451,30 @@ public virtual void CheckDocumentStamping(String filename, byte[] password) { } } + // basically this is comparing content of decrypted by itext document with content of encrypted document + /// + /// + /// + public virtual void CheckEncryptedWithCertificateDocumentStamping(String filename, X509Certificate certificate + ) { + String srcFileName = destinationFolder + filename; + String outFileName = destinationFolder + "stamped_" + filename; + PdfReader reader = new PdfReader(srcFileName, new ReaderProperties().SetPublicKeySecurityParams(certificate + , GetPrivateKey())); + PdfDocument document = new PdfDocument(reader, new PdfWriter(outFileName)); + document.Close(); + CompareTool compareTool = new CompareTool(); + compareTool.GetCmpReaderProperties().SetPublicKeySecurityParams(certificate, GetPrivateKey()); + String compareResult = compareTool.CompareByContent(outFileName, sourceFolder + "cmp_" + filename, destinationFolder + , "diff_"); + if (compareResult != null) { + NUnit.Framework.Assert.Fail(compareResult); + } + } + /// /// - public virtual void CheckDocumentAppending(String filename, byte[] password) { + public virtual void CheckEncryptedWithPasswordDocumentAppending(String filename, byte[] password) { String srcFileName = destinationFolder + filename; String outFileName = destinationFolder + "appended_" + filename; PdfReader reader = new PdfReader(srcFileName, new ReaderProperties().SetPassword(password)); @@ -175,6 +482,7 @@ public virtual void CheckDocumentAppending(String filename, byte[] password) { ()); PdfPage newPage = document.AddNewPage(); newPage.Put(PdfName.Default, new PdfString("Hello world string")); + WriteTextBytesOnPageContent(newPage, "Hello world page_2!"); document.Close(); CompareTool compareTool = new CompareTool().EnableEncryptionCompare(); String compareResult = compareTool.CompareByContent(outFileName, sourceFolder + "cmp_appended_" + filename @@ -183,5 +491,39 @@ public virtual void CheckDocumentAppending(String filename, byte[] password) { NUnit.Framework.Assert.Fail(compareResult); } } + + /// + /// + /// + public virtual void CheckEncryptedWithCertificateDocumentAppending(String filename, X509Certificate certificate + ) { + String srcFileName = destinationFolder + filename; + String outFileName = destinationFolder + "appended_" + filename; + PdfReader reader = new PdfReader(srcFileName, new ReaderProperties().SetPublicKeySecurityParams(certificate + , GetPrivateKey())); + PdfDocument document = new PdfDocument(reader, new PdfWriter(outFileName), new StampingProperties().UseAppendMode + ()); + PdfPage newPage = document.AddNewPage(); + String helloWorldStringValue = "Hello world string"; + newPage.Put(PdfName.Default, new PdfString(helloWorldStringValue)); + WriteTextBytesOnPageContent(newPage, "Hello world page_2!"); + document.Close(); + PdfReader appendedDocReader = new PdfReader(outFileName, new ReaderProperties().SetPublicKeySecurityParams + (certificate, GetPrivateKey())); + PdfDocument appendedDoc = new PdfDocument(appendedDocReader); + PdfPage secondPage = appendedDoc.GetPage(2); + PdfString helloWorldPdfString = secondPage.GetPdfObject().GetAsString(PdfName.Default); + String actualHelloWorldStringValue = helloWorldPdfString != null ? helloWorldPdfString.GetValue() : null; + NUnit.Framework.Assert.AreEqual(actualHelloWorldStringValue, helloWorldStringValue); + appendedDoc.Close(); + CompareTool compareTool = new CompareTool().EnableEncryptionCompare(); + compareTool.GetOutReaderProperties().SetPublicKeySecurityParams(certificate, GetPrivateKey()); + compareTool.GetCmpReaderProperties().SetPublicKeySecurityParams(certificate, GetPrivateKey()); + String compareResult = compareTool.CompareByContent(outFileName, sourceFolder + "cmp_appended_" + filename + , destinationFolder, "diff_"); + if (compareResult != null) { + NUnit.Framework.Assert.Fail(compareResult); + } + } } } diff --git a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfExtGStateTest.cs b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfExtGStateTest.cs index 14aa6f6429..049bc0f9ba 100644 --- a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfExtGStateTest.cs +++ b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfExtGStateTest.cs @@ -1,5 +1,4 @@ using System; -using System.IO; using iText.IO.Font; using iText.Kernel.Font; using iText.Kernel.Pdf.Canvas; @@ -23,9 +22,7 @@ public static void BeforeClass() { [NUnit.Framework.Test] public virtual void EgsTest1() { String destinationDocument = destinationFolder + "egsTest1.pdf"; - FileStream fos = new FileStream(destinationDocument, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument document = new PdfDocument(writer); + PdfDocument document = new PdfDocument(new PdfWriter(destinationDocument)); //Create page and canvas PdfPage page = document.AddNewPage(); PdfCanvas canvas = new PdfCanvas(page); diff --git a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfFontTest.cs b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfFontTest.cs index 3b9a8d44e5..605235a508 100644 --- a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfFontTest.cs +++ b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfFontTest.cs @@ -41,8 +41,7 @@ public virtual void CreateDocumentWithKozmin() { String filename = destinationFolder + "DocumentWithKozmin.pdf"; String cmpFilename = sourceFolder + "cmp_DocumentWithKozmin.pdf"; String title = "Type 0 test"; - FileStream fos = new FileStream(filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); + PdfWriter writer = new PdfWriter(filename); writer.SetCompressionLevel(CompressionConstants.NO_COMPRESSION); PdfDocument pdfDoc = new PdfDocument(writer); pdfDoc.GetDocumentInfo().SetAuthor(author).SetCreator(creator).SetTitle(title); @@ -68,8 +67,7 @@ public virtual void CreateDocumentWithStSongUni() { String filename = destinationFolder + "DocumentWithStSongUni.pdf"; String cmpFilename = sourceFolder + "cmp_DocumentWithStSongUni.pdf"; String title = "Type0 test"; - FileStream fos = new FileStream(filename, FileMode.Create); - PdfDocument pdfDoc = new PdfDocument(new PdfWriter(fos).SetCompressionLevel(CompressionConstants.NO_COMPRESSION + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(filename).SetCompressionLevel(CompressionConstants.NO_COMPRESSION )); pdfDoc.GetDocumentInfo().SetAuthor(author).SetCreator(creator).SetTitle(title); PdfFont type0Font = PdfFontFactory.CreateFont("STSong-Light", "UniGB-UTF16-H"); @@ -94,8 +92,7 @@ public virtual void CreateDocumentWithStSong() { String filename = destinationFolder + "DocumentWithStSong.pdf"; String cmpFilename = sourceFolder + "cmp_DocumentWithStSong.pdf"; String title = "Type0 test"; - FileStream fos = new FileStream(filename, FileMode.Create); - PdfDocument pdfDoc = new PdfDocument(new PdfWriter(fos).SetCompressionLevel(CompressionConstants.NO_COMPRESSION + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(filename).SetCompressionLevel(CompressionConstants.NO_COMPRESSION )); pdfDoc.GetDocumentInfo().SetAuthor(author).SetCreator(creator).SetTitle(title); PdfFont type0Font = PdfFontFactory.CreateFont("STSong-Light", "Adobe-GB1-4"); @@ -120,8 +117,7 @@ public virtual void CreateDocumentWithTrueTypeAsType0() { String filename = destinationFolder + "DocumentWithTrueTypeAsType0.pdf"; String cmpFilename = sourceFolder + "cmp_DocumentWithTrueTypeAsType0.pdf"; String title = "Type0 test"; - FileStream fos = new FileStream(filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); + PdfWriter writer = new PdfWriter(filename); writer.SetCompressionLevel(CompressionConstants.NO_COMPRESSION); PdfDocument pdfDoc = new PdfDocument(writer); pdfDoc.GetDocumentInfo().SetAuthor(author).SetCreator(creator).SetTitle(title); @@ -166,8 +162,7 @@ public virtual void CreateDocumentWithType3Font() { // A A A A E E E ~ é //writing type3 font characters String title = "Type3 font iText 6 Document"; - FileStream fos = new FileStream(filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); + PdfWriter writer = new PdfWriter(filename); writer.SetCompressionLevel(CompressionConstants.NO_COMPRESSION); PdfDocument pdfDoc = new PdfDocument(writer); PdfType3Font type3 = PdfFontFactory.CreateType3Font(pdfDoc, false); @@ -218,8 +213,7 @@ public virtual void CreateDocumentWithHelvetica() { String filename = destinationFolder + "DocumentWithHelvetica.pdf"; String cmpFilename = sourceFolder + "cmp_DocumentWithHelvetica.pdf"; String title = "Type3 test"; - FileStream fos = new FileStream(filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); + PdfWriter writer = new PdfWriter(filename); writer.SetCompressionLevel(CompressionConstants.NO_COMPRESSION); PdfDocument pdfDoc = new PdfDocument(writer); pdfDoc.GetDocumentInfo().SetAuthor(author).SetCreator(creator).SetTitle(title); @@ -244,8 +238,7 @@ public virtual void CreateDocumentWithHelveticaOblique() { String filename = destinationFolder + "DocumentWithHelveticaOblique.pdf"; String cmpFilename = sourceFolder + "cmp_DocumentWithHelveticaOblique.pdf"; String title = "Empty iText 6 Document"; - FileStream fos = new FileStream(filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); + PdfWriter writer = new PdfWriter(filename); writer.SetCompressionLevel(CompressionConstants.NO_COMPRESSION); PdfDocument pdfDoc = new PdfDocument(writer); pdfDoc.GetDocumentInfo().SetAuthor(author).SetCreator(creator).SetTitle(title); @@ -270,8 +263,7 @@ public virtual void CreateDocumentWithHelveticaBoldOblique() { String filename = destinationFolder + "DocumentWithHelveticaBoldOblique.pdf"; String cmpFilename = sourceFolder + "cmp_DocumentWithHelveticaBoldOblique.pdf"; String title = "Empty iText 6 Document"; - FileStream fos = new FileStream(filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); + PdfWriter writer = new PdfWriter(filename); writer.SetCompressionLevel(CompressionConstants.NO_COMPRESSION); PdfDocument pdfDoc = new PdfDocument(writer); pdfDoc.GetDocumentInfo().SetAuthor(author).SetCreator(creator).SetTitle(title); @@ -296,8 +288,7 @@ public virtual void CreateDocumentWithCourierBold() { String filename = destinationFolder + "DocumentWithCourierBold.pdf"; String cmpFilename = sourceFolder + "cmp_DocumentWithCourierBold.pdf"; String title = "Empty iText 6 Document"; - FileStream fos = new FileStream(filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); + PdfWriter writer = new PdfWriter(filename); writer.SetCompressionLevel(CompressionConstants.NO_COMPRESSION); PdfDocument pdfDoc = new PdfDocument(writer); pdfDoc.GetDocumentInfo().SetAuthor(author).SetCreator(creator).SetTitle(title); @@ -322,8 +313,7 @@ public virtual void CreateDocumentWithType1FontAfm() { String filename = destinationFolder + "DocumentWithCMR10Afm.pdf"; String cmpFilename = sourceFolder + "cmp_DocumentWithCMR10Afm.pdf"; String title = "Empty iText 6 Document"; - FileStream fos = new FileStream(filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); + PdfWriter writer = new PdfWriter(filename); writer.SetCompressionLevel(CompressionConstants.NO_COMPRESSION); PdfDocument pdfDoc = new PdfDocument(writer); pdfDoc.GetDocumentInfo().SetAuthor(author).SetCreator(creator).SetTitle(title); @@ -355,8 +345,7 @@ public virtual void CreateDocumentWithType1FontPfm() { String filename = destinationFolder + "DocumentWithCMR10Pfm.pdf"; String cmpFilename = sourceFolder + "cmp_DocumentWithCMR10Pfm.pdf"; String title = "Empty iText 6 Document"; - FileStream fos = new FileStream(filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); + PdfWriter writer = new PdfWriter(filename); writer.SetCompressionLevel(CompressionConstants.NO_COMPRESSION); PdfDocument pdfDoc = new PdfDocument(writer); pdfDoc.GetDocumentInfo().SetAuthor(author).SetCreator(creator).SetTitle(title); @@ -381,8 +370,7 @@ public virtual void CreateDocumentWithTrueTypeFont1() { String filename = destinationFolder + "DocumentWithTrueTypeFont1.pdf"; String cmpFilename = sourceFolder + "cmp_DocumentWithTrueTypeFont1.pdf"; String title = "Empty iText 6 Document"; - FileStream fos = new FileStream(filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); + PdfWriter writer = new PdfWriter(filename); writer.SetCompressionLevel(CompressionConstants.NO_COMPRESSION); PdfDocument pdfDoc = new PdfDocument(writer); pdfDoc.GetDocumentInfo().SetAuthor(author).SetCreator(creator).SetTitle(title); @@ -413,8 +401,7 @@ public virtual void CreateDocumentWithTrueTypeOtfFont() { String filename = destinationFolder + "DocumentWithTrueTypeOtfFont.pdf"; String cmpFilename = sourceFolder + "cmp_DocumentWithTrueTypeOtfFont.pdf"; String title = "Empty iText 6 Document"; - FileStream fos = new FileStream(filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); + PdfWriter writer = new PdfWriter(filename); writer.SetCompressionLevel(CompressionConstants.NO_COMPRESSION); PdfDocument pdfDoc = new PdfDocument(writer); pdfDoc.GetDocumentInfo().SetAuthor(author).SetCreator(creator).SetTitle(title); @@ -451,8 +438,7 @@ public virtual void CreateDocumentWithType0OtfFont() { String filename = destinationFolder + "DocumentWithType0OtfFont.pdf"; String cmpFilename = sourceFolder + "cmp_DocumentWithType0OtfFont.pdf"; String title = "Empty iText 6 Document"; - FileStream fos = new FileStream(filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); + PdfWriter writer = new PdfWriter(filename); writer.SetCompressionLevel(CompressionConstants.NO_COMPRESSION); PdfDocument pdfDoc = new PdfDocument(writer); pdfDoc.GetDocumentInfo().SetAuthor(author).SetCreator(creator).SetTitle(title); @@ -491,7 +477,7 @@ public virtual void TestUpdateType3FontBasedExistingFont() { String cmpOutputFileName = sourceFolder + "cmp_type3Font_update.pdf"; String title = "Type3 font iText 6 Document"; PdfReader reader = new PdfReader(inputFileName); - PdfWriter writer = new PdfWriter(new FileStream(outputFileName, FileMode.Create)); + PdfWriter writer = new PdfWriter(outputFileName); writer.SetCompressionLevel(CompressionConstants.NO_COMPRESSION); PdfDocument pdfDoc = new PdfDocument(reader, writer); pdfDoc.GetDocumentInfo().SetAuthor(author).SetCreator(creator).SetTitle(title); @@ -522,7 +508,7 @@ public virtual void TestNewType3FontBasedExistingFont() { String cmpOutputFileName = sourceFolder + "cmp_type3Font_new.pdf"; String title = "Type3 font iText 6 Document"; PdfReader reader = new PdfReader(inputFileName); - PdfWriter pdfWriter = new PdfWriter(new FileStream(outputFileName, FileMode.Create)); + PdfWriter pdfWriter = new PdfWriter(outputFileName); pdfWriter.SetCompressionLevel(CompressionConstants.NO_COMPRESSION); PdfDocument inputPdfDoc = new PdfDocument(reader); PdfDocument outputPdfDoc = new PdfDocument(pdfWriter); @@ -558,8 +544,7 @@ public virtual void TestNewType1FontBasedExistingFont() { PdfReader reader1 = new PdfReader(inputFileName1); PdfDocument inputPdfDoc1 = new PdfDocument(reader1); PdfDictionary pdfDictionary = (PdfDictionary)inputPdfDoc1.GetPdfObject(4); - FileStream fos = new FileStream(filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); + PdfWriter writer = new PdfWriter(filename); writer.SetCompressionLevel(CompressionConstants.NO_COMPRESSION); PdfDocument pdfDoc = new PdfDocument(writer); pdfDoc.GetDocumentInfo().SetAuthor(author).SetCreator(creator).SetTitle(title); @@ -586,8 +571,7 @@ public virtual void TestNewTrueTypeFont1BasedExistingFont() { String title = "testNewTrueTypeFont1BasedExistingFont"; PdfReader reader1 = new PdfReader(inputFileName1); PdfDocument inputPdfDoc1 = new PdfDocument(reader1); - FileStream fos = new FileStream(filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); + PdfWriter writer = new PdfWriter(filename); writer.SetCompressionLevel(CompressionConstants.NO_COMPRESSION); PdfDocument pdfDoc = new PdfDocument(writer); pdfDoc.GetDocumentInfo().SetAuthor(author).SetCreator(creator).SetTitle(title); @@ -616,8 +600,7 @@ public virtual void TestNewTrueTypeFont2BasedExistingFont() { PdfReader reader1 = new PdfReader(inputFileName1); PdfDocument inputPdfDoc1 = new PdfDocument(reader1); PdfDictionary pdfDictionary = (PdfDictionary)inputPdfDoc1.GetPdfObject(4); - FileStream fos = new FileStream(filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); + PdfWriter writer = new PdfWriter(filename); writer.SetCompressionLevel(CompressionConstants.NO_COMPRESSION); PdfDocument pdfDoc = new PdfDocument(writer); pdfDoc.GetDocumentInfo().SetAuthor(author).SetCreator(creator).SetTitle(title); @@ -642,8 +625,7 @@ public virtual void TestTrueTypeFont1BasedExistingFont() { String filename = destinationFolder + "DocumentWithTrueTypeFont1_updated.pdf"; String cmpFilename = sourceFolder + "cmp_DocumentWithTrueTypeFont1_updated.pdf"; PdfReader reader1 = new PdfReader(inputFileName1); - FileStream fos = new FileStream(filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); + PdfWriter writer = new PdfWriter(filename); writer.SetCompressionLevel(CompressionConstants.NO_COMPRESSION); PdfDocument pdfDoc = new PdfDocument(reader1, writer); PdfDictionary pdfDictionary = (PdfDictionary)pdfDoc.GetPdfObject(4); @@ -669,8 +651,7 @@ public virtual void TestUpdateCjkFontBasedExistingFont() { String cmpFilename = sourceFolder + "cmp_DocumentWithKozmin_update.pdf"; String title = "Type0 font iText 6 Document"; PdfReader reader = new PdfReader(inputFileName1); - FileStream fos = new FileStream(filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); + PdfWriter writer = new PdfWriter(filename); writer.SetCompressionLevel(CompressionConstants.NO_COMPRESSION); PdfDocument pdfDoc = new PdfDocument(reader, writer); pdfDoc.GetDocumentInfo().SetAuthor(author).SetCreator(creator).SetTitle(title); @@ -699,8 +680,7 @@ public virtual void TestNewCjkFontBasedExistingFont() { PdfReader reader1 = new PdfReader(inputFileName1); PdfDocument inputPdfDoc1 = new PdfDocument(reader1); PdfDictionary pdfDictionary = (PdfDictionary)inputPdfDoc1.GetPdfObject(6); - FileStream fos = new FileStream(filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); + PdfWriter writer = new PdfWriter(filename); writer.SetCompressionLevel(CompressionConstants.NO_COMPRESSION); PdfDocument pdfDoc = new PdfDocument(writer); pdfDoc.GetDocumentInfo().SetAuthor(author).SetCreator(creator).SetTitle(title); @@ -728,8 +708,7 @@ public virtual void CreateDocumentWithTrueTypeAsType0BasedExistingFont() { PdfReader reader1 = new PdfReader(inputFileName1); PdfDocument inputPdfDoc1 = new PdfDocument(reader1); PdfDictionary pdfDictionary = (PdfDictionary)inputPdfDoc1.GetPdfObject(6); - FileStream fos = new FileStream(filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); + PdfWriter writer = new PdfWriter(filename); writer.SetCompressionLevel(CompressionConstants.NO_COMPRESSION); PdfDocument pdfDoc = new PdfDocument(writer); pdfDoc.GetDocumentInfo().SetAuthor(author).SetCreator(creator).SetTitle(title); @@ -755,8 +734,7 @@ public virtual void CreateUpdatedDocumentWithTrueTypeAsType0BasedExistingFont() String cmpFilename = sourceFolder + "cmp_DocumentWithTrueTypeAsType0_update.pdf"; String title = "Type0 font iText 6 Document"; PdfReader reader = new PdfReader(inputFileName1); - FileStream fos = new FileStream(filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); + PdfWriter writer = new PdfWriter(filename); writer.SetCompressionLevel(CompressionConstants.NO_COMPRESSION); PdfDocument pdfDoc = new PdfDocument(reader, writer); pdfDoc.GetDocumentInfo().SetAuthor(author).SetCreator(creator).SetTitle(title); @@ -784,8 +762,7 @@ public virtual void CreateDocumentWithType1WithToUnicodeBasedExistingFont() { PdfReader reader1 = new PdfReader(inputFileName1); PdfDocument inputPdfDoc1 = new PdfDocument(reader1); PdfDictionary pdfDictionary = (PdfDictionary)inputPdfDoc1.GetPdfObject(4); - FileStream fos = new FileStream(filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); + PdfWriter writer = new PdfWriter(filename); writer.SetCompressionLevel(CompressionConstants.NO_COMPRESSION); PdfDocument pdfDoc = new PdfDocument(writer); pdfDoc.GetDocumentInfo().SetAuthor(author).SetCreator(creator).SetTitle(title); @@ -810,8 +787,7 @@ public virtual void TestType1FontUpdateContent() { String filename = destinationFolder + "DocumentWithCMR10Afm_updated.pdf"; String cmpFilename = sourceFolder + "cmp_DocumentWithCMR10Afm_updated.pdf"; PdfReader reader = new PdfReader(inputFileName1); - PdfWriter writer = new PdfWriter(new FileStream(filename, FileMode.Create)).SetCompressionLevel(CompressionConstants - .NO_COMPRESSION); + PdfWriter writer = new PdfWriter(filename).SetCompressionLevel(CompressionConstants.NO_COMPRESSION); PdfDocument pdfDoc = new PdfDocument(reader, writer); PdfDictionary pdfDictionary = (PdfDictionary)pdfDoc.GetPdfObject(4); PdfFont pdfType1Font = PdfFontFactory.CreateFont(pdfDictionary); @@ -848,14 +824,15 @@ public virtual void CreateWrongAfm1() { [NUnit.Framework.Test] public virtual void CreateWrongAfm2() { String message = ""; + String font = fontsFolder + "cmr10.pfb"; try { - FontProgramFactory.CreateType1Font(fontsFolder + "cmr10.pfb", null); + FontProgramFactory.CreateType1Font(font, null); } catch (iText.IO.IOException e) { message = e.Message; } - NUnit.Framework.Assert.AreEqual(NUnit.Framework.TestContext.CurrentContext.TestDirectory + "/../../resources/itext/kernel/pdf/fonts/cmr10.pfb is.not.an.afm.or.pfm.font.file" - , message); + NUnit.Framework.Assert.AreEqual(String.Format(iText.IO.IOException._1IsNotAnAfmOrPfmFontFile, font), message + ); } /// @@ -929,8 +906,7 @@ public virtual void TestWriteTTC() { String filename = destinationFolder + "DocumentWithTTC.pdf"; String cmpFilename = sourceFolder + "cmp_DocumentWithTTC.pdf"; String title = "Empty iText 6 Document"; - FileStream fos = new FileStream(filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); + PdfWriter writer = new PdfWriter(filename); writer.SetCompressionLevel(CompressionConstants.NO_COMPRESSION); PdfDocument pdfDoc = new PdfDocument(writer); pdfDoc.GetDocumentInfo().SetAuthor(author).SetCreator(creator).SetTitle(title); @@ -983,8 +959,7 @@ public virtual void TestNotoFont() { public virtual void NotoSansCJKjpTest() { String filename = destinationFolder + "NotoSansCJKjpTest.pdf"; String cmpFilename = sourceFolder + "cmp_DocumentWithTTC.pdf"; - PdfWriter writer = new PdfWriter(new FileStream(filename, FileMode.Create)); - PdfDocument doc = new PdfDocument(writer); + PdfDocument doc = new PdfDocument(new PdfWriter(filename)); PdfPage page = doc.AddNewPage(); // Identity-H must be embedded PdfFont font = PdfFontFactory.CreateFont(fontsFolder + "NotoSansCJKjp-Bold.otf", "Identity-H"); @@ -1008,13 +983,12 @@ public virtual void NotoSansCJKjpTest() { /// [NUnit.Framework.Test] public virtual void TestCheckTTCSize() { - TrueTypeCollection collection = new TrueTypeCollection(fontsFolder + "uming.ttc", "WinAnsi"); + TrueTypeCollection collection = new TrueTypeCollection(fontsFolder + "uming.ttc"); NUnit.Framework.Assert.IsTrue(collection.GetTTCSize() == 4); } /// [NUnit.Framework.Test] - [LogMessage(LogMessageConstant.REGISTERING_DIRECTORY)] public virtual void TestFontDirectoryRegister() { PdfFontFactory.RegisterDirectory(sourceFolder); PdfWriter writer = new PdfWriter(new ByteArrayOutputStream()); @@ -1047,10 +1021,10 @@ public virtual void TestFontRegister() { [NUnit.Framework.Test] public virtual void TestSplitString() { PdfFont font = PdfFontFactory.CreateFont(); - IList list1 = font.SplitString("Hello", 12, 10); + IList list1 = font.SplitString("Hello", 12f, 10); NUnit.Framework.Assert.IsTrue(list1.Count == 2); IList list2 = font.SplitString("Digitally signed by Dmitry Trusevich\nDate: 2015.10.25 14:43:56 MSK\nReason: Test 1\nLocation: Ghent" - , 12, 176); + , 12f, 176); NUnit.Framework.Assert.IsTrue(list2.Count == 5); } } diff --git a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfLayerTest.cs b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfLayerTest.cs index 6db8bf0263..70b7255c96 100644 --- a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfLayerTest.cs +++ b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfLayerTest.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.IO; using iText.IO.Font; using iText.Kernel.Font; using iText.Kernel.Pdf.Canvas; @@ -24,9 +23,8 @@ public static void BeforeClass() { /// [NUnit.Framework.Test] public virtual void TestInStamperMode1() { - PdfDocument pdfDoc = new PdfDocument(new PdfReader(new FileStream(sourceFolder + "input_layered.pdf", FileMode.Open - , FileAccess.Read)), new PdfWriter(new FileStream(destinationFolder + "output_copy_layered.pdf", FileMode.Create - ))); + PdfDocument pdfDoc = new PdfDocument(new PdfReader(sourceFolder + "input_layered.pdf"), new PdfWriter(destinationFolder + + "output_copy_layered.pdf")); pdfDoc.Close(); NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(destinationFolder + "output_copy_layered.pdf" , sourceFolder + "input_layered.pdf", destinationFolder, "diff")); @@ -36,9 +34,8 @@ public virtual void TestInStamperMode1() { /// [NUnit.Framework.Test] public virtual void TestInStamperMode2() { - PdfDocument pdfDoc = new PdfDocument(new PdfReader(new FileStream(sourceFolder + "input_layered.pdf", FileMode.Open - , FileAccess.Read)), new PdfWriter(new FileStream(destinationFolder + "output_layered.pdf", FileMode.Create - ))); + PdfDocument pdfDoc = new PdfDocument(new PdfReader(sourceFolder + "input_layered.pdf"), new PdfWriter(destinationFolder + + "output_layered.pdf")); PdfCanvas canvas = new PdfCanvas(pdfDoc, 1); PdfLayer newLayer = new PdfLayer("appended", pdfDoc); canvas.BeginLayer(newLayer).BeginText().SetFontAndSize(PdfFontFactory.CreateFont(FontConstants.HELVETICA), diff --git a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfObjectTest.cs b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfObjectTest.cs index bd82bce1f2..851e3e8e29 100644 --- a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfObjectTest.cs +++ b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfObjectTest.cs @@ -5,9 +5,7 @@ namespace iText.Kernel.Pdf { public class PdfObjectTest { [NUnit.Framework.Test] public virtual void IndirectsChain1() { - MemoryStream baos = new MemoryStream(); - PdfWriter writer = new PdfWriter(baos); - PdfDocument document = new PdfDocument(writer); + PdfDocument document = new PdfDocument(new PdfWriter(new MemoryStream())); document.AddNewPage(); PdfDictionary catalog = document.GetCatalog().GetPdfObject(); catalog.Put(new PdfName("a"), ((PdfDictionary)GetTestPdfDictionary().MakeIndirect(document)).GetIndirectReference @@ -19,9 +17,7 @@ public virtual void IndirectsChain1() { [NUnit.Framework.Test] public virtual void IndirectsChain2() { - MemoryStream baos = new MemoryStream(); - PdfWriter writer = new PdfWriter(baos); - PdfDocument document = new PdfDocument(writer); + PdfDocument document = new PdfDocument(new PdfWriter(new MemoryStream())); document.AddNewPage(); PdfDictionary catalog = document.GetCatalog().GetPdfObject(); PdfDictionary dictionary = GetTestPdfDictionary(); @@ -37,9 +33,7 @@ public virtual void IndirectsChain2() { [NUnit.Framework.Test] public virtual void IndirectsChain3() { - MemoryStream baos = new MemoryStream(); - PdfWriter writer = new PdfWriter(baos); - PdfDocument document = new PdfDocument(writer); + PdfDocument document = new PdfDocument(new PdfWriter(new MemoryStream())); document.AddNewPage(); PdfDictionary catalog = document.GetCatalog().GetPdfObject(); PdfDictionary dictionary = GetTestPdfDictionary(); @@ -57,9 +51,7 @@ public virtual void IndirectsChain3() { [NUnit.Framework.Test] public virtual void IndirectsChain4() { - MemoryStream baos = new MemoryStream(); - PdfWriter writer = new PdfWriter(baos); - PdfDocument document = new PdfDocument(writer); + PdfDocument document = new PdfDocument(new PdfWriter(new MemoryStream())); document.AddNewPage(); PdfDictionary catalog = document.GetCatalog().GetPdfObject(); PdfDictionary dictionary = GetTestPdfDictionary(); @@ -115,8 +107,7 @@ public virtual void PdfIndirectReferenceFlags() { [NUnit.Framework.Test] public virtual void PdtIndirectReferenceLateInitializing1() { MemoryStream baos = new MemoryStream(); - PdfWriter writer = new PdfWriter(baos); - PdfDocument document = new PdfDocument(writer); + PdfDocument document = new PdfDocument(new PdfWriter(baos)); document.AddNewPage(); PdfDictionary catalog = document.GetCatalog().GetPdfObject(); PdfIndirectReference indRef = document.CreateNextIndirectReference(); @@ -126,8 +117,7 @@ public virtual void PdtIndirectReferenceLateInitializing1() { dictionary.MakeIndirect(document, indRef); document.Close(); MemoryStream bais = new MemoryStream(baos.ToArray()); - PdfReader reader = new PdfReader(bais); - document = new PdfDocument(reader); + document = new PdfDocument(new PdfReader(bais)); PdfObject @object = document.GetCatalog().GetPdfObject().Get(new PdfName("Smth")); NUnit.Framework.Assert.IsTrue(@object is PdfDictionary); dictionary = (PdfDictionary)@object; @@ -140,8 +130,7 @@ public virtual void PdtIndirectReferenceLateInitializing1() { [NUnit.Framework.Test] public virtual void PdtIndirectReferenceLateInitializing2() { MemoryStream baos = new MemoryStream(); - PdfWriter writer = new PdfWriter(baos); - PdfDocument document = new PdfDocument(writer); + PdfDocument document = new PdfDocument(new PdfWriter(baos)); document.AddNewPage(); PdfDictionary catalog = document.GetCatalog().GetPdfObject(); PdfIndirectReference indRef1 = document.CreateNextIndirectReference(); @@ -153,8 +142,7 @@ public virtual void PdtIndirectReferenceLateInitializing2() { array.MakeIndirect(document, indRef2); document.Close(); MemoryStream bais = new MemoryStream(baos.ToArray()); - PdfReader reader = new PdfReader(bais); - document = new PdfDocument(reader); + document = new PdfDocument(new PdfReader(bais)); PdfDictionary catalogDict = document.GetCatalog().GetPdfObject(); PdfObject object1 = catalogDict.Get(new PdfName("Smth1")); PdfObject object2 = catalogDict.Get(new PdfName("Smth2")); @@ -165,9 +153,7 @@ public virtual void PdtIndirectReferenceLateInitializing2() { /// [NUnit.Framework.Test] public virtual void PdtIndirectReferenceLateInitializing3() { - MemoryStream baos = new MemoryStream(); - PdfWriter writer = new PdfWriter(baos); - PdfDocument document = new PdfDocument(writer); + PdfDocument document = new PdfDocument(new PdfWriter(new MemoryStream())); document.AddNewPage(); PdfDictionary catalog = document.GetCatalog().GetPdfObject(); PdfIndirectReference indRef1 = document.CreateNextIndirectReference(); diff --git a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfOutlineTest.cs b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfOutlineTest.cs index 62c586c045..52bae353c7 100644 --- a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfOutlineTest.cs +++ b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfOutlineTest.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.IO; using iText.IO; using iText.Kernel.Pdf.Navigation; using iText.Kernel.Utils; @@ -18,9 +17,7 @@ public class PdfOutlineTest : ExtendedITextTest { [NUnit.Framework.TestFixtureSetUp] public static void BeforeClass() { CreateDestinationFolder(destinationFolder); - FileStream fos = new FileStream(destinationFolder + "documentWithOutlines.pdf", FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(destinationFolder + "documentWithOutlines.pdf")); pdfDoc.GetCatalog().SetPageMode(PdfName.UseOutlines); PdfPage firstPage = pdfDoc.AddNewPage(); PdfPage secondPage = pdfDoc.AddNewPage(); @@ -35,9 +32,7 @@ public static void BeforeClass() { /// [NUnit.Framework.Test] public virtual void OutlinesTest() { - PdfReader reader = new PdfReader(new FileStream(sourceFolder + "iphone_user_guide.pdf", FileMode.Open, FileAccess.Read - )); - PdfDocument pdfDoc = new PdfDocument(reader); + PdfDocument pdfDoc = new PdfDocument(new PdfReader(sourceFolder + "iphone_user_guide.pdf")); PdfOutline outlines = pdfDoc.GetOutlines(false); IList children = outlines.GetAllChildren()[0].GetAllChildren(); NUnit.Framework.Assert.AreEqual(outlines.GetTitle(), "Outlines"); @@ -48,9 +43,7 @@ public virtual void OutlinesTest() { /// [NUnit.Framework.Test] public virtual void OutlinesWithPagesTest() { - PdfReader reader = new PdfReader(new FileStream(sourceFolder + "iphone_user_guide.pdf", FileMode.Open, FileAccess.Read - )); - PdfDocument pdfDoc = new PdfDocument(reader); + PdfDocument pdfDoc = new PdfDocument(new PdfReader(sourceFolder + "iphone_user_guide.pdf")); PdfPage page = pdfDoc.GetPage(52); IList pageOutlines = page.GetOutlines(true); try { @@ -67,9 +60,8 @@ public virtual void OutlinesWithPagesTest() { [NUnit.Framework.SetUp] public virtual void SetupAddOutlinesToDocumentTest() { String filename = sourceFolder + "iphone_user_guide.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); - FileStream fos = new FileStream(destinationFolder + "addOutlinesResult.pdf", FileMode.Create); - PdfWriter writer = new PdfWriter(fos); + PdfReader reader = new PdfReader(filename); + PdfWriter writer = new PdfWriter(destinationFolder + "addOutlinesResult.pdf"); PdfDocument pdfDoc = new PdfDocument(reader, writer); pdfDoc.SetTagged(); PdfOutline outlines = pdfDoc.GetOutlines(false); @@ -84,7 +76,6 @@ public virtual void SetupAddOutlinesToDocumentTest() { outlines.GetAllChildren()[0].GetAllChildren()[1].AddOutline("testOutline", 1).AddDestination(PdfExplicitDestination .CreateFit(pdfDoc.GetPage(102))); pdfDoc.Close(); - fos.Close(); } /// @@ -92,8 +83,7 @@ public virtual void SetupAddOutlinesToDocumentTest() { [NUnit.Framework.Test] public virtual void AddOutlinesToDocumentTest() { String filename = destinationFolder + "addOutlinesResult.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); - PdfDocument pdfDoc = new PdfDocument(reader); + PdfDocument pdfDoc = new PdfDocument(new PdfReader(filename)); PdfOutline outlines = pdfDoc.GetOutlines(false); try { NUnit.Framework.Assert.AreEqual(3, outlines.GetAllChildren().Count); @@ -109,10 +99,8 @@ public virtual void AddOutlinesToDocumentTest() { [NUnit.Framework.SetUp] public virtual void SetupRemovePageWithOutlinesTest() { String filename = sourceFolder + "iphone_user_guide.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); - FileStream fos = new FileStream(destinationFolder + "removePagesWithOutlinesResult.pdf", FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument pdfDoc = new PdfDocument(reader, writer); + PdfDocument pdfDoc = new PdfDocument(new PdfReader(filename), new PdfWriter(destinationFolder + "removePagesWithOutlinesResult.pdf" + )); pdfDoc.RemovePage(102); pdfDoc.Close(); } @@ -121,8 +109,7 @@ public virtual void SetupRemovePageWithOutlinesTest() { [NUnit.Framework.Test] public virtual void RemovePageWithOutlinesTest() { String filename = destinationFolder + "removePagesWithOutlinesResult.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); - PdfDocument pdfDoc = new PdfDocument(reader); + PdfDocument pdfDoc = new PdfDocument(new PdfReader(filename)); PdfPage page = pdfDoc.GetPage(102); IList pageOutlines = page.GetOutlines(false); try { @@ -137,9 +124,8 @@ public virtual void RemovePageWithOutlinesTest() { [NUnit.Framework.SetUp] public virtual void SetupUpdateOutlineTitle() { String filename = sourceFolder + "iphone_user_guide.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); - FileStream fos = new FileStream(destinationFolder + "updateOutlineTitleResult.pdf", FileMode.Create); - PdfWriter writer = new PdfWriter(fos); + PdfReader reader = new PdfReader(filename); + PdfWriter writer = new PdfWriter(destinationFolder + "updateOutlineTitleResult.pdf"); PdfDocument pdfDoc = new PdfDocument(reader, writer); PdfOutline outlines = pdfDoc.GetOutlines(false); outlines.GetAllChildren()[0].GetAllChildren()[1].SetTitle("New Title"); @@ -150,8 +136,7 @@ public virtual void SetupUpdateOutlineTitle() { [NUnit.Framework.Test] public virtual void UpdateOutlineTitle() { String filename = destinationFolder + "updateOutlineTitleResult.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); - PdfDocument pdfDoc = new PdfDocument(reader); + PdfDocument pdfDoc = new PdfDocument(new PdfReader(filename)); PdfOutline outlines = pdfDoc.GetOutlines(false); PdfOutline outline = outlines.GetAllChildren()[0].GetAllChildren()[1]; try { @@ -166,10 +151,8 @@ public virtual void UpdateOutlineTitle() { [NUnit.Framework.SetUp] public virtual void SetupAddOutlineInNotOutlineMode() { String filename = sourceFolder + "iphone_user_guide.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); - FileStream fos = new FileStream(destinationFolder + "addOutlinesWithoutOutlineModeResult.pdf", FileMode.Create - ); - PdfWriter writer = new PdfWriter(fos); + PdfReader reader = new PdfReader(filename); + PdfWriter writer = new PdfWriter(destinationFolder + "addOutlinesWithoutOutlineModeResult.pdf"); PdfDocument pdfDoc = new PdfDocument(reader, writer); PdfOutline outlines = new PdfOutline(pdfDoc); PdfOutline firstPage = outlines.AddOutline("firstPage"); @@ -187,8 +170,7 @@ public virtual void SetupAddOutlineInNotOutlineMode() { [NUnit.Framework.Test] public virtual void AddOutlineInNotOutlineMode() { String filename = destinationFolder + "addOutlinesWithoutOutlineModeResult.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); - PdfDocument pdfDoc = new PdfDocument(reader); + PdfDocument pdfDoc = new PdfDocument(new PdfReader(filename)); IList pageOutlines = pdfDoc.GetPage(102).GetOutlines(true); try { NUnit.Framework.Assert.AreEqual(5, pageOutlines.Count); @@ -203,8 +185,7 @@ public virtual void AddOutlineInNotOutlineMode() { [NUnit.Framework.Test] public virtual void CreateDocWithOutlines() { String filename = destinationFolder + "documentWithOutlines.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); - PdfDocument pdfDoc = new PdfDocument(reader); + PdfDocument pdfDoc = new PdfDocument(new PdfReader(filename)); PdfOutline outlines = pdfDoc.GetOutlines(false); try { NUnit.Framework.Assert.AreEqual(2, outlines.GetAllChildren().Count); @@ -219,10 +200,8 @@ public virtual void CreateDocWithOutlines() { [NUnit.Framework.Test] [LogMessage(LogMessageConstant.SOURCE_DOCUMENT_HAS_ACROFORM_DICTIONARY)] public virtual void CopyPagesWithOutlines() { - PdfReader reader = new PdfReader(new FileStream(sourceFolder + "iphone_user_guide.pdf", FileMode.Open, FileAccess.Read - )); - PdfWriter writer = new PdfWriter(new FileStream(destinationFolder + "copyPagesWithOutlines01.pdf", FileMode.Create - )); + PdfReader reader = new PdfReader(sourceFolder + "iphone_user_guide.pdf"); + PdfWriter writer = new PdfWriter(destinationFolder + "copyPagesWithOutlines01.pdf"); PdfDocument pdfDoc = new PdfDocument(reader); PdfDocument pdfDoc1 = new PdfDocument(writer); IList pages = new List(); @@ -244,11 +223,9 @@ public virtual void CopyPagesWithOutlines() { /// [NUnit.Framework.Test] public virtual void AddOutlinesWithNamedDestinations01() { - PdfReader reader = new PdfReader(new FileStream(sourceFolder + "iphone_user_guide.pdf", FileMode.Open, FileAccess.Read - )); String filename = destinationFolder + "outlinesWithNamedDestinations01.pdf"; - FileStream fos = new FileStream(filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); + PdfReader reader = new PdfReader(sourceFolder + "iphone_user_guide.pdf"); + PdfWriter writer = new PdfWriter(filename); PdfDocument pdfDoc = new PdfDocument(reader, writer); PdfArray array1 = new PdfArray(); array1.Add(pdfDoc.GetPage(2).GetPdfObject()); @@ -288,9 +265,7 @@ public virtual void AddOutlinesWithNamedDestinations01() { [NUnit.Framework.Test] public virtual void AddOutlinesWithNamedDestinations02() { String filename = destinationFolder + "outlinesWithNamedDestinations02.pdf"; - FileStream fos = new FileStream(filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(filename)); PdfArray array1 = new PdfArray(); array1.Add(pdfDoc.AddNewPage().GetPdfObject()); array1.Add(PdfName.XYZ); diff --git a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfPagesTest.cs b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfPagesTest.cs index 284caa0617..d3698f873d 100644 --- a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfPagesTest.cs +++ b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfPagesTest.cs @@ -3,6 +3,8 @@ using System.IO; using iText.IO; using iText.Kernel; +using iText.Kernel.Pdf.Extgstate; +using iText.Kernel.Utils; using iText.Test; using iText.Test.Attributes; @@ -27,9 +29,7 @@ public static void Setup() { public virtual void SimplePagesTest() { String filename = "simplePagesTest.pdf"; int pageCount = 111; - FileStream fos = new FileStream(destinationFolder + filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(destinationFolder + filename)); for (int i = 0; i < pageCount; i++) { PdfPage page = pdfDoc.AddNewPage(); page.GetPdfObject().Put(PageNum, new PdfNumber(i + 1)); @@ -66,9 +66,7 @@ public virtual void SimplePagesTest() { public virtual void ReversePagesTest() { String filename = "reversePagesTest.pdf"; int pageCount = 111; - FileStream fos = new FileStream(destinationFolder + filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(destinationFolder + filename)); for (int i = pageCount; i > 0; i--) { PdfPage page = new PdfPage(pdfDoc, pdfDoc.GetDefaultPageSize()); pdfDoc.AddPage(1, page); @@ -79,6 +77,21 @@ public virtual void ReversePagesTest() { VerifyPagesOrder(destinationFolder + filename, pageCount); } + /// + [NUnit.Framework.Test] + public virtual void ReversePagesTest2() { + String filename = "1000PagesDocument_reversed.pdf"; + PdfDocument pdfDoc = new PdfDocument(new PdfReader(sourceFolder + "1000PagesDocument.pdf"), new PdfWriter( + destinationFolder + filename)); + for (int i = pdfDoc.GetNumberOfPages() - 1; i > 0; i--) { + PdfPage page = pdfDoc.RemovePage(i); + pdfDoc.AddPage(page); + } + pdfDoc.Close(); + new CompareTool().CompareByContent(destinationFolder + filename, sourceFolder + "cmp_" + filename, destinationFolder + , "diff"); + } + /// [NUnit.Framework.Test] public virtual void RandomObjectPagesTest() { @@ -95,9 +108,7 @@ public virtual void RandomObjectPagesTest() { indexes[index] = indexes[i_1]; indexes[i_1] = a; } - FileStream fos = new FileStream(destinationFolder + filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument document = new PdfDocument(writer); + PdfDocument document = new PdfDocument(new PdfWriter(destinationFolder + filename)); PdfPage[] pages = new PdfPage[pageCount]; for (int i_2 = 0; i_2 < indexes.Length; i_2++) { PdfPage page = document.AddNewPage(); @@ -134,9 +145,7 @@ public virtual void RandomNumberPagesTest() { indexes[index] = indexes[i_1]; indexes[i_1] = a; } - FileStream fos = new FileStream(destinationFolder + filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(destinationFolder + filename)); for (int i_2 = 0; i_2 < indexes.Length; i_2++) { PdfPage page = pdfDoc.AddNewPage(); page.GetPdfObject().Put(PageNum, new PdfNumber(indexes[i_2])); @@ -208,9 +217,7 @@ public virtual void AddFlushedPageTest() { public virtual void RemoveFlushedPage() { String filename = "removeFlushedPage.pdf"; int pageCount = 10; - FileStream fos = new FileStream(destinationFolder + filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(destinationFolder + filename)); PdfPage removedPage = pdfDoc.AddNewPage(); int removedPageObjectNumber = removedPage.GetPdfObject().GetIndirectReference().GetObjNumber(); removedPage.Flush(); @@ -239,7 +246,7 @@ internal virtual void VerifyPagesOrder(String filename, int numOfPages) { NUnit.Framework.Assert.AreEqual(i, number.IntValue(), "Page number"); } NUnit.Framework.Assert.AreEqual(numOfPages, pdfDocument.GetNumberOfPages(), "Number of pages"); - reader.Close(); + pdfDocument.Close(); } internal virtual int VerifyIntegrity(PdfPagesTree pagesTree) { @@ -254,17 +261,17 @@ internal virtual int VerifyIntegrity(PdfPagesTree pagesTree) { return -1; } - // @Test@Ignore - // public void testInheritedResources() throws IOException { - // String inputFileName1 = sourceFolder + "veraPDF-A003-a-pass.pdf"; - // PdfReader reader1 = new PdfReader(inputFileName1); - // PdfDocument inputPdfDoc1 = new PdfDocument(reader1); - // PdfPage page = inputPdfDoc1.getPage(1); - // List list = page.getResources().getFonts(true); - // Assert.assertEquals(1, list.size()); - // Assert.assertEquals("ASJKFO+Arial-BoldMT", list.get(0).getFontProgram().getFontNames().getFontName()); - // } - // + /// + [NUnit.Framework.Test] + public virtual void TestInheritedResources() { + PdfDocument pdfDocument = new PdfDocument(new PdfReader(sourceFolder + "simpleInheritedResources.pdf")); + PdfPage page = pdfDocument.GetPage(1); + PdfDictionary dict = page.GetResources().GetResource(PdfName.ExtGState); + NUnit.Framework.Assert.AreEqual(2, dict.Size()); + PdfExtGState gState = new PdfExtGState((PdfDictionary)dict.Get(new PdfName("Gs1"))); + NUnit.Framework.Assert.AreEqual(10, gState.GetLineWidth()); + } + // @Test(expected = PdfException.class) // public void testCircularReferencesInResources() throws IOException { // String inputFileName1 = sourceFolder + "circularReferencesInResources.pdf"; @@ -274,24 +281,23 @@ internal virtual int VerifyIntegrity(PdfPagesTree pagesTree) { // List list = page.getResources().getFonts(true); // } // - // @Test@Ignore - // public void testInheritedResourcesUpdate() throws IOException { - // String inputFileName1 = sourceFolder + "veraPDF-A003-a-pass.pdf"; - // PdfReader reader1 = new PdfReader(inputFileName1); - // - // FileOutputStream fos = new FileOutputStream(destinationFolder + "veraPDF-A003-a-pass_new.pdf"); - // PdfWriter writer = new PdfWriter(fos); - // writer.setCompressionLevel(PdfOutputStream.NO_COMPRESSION); - // PdfDocument pdfDoc = new PdfDocument(reader1, writer); - // pdfDoc.getPage(1).getResources().getFonts(true); - // PdfFont f = PdfFont.createFont((PdfDictionary) pdfDoc.getPdfObject(6)); - // pdfDoc.getPage(1).getResources().addFont(pdfDoc, f); - // int fontCount = pdfDoc.getPage(1).getResources().getFonts(false).size(); - // pdfDoc.getPage(1).flush(); - // pdfDoc.close(); - // - // Assert.assertEquals(2, fontCount); - // } + /// + /// + [NUnit.Framework.Test] + public virtual void TestInheritedResourcesUpdate() { + PdfDocument pdfDoc = new PdfDocument(new PdfReader(sourceFolder + "simpleInheritedResources.pdf"), new PdfWriter + (destinationFolder + "updateInheritedResources.pdf").SetCompressionLevel(CompressionConstants.NO_COMPRESSION + )); + PdfName newGsName = pdfDoc.GetPage(1).GetResources().AddExtGState(new PdfExtGState().SetLineWidth(30)); + int gsCount = pdfDoc.GetPage(1).GetResources().GetResource(PdfName.ExtGState).Size(); + pdfDoc.Close(); + String compareResult = new CompareTool().CompareByContent(destinationFolder + "updateInheritedResources.pdf" + , sourceFolder + "cmp_" + "updateInheritedResources.pdf", destinationFolder, "diff"); + NUnit.Framework.Assert.AreEqual(3, gsCount); + NUnit.Framework.Assert.AreEqual("Gs3", newGsName.GetValue()); + NUnit.Framework.Assert.IsNull(compareResult); + } + /// [NUnit.Framework.Test] public virtual void GetPageByDictionary() { @@ -321,6 +327,20 @@ public virtual void RemovePageWithFormFieldsTest() { PdfDictionary kid = (PdfDictionary)field.GetAsArray(PdfName.Kids).Get(0); NUnit.Framework.Assert.AreEqual(6, kid.KeySet().Count); NUnit.Framework.Assert.AreEqual(3, fields.Size()); + pdfDoc.Close(); + } + + /// + [NUnit.Framework.Test] + public virtual void GetPageSizeWithInheritedMediaBox() { + double eps = 0.0000001; + String filename = sourceFolder + "inheritedMediaBox.pdf"; + PdfDocument pdfDoc = new PdfDocument(new PdfReader(filename)); + NUnit.Framework.Assert.AreEqual(0, pdfDoc.GetPage(1).GetPageSize().GetLeft(), eps); + NUnit.Framework.Assert.AreEqual(0, pdfDoc.GetPage(1).GetPageSize().GetBottom(), eps); + NUnit.Framework.Assert.AreEqual(595, pdfDoc.GetPage(1).GetPageSize().GetRight(), eps); + NUnit.Framework.Assert.AreEqual(842, pdfDoc.GetPage(1).GetPageSize().GetTop(), eps); + pdfDoc.Close(); } } } diff --git a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfPrimitivesTest.cs b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfPrimitivesTest.cs index 6721858705..690a26e511 100644 --- a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfPrimitivesTest.cs +++ b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfPrimitivesTest.cs @@ -1,7 +1,9 @@ using System; -using System.IO; using System.Text; +using iText.IO; +using iText.IO.Source; using iText.Test; +using iText.Test.Attributes; namespace iText.Kernel.Pdf { public class PdfPrimitivesTest : ExtendedITextTest { @@ -59,9 +61,7 @@ public virtual void Setup() { [NUnit.Framework.Test] public virtual void PrimitivesFloatNumberTest() { String filename = "primitivesFloatNumberTest.pdf"; - FileStream fos = new FileStream(destinationFolder + filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(destinationFolder + filename)); for (int i = 0; i < PageCount; i++) { PdfPage page = pdfDoc.AddNewPage(); PdfArray array = GeneratePdfArrayWithFloatNumbers(null, false); @@ -76,9 +76,7 @@ public virtual void PrimitivesFloatNumberTest() { [NUnit.Framework.Test] public virtual void PrimitivesIntNumberTest() { String filename = "primitivesIntNumberTest.pdf"; - FileStream fos = new FileStream(destinationFolder + filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(destinationFolder + filename)); for (int i = 0; i < PageCount; i++) { PdfPage page = pdfDoc.AddNewPage(); PdfArray array = GeneratePdfArrayWithIntNumbers(null, false); @@ -93,9 +91,7 @@ public virtual void PrimitivesIntNumberTest() { [NUnit.Framework.Test] public virtual void PrimitivesNameTest() { String filename = "primitivesNameTest.pdf"; - FileStream fos = new FileStream(destinationFolder + filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(destinationFolder + filename)); for (int i = 0; i < PageCount; i++) { PdfPage page = pdfDoc.AddNewPage(); PdfArray array = GeneratePdfArrayWithNames(null, false); @@ -110,9 +106,7 @@ public virtual void PrimitivesNameTest() { [NUnit.Framework.Test] public virtual void PrimitivesStringTest() { String filename = "primitivesStringTest.pdf"; - FileStream fos = new FileStream(destinationFolder + filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(destinationFolder + filename)); for (int i = 0; i < PageCount; i++) { PdfPage page = pdfDoc.AddNewPage(); PdfArray array = GeneratePdfArrayWithStrings(null, false); @@ -127,9 +121,7 @@ public virtual void PrimitivesStringTest() { [NUnit.Framework.Test] public virtual void PrimitivesBooleanTest() { String filename = "primitivesBooleanTest.pdf"; - FileStream fos = new FileStream(destinationFolder + filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(destinationFolder + filename)); for (int i = 0; i < PageCount; i++) { PdfPage page = pdfDoc.AddNewPage(); page.GetPdfObject().Put(TestArray, GeneratePdfArrayWithBooleans(null, false)); @@ -142,9 +134,7 @@ public virtual void PrimitivesBooleanTest() { [NUnit.Framework.Test] public virtual void PrimitivesFloatNumberIndirectTest() { String filename = "primitivesFloatNumberIndirectTest.pdf"; - FileStream fos = new FileStream(destinationFolder + filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(destinationFolder + filename)); for (int i = 0; i < PageCount; i++) { PdfPage page = pdfDoc.AddNewPage(); page.GetPdfObject().Put(TestArray, GeneratePdfArrayWithFloatNumbers(pdfDoc, true)); @@ -157,9 +147,7 @@ public virtual void PrimitivesFloatNumberIndirectTest() { [NUnit.Framework.Test] public virtual void PrimitivesIntNumberIndirectTest() { String filename = "primitivesIntNumberIndirectTest.pdf"; - FileStream fos = new FileStream(destinationFolder + filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(destinationFolder + filename)); for (int i = 0; i < PageCount; i++) { PdfPage page = pdfDoc.AddNewPage(); page.GetPdfObject().Put(TestArray, GeneratePdfArrayWithIntNumbers(pdfDoc, true)); @@ -172,9 +160,7 @@ public virtual void PrimitivesIntNumberIndirectTest() { [NUnit.Framework.Test] public virtual void PrimitivesStringIndirectTest() { String filename = "primitivesStringIndirectTest.pdf"; - FileStream fos = new FileStream(destinationFolder + filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(destinationFolder + filename)); for (int i = 0; i < PageCount; i++) { PdfPage page = pdfDoc.AddNewPage(); page.GetPdfObject().Put(TestArray, GeneratePdfArrayWithStrings(pdfDoc, true)); @@ -187,9 +173,7 @@ public virtual void PrimitivesStringIndirectTest() { [NUnit.Framework.Test] public virtual void PrimitivesNameIndirectTest() { String filename = "primitivesNameIndirectTest.pdf"; - FileStream fos = new FileStream(destinationFolder + filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(destinationFolder + filename)); for (int i = 0; i < PageCount; i++) { PdfPage page = pdfDoc.AddNewPage(); page.GetPdfObject().Put(TestArray, GeneratePdfArrayWithNames(pdfDoc, true)); @@ -202,9 +186,7 @@ public virtual void PrimitivesNameIndirectTest() { [NUnit.Framework.Test] public virtual void PrimitivesBooleanIndirectTest() { String filename = "primitivesBooleanIndirectTest.pdf"; - FileStream fos = new FileStream(destinationFolder + filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(destinationFolder + filename)); for (int i = 0; i < PageCount; i++) { PdfPage page = pdfDoc.AddNewPage(); page.GetPdfObject().Put(TestArray, GeneratePdfArrayWithBooleans(pdfDoc, true)); @@ -221,6 +203,61 @@ public virtual void PdfNamesTest() { } } + [NUnit.Framework.Test] + public virtual void EqualStrings() { + PdfString a = ((PdfString)new PdfString("abcd").MakeIndirect(new PdfDocument(new PdfWriter(new ByteArrayOutputStream + ())))); + PdfString b = new PdfString("abcd".GetBytes(Encoding.ASCII)); + NUnit.Framework.Assert.IsTrue(a.Equals(b)); + PdfString c = new PdfString("abcd", "UTF-8"); + NUnit.Framework.Assert.IsFalse(c.Equals(a)); + } + + [NUnit.Framework.Test] + [LogMessage(LogMessageConstant.CALCULATE_HASHCODE_FOR_MODIFIED_PDFNUMBER)] + public virtual void EqualNumbers() { + PdfNumber num1 = ((PdfNumber)new PdfNumber(1).MakeIndirect(new PdfDocument(new PdfWriter(new ByteArrayOutputStream + ())))); + PdfNumber num2 = new PdfNumber(2); + NUnit.Framework.Assert.IsFalse(num1.Equals(num2)); + int hashCode = num1.GetHashCode(); + num1.Increment(); + NUnit.Framework.Assert.IsTrue(num1.Equals(num2)); + NUnit.Framework.Assert.AreNotEqual(hashCode, num1.GetHashCode()); + } + + [NUnit.Framework.Test] + public virtual void EqualNames() { + PdfName a = ((PdfName)new PdfName("abcd").MakeIndirect(new PdfDocument(new PdfWriter(new ByteArrayOutputStream + ())))); + PdfName b = new PdfName("abcd"); + NUnit.Framework.Assert.IsTrue(a.Equals(b)); + } + + [NUnit.Framework.Test] + public virtual void EqualBoolean() { + PdfBoolean f = ((PdfBoolean)new PdfBoolean(false).MakeIndirect(new PdfDocument(new PdfWriter(new ByteArrayOutputStream + ())))); + PdfBoolean t = new PdfBoolean(true); + NUnit.Framework.Assert.IsFalse(f.Equals(t)); + NUnit.Framework.Assert.IsTrue(f.Equals(PdfBoolean.FALSE)); + NUnit.Framework.Assert.IsTrue(t.Equals(PdfBoolean.TRUE)); + } + + [NUnit.Framework.Test] + public virtual void EqualNulls() { + PdfNull a = ((PdfNull)new PdfNull().MakeIndirect(new PdfDocument(new PdfWriter(new ByteArrayOutputStream() + )))); + NUnit.Framework.Assert.IsTrue(a.Equals(PdfNull.PDF_NULL)); + } + + [NUnit.Framework.Test] + public virtual void EqualLiterals() { + PdfLiteral a = new PdfLiteral("abcd"); + PdfLiteral b = new PdfLiteral("abcd".GetBytes(Encoding.ASCII)); + NUnit.Framework.Assert.IsTrue(a.Equals(b)); + } + private PdfArray GeneratePdfArrayWithFloatNumbers(PdfDocument doc, bool indirects) { PdfArray array = ((PdfArray)new PdfArray().MakeIndirect(doc)); Random rnd = new Random(); diff --git a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfReaderTest.cs b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfReaderTest.cs index 3b1d540413..937047d736 100644 --- a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfReaderTest.cs +++ b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfReaderTest.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.IO; using iText.IO; using iText.IO.Source; using iText.Kernel; @@ -29,13 +28,11 @@ public static void BeforeClass() { [NUnit.Framework.Test] public virtual void OpenSimpleDoc() { String filename = destinationFolder + "openSimpleDoc.pdf"; - FileStream fos = new FileStream(filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(filename)); pdfDoc.GetDocumentInfo().SetAuthor(author).SetCreator(creator).SetTitle(title); pdfDoc.AddNewPage(); pdfDoc.Close(); - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); + PdfReader reader = new PdfReader(filename); pdfDoc = new PdfDocument(reader); NUnit.Framework.Assert.AreEqual(author, pdfDoc.GetDocumentInfo().GetAuthor()); NUnit.Framework.Assert.AreEqual(creator, pdfDoc.GetDocumentInfo().GetCreator()); @@ -60,7 +57,7 @@ public virtual void OpenSimpleDoc() { [NUnit.Framework.Test] public virtual void OpenSimpleDocWithFullCompression() { String filename = sourceFolder + "simpleCanvasWithFullCompression.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); + PdfReader reader = new PdfReader(filename); PdfDocument pdfDoc = new PdfDocument(reader); PdfObject @object = pdfDoc.GetPdfObject(1); NUnit.Framework.Assert.AreEqual(PdfObject.DICTIONARY, @object.GetObjectType()); @@ -86,7 +83,7 @@ public virtual void OpenSimpleDocWithFullCompression() { [NUnit.Framework.Test] public virtual void OpenDocWithFlateFilter() { String filename = sourceFolder + "100PagesDocumentWithFlateFilter.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); + PdfReader reader = new PdfReader(filename); PdfDocument document = new PdfDocument(reader); NUnit.Framework.Assert.AreEqual(100, document.GetNumberOfPages(), "Page count"); String contentTemplate = "q\n" + "BT\n" + "36 700 Td\n" + "/F1 72 Tf\n" + "({0})Tj\n" + "ET\n" + "Q\n" + "100 500 100 100 re\n" @@ -99,7 +96,6 @@ public virtual void OpenDocWithFlateFilter() { } NUnit.Framework.Assert.IsFalse(reader.HasRebuiltXref(), "No need in rebuildXref()"); NUnit.Framework.Assert.IsFalse(reader.HasFixedXref(), "No need in fixXref()"); - reader.Close(); document.Close(); } @@ -107,14 +103,12 @@ public virtual void OpenDocWithFlateFilter() { [NUnit.Framework.Test] public virtual void PrimitivesRead() { String filename = destinationFolder + "primitivesRead.pdf"; - FileStream fos = new FileStream(filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument document = new PdfDocument(writer); + PdfDocument document = new PdfDocument(new PdfWriter(filename)); document.AddNewPage(); PdfDictionary catalog = document.GetCatalog().GetPdfObject(); catalog.Put(new PdfName("a"), ((PdfBoolean)new PdfBoolean(true).MakeIndirect(document))); document.Close(); - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); + PdfReader reader = new PdfReader(filename); document = new PdfDocument(reader); PdfObject @object = document.GetXref().Get(1).GetRefersTo(); NUnit.Framework.Assert.AreEqual(PdfObject.DICTIONARY, @object.GetObjectType()); @@ -132,7 +126,6 @@ public virtual void PrimitivesRead() { NUnit.Framework.Assert.AreEqual(PdfObject.BOOLEAN, @object.GetObjectType()); NUnit.Framework.Assert.IsNotNull(@object.GetIndirectReference()); NUnit.Framework.Assert.IsFalse(reader.HasRebuiltXref(), "No need in rebuildXref()"); - reader.Close(); document.Close(); } @@ -140,9 +133,7 @@ public virtual void PrimitivesRead() { [NUnit.Framework.Test] public virtual void IndirectsChain1() { String filename = destinationFolder + "indirectsChain1.pdf"; - FileStream fos = new FileStream(filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument document = new PdfDocument(writer); + PdfDocument document = new PdfDocument(new PdfWriter(filename)); document.AddNewPage(); PdfDictionary catalog = document.GetCatalog().GetPdfObject(); PdfObject pdfObject = GetTestPdfDictionary(); @@ -151,7 +142,7 @@ public virtual void IndirectsChain1() { } catalog.Put(new PdfName("a"), pdfObject); document.Close(); - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); + PdfReader reader = new PdfReader(filename); document = new PdfDocument(reader); pdfObject = document.GetXref().Get(1).GetRefersTo(); NUnit.Framework.Assert.AreEqual(PdfObject.DICTIONARY, pdfObject.GetObjectType()); @@ -170,7 +161,6 @@ public virtual void IndirectsChain1() { ()); } NUnit.Framework.Assert.IsFalse(reader.HasRebuiltXref(), "No need in rebuildXref()"); - reader.Close(); document.Close(); } @@ -178,9 +168,7 @@ public virtual void IndirectsChain1() { [NUnit.Framework.Test] public virtual void IndirectsChain2() { String filename = destinationFolder + "indirectsChain2.pdf"; - FileStream fos = new FileStream(filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument document = new PdfDocument(writer); + PdfDocument document = new PdfDocument(new PdfWriter(filename)); document.AddNewPage(); PdfDictionary catalog = document.GetCatalog().GetPdfObject(); PdfObject pdfObject = GetTestPdfDictionary(); @@ -189,7 +177,7 @@ public virtual void IndirectsChain2() { } catalog.Put(new PdfName("a"), pdfObject); document.Close(); - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); + PdfReader reader = new PdfReader(filename); document = new PdfDocument(reader); pdfObject = document.GetXref().Get(1).GetRefersTo(); NUnit.Framework.Assert.AreEqual(PdfObject.DICTIONARY, pdfObject.GetObjectType()); @@ -212,7 +200,6 @@ public virtual void IndirectsChain2() { ()); } NUnit.Framework.Assert.IsFalse(reader.HasRebuiltXref(), "No need in rebuildXref()"); - reader.Close(); document.Close(); } @@ -220,7 +207,7 @@ public virtual void IndirectsChain2() { [NUnit.Framework.Test] public virtual void IndirectsChain3() { String filename = sourceFolder + "indirectsChain3.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); + PdfReader reader = new PdfReader(filename); PdfDocument document = new PdfDocument(reader); PdfObject @object = document.GetXref().Get(1).GetRefersTo(); NUnit.Framework.Assert.AreEqual(PdfObject.DICTIONARY, @object.GetObjectType()); @@ -241,7 +228,6 @@ public virtual void IndirectsChain3() { ()); } NUnit.Framework.Assert.IsFalse(reader.HasRebuiltXref(), "No need in rebuildXref()"); - reader.Close(); document.Close(); } @@ -249,7 +235,7 @@ public virtual void IndirectsChain3() { [NUnit.Framework.Test] public virtual void InvalidIndirect() { String filename = sourceFolder + "invalidIndirect.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); + PdfReader reader = new PdfReader(filename); PdfDocument document = new PdfDocument(reader); PdfObject @object = document.GetXref().Get(1).GetRefersTo(); NUnit.Framework.Assert.AreEqual(PdfObject.DICTIONARY, @object.GetObjectType()); @@ -269,7 +255,6 @@ public virtual void InvalidIndirect() { NUnit.Framework.Assert.IsNull(document.GetXref().Get(i).GetRefersTo()); } NUnit.Framework.Assert.IsFalse(reader.HasRebuiltXref(), "No need in rebuildXref()"); - reader.Close(); document.Close(); } @@ -277,7 +262,7 @@ public virtual void InvalidIndirect() { [NUnit.Framework.Test] public virtual void PagesTest01() { String filename = sourceFolder + "1000PagesDocument.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); + PdfReader reader = new PdfReader(filename); PdfWriter writer = new PdfWriter(new ByteArrayOutputStream()); PdfDocument document = new PdfDocument(reader, writer); int pageCount = document.GetNumberOfPages(); @@ -298,7 +283,7 @@ public virtual void PagesTest01() { NUnit.Framework.Assert.IsTrue(content.Contains("(" + i_1 + ")")); } reader.Close(); - reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); + reader = new PdfReader(filename); document = new PdfDocument(reader); for (int i_2 = 1; i_2 < pageCount + 1; i_2++) { int pageNum = document.GetNumberOfPages(); @@ -307,14 +292,14 @@ public virtual void PagesTest01() { NUnit.Framework.Assert.IsTrue(content.Contains("(" + pageNum + ")")); } NUnit.Framework.Assert.IsFalse(reader.HasRebuiltXref(), "No need in rebuildXref()"); - reader.Close(); + document.Close(); } /// [NUnit.Framework.Test] public virtual void PagesTest02() { String filename = sourceFolder + "1000PagesDocumentWithFullCompression.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); + PdfReader reader = new PdfReader(filename); PdfDocument document = new PdfDocument(reader); int pageCount = document.GetNumberOfPages(); NUnit.Framework.Assert.AreEqual(1000, pageCount); @@ -329,9 +314,8 @@ public virtual void PagesTest02() { NUnit.Framework.Assert.IsTrue(content.Contains("(" + i_1 + ")")); } NUnit.Framework.Assert.IsFalse(reader.HasRebuiltXref(), "No need in rebuildXref()"); - reader.Close(); document.Close(); - reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); + reader = new PdfReader(filename); document = new PdfDocument(reader); for (int i_2 = 1; i_2 < pageCount + 1; i_2++) { int pageNum = document.GetNumberOfPages(); @@ -339,7 +323,6 @@ public virtual void PagesTest02() { String content = iText.IO.Util.JavaUtil.GetStringForBytes(page.GetContentStream(0).GetBytes()); NUnit.Framework.Assert.IsTrue(content.Contains("(" + pageNum + ")")); } - reader.Close(); document.Close(); } @@ -347,7 +330,7 @@ public virtual void PagesTest02() { [NUnit.Framework.Test] public virtual void PagesTest03() { String filename = sourceFolder + "10PagesDocumentWithLeafs.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); + PdfReader reader = new PdfReader(filename); PdfDocument document = new PdfDocument(reader); int pageCount = document.GetNumberOfPages(); NUnit.Framework.Assert.AreEqual(10, pageCount); @@ -362,9 +345,8 @@ public virtual void PagesTest03() { NUnit.Framework.Assert.IsTrue(content.Contains("(" + i_1 + ")")); } NUnit.Framework.Assert.IsFalse(reader.HasRebuiltXref(), "No need in rebuildXref()"); - reader.Close(); document.Close(); - reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); + reader = new PdfReader(filename); document = new PdfDocument(reader); for (int i_2 = 1; i_2 < pageCount + 1; i_2++) { int pageNum = document.GetNumberOfPages(); @@ -373,7 +355,6 @@ public virtual void PagesTest03() { NUnit.Framework.Assert.IsTrue(content.Contains("(" + pageNum + ")")); } NUnit.Framework.Assert.IsFalse(reader.HasRebuiltXref(), "No need in rebuildXref()"); - reader.Close(); document.Close(); } @@ -381,7 +362,7 @@ public virtual void PagesTest03() { [NUnit.Framework.Test] public virtual void PagesTest04() { String filename = sourceFolder + "PagesDocument.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); + PdfReader reader = new PdfReader(filename); PdfDocument document = new PdfDocument(reader); int pageCount = document.GetNumberOfPages(); NUnit.Framework.Assert.AreEqual(3, pageCount); @@ -396,9 +377,8 @@ public virtual void PagesTest04() { NUnit.Framework.Assert.IsTrue(content.StartsWith(i_1 + "00")); } NUnit.Framework.Assert.IsFalse(reader.HasRebuiltXref(), "No need in rebuildXref()"); - reader.Close(); document.Close(); - reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); + reader = new PdfReader(filename); document = new PdfDocument(reader); for (int i_2 = 1; i_2 < pageCount + 1; i_2++) { int pageNum = document.GetNumberOfPages(); @@ -407,7 +387,6 @@ public virtual void PagesTest04() { NUnit.Framework.Assert.IsTrue(content.StartsWith(pageNum + "00")); } NUnit.Framework.Assert.IsFalse(reader.HasRebuiltXref(), "No need in rebuildXref()"); - reader.Close(); document.Close(); } @@ -415,7 +394,7 @@ public virtual void PagesTest04() { [NUnit.Framework.Test] public virtual void PagesTest05() { String filename = sourceFolder + "PagesDocument05.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); + PdfReader reader = new PdfReader(filename); PdfDocument document = new PdfDocument(reader); int pageCount = document.GetNumberOfPages(); NUnit.Framework.Assert.AreEqual(3, pageCount); @@ -430,9 +409,8 @@ public virtual void PagesTest05() { NUnit.Framework.Assert.IsTrue(content.StartsWith(i_1 + "00")); } NUnit.Framework.Assert.IsFalse(reader.HasRebuiltXref(), "No need in rebuildXref()"); - reader.Close(); document.Close(); - reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); + reader = new PdfReader(filename); document = new PdfDocument(reader); for (int i_2 = 1; i_2 < pageCount + 1; i_2++) { int pageNum = document.GetNumberOfPages(); @@ -441,7 +419,6 @@ public virtual void PagesTest05() { NUnit.Framework.Assert.IsTrue(content.StartsWith(pageNum + "00")); } NUnit.Framework.Assert.IsFalse(reader.HasRebuiltXref(), "No need in rebuildXref()"); - reader.Close(); document.Close(); } @@ -449,8 +426,7 @@ public virtual void PagesTest05() { [NUnit.Framework.Test] public virtual void PagesTest06() { String filename = sourceFolder + "PagesDocument06.pdf"; - Stream stream = new FileStream(filename, FileMode.Open, FileAccess.Read); - PdfReader reader = new PdfReader(stream); + PdfReader reader = new PdfReader(filename); PdfDocument document = new PdfDocument(reader); int pageCount = document.GetNumberOfPages(); NUnit.Framework.Assert.AreEqual(2, pageCount); @@ -461,9 +437,8 @@ public virtual void PagesTest06() { content = iText.IO.Util.JavaUtil.GetStringForBytes(page.GetContentStream(0).GetBytes()); NUnit.Framework.Assert.IsTrue(content.StartsWith("300")); NUnit.Framework.Assert.IsFalse(reader.HasRebuiltXref(), "No need in rebuildXref()"); - reader.Close(); document.Close(); - reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); + reader = new PdfReader(filename); document = new PdfDocument(reader); page = document.RemovePage(2); content = iText.IO.Util.JavaUtil.GetStringForBytes(page.GetContentStream(0).GetBytes()); @@ -472,7 +447,6 @@ public virtual void PagesTest06() { content = iText.IO.Util.JavaUtil.GetStringForBytes(page.GetContentStream(0).GetBytes()); NUnit.Framework.Assert.IsTrue(content.StartsWith("100")); NUnit.Framework.Assert.IsFalse(reader.HasRebuiltXref(), "No need in rebuildXref()"); - reader.Close(); document.Close(); } @@ -480,8 +454,7 @@ public virtual void PagesTest06() { [NUnit.Framework.Test] public virtual void PagesTest07() { String filename = sourceFolder + "PagesDocument07.pdf"; - Stream stream = new FileStream(filename, FileMode.Open, FileAccess.Read); - PdfReader reader = new PdfReader(stream); + PdfReader reader = new PdfReader(filename); PdfDocument document = new PdfDocument(reader); int pageCount = document.GetNumberOfPages(); NUnit.Framework.Assert.AreEqual(2, pageCount); @@ -494,7 +467,6 @@ public virtual void PagesTest07() { } NUnit.Framework.Assert.IsTrue(exception); NUnit.Framework.Assert.IsFalse(reader.HasRebuiltXref(), "No need in rebuildXref()"); - reader.Close(); document.Close(); } @@ -502,8 +474,7 @@ public virtual void PagesTest07() { [NUnit.Framework.Test] public virtual void PagesTest08() { String filename = sourceFolder + "PagesDocument08.pdf"; - Stream stream = new FileStream(filename, FileMode.Open, FileAccess.Read); - PdfReader reader = new PdfReader(stream); + PdfReader reader = new PdfReader(filename); PdfDocument document = new PdfDocument(reader); int pageCount = document.GetNumberOfPages(); NUnit.Framework.Assert.AreEqual(1, pageCount); @@ -516,7 +487,6 @@ public virtual void PagesTest08() { } NUnit.Framework.Assert.IsTrue(exception); NUnit.Framework.Assert.IsFalse(reader.HasRebuiltXref(), "No need in rebuildXref()"); - reader.Close(); document.Close(); } @@ -524,8 +494,7 @@ public virtual void PagesTest08() { [NUnit.Framework.Test] public virtual void PagesTest09() { String filename = sourceFolder + "PagesDocument09.pdf"; - Stream stream = new FileStream(filename, FileMode.Open, FileAccess.Read); - PdfReader reader = new PdfReader(stream); + PdfReader reader = new PdfReader(filename); PdfDocument document = new PdfDocument(reader); int pageCount = document.GetNumberOfPages(); NUnit.Framework.Assert.AreEqual(1, pageCount); @@ -536,7 +505,6 @@ public virtual void PagesTest09() { content = iText.IO.Util.JavaUtil.GetStringForBytes(page.GetContentStream(0).GetBytes()); NUnit.Framework.Assert.IsTrue(content.StartsWith("100")); NUnit.Framework.Assert.IsFalse(reader.HasRebuiltXref(), "No need in rebuildXref()"); - reader.Close(); document.Close(); } @@ -544,7 +512,7 @@ public virtual void PagesTest09() { [NUnit.Framework.Test] public virtual void PagesTest10() { String filename = sourceFolder + "1000PagesDocumentWithFullCompression.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); + PdfReader reader = new PdfReader(filename); PdfDocument document = new PdfDocument(reader); int pageCount = document.GetNumberOfPages(); NUnit.Framework.Assert.AreEqual(1000, pageCount); @@ -567,7 +535,6 @@ public virtual void PagesTest10() { NUnit.Framework.Assert.IsTrue(content.Contains("(" + pageNum + ")")); } NUnit.Framework.Assert.IsFalse(reader.HasRebuiltXref(), "No need in rebuildXref()"); - reader.Close(); document.Close(); } @@ -576,14 +543,13 @@ public virtual void PagesTest10() { [LogMessage(LogMessageConstant.XREF_ERROR, Count = 1)] public virtual void CorrectSimpleDoc1() { String filename = sourceFolder + "correctSimpleDoc1.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); + PdfReader reader = new PdfReader(filename); PdfDocument document = new PdfDocument(reader); NUnit.Framework.Assert.IsTrue(reader.HasRebuiltXref(), "Need rebuildXref()"); int pageCount = document.GetNumberOfPages(); NUnit.Framework.Assert.AreEqual(1, pageCount); PdfPage page = document.GetPage(1); NUnit.Framework.Assert.IsNotNull(page.GetContentStream(0).GetBytes()); - reader.Close(); document.Close(); } @@ -591,14 +557,13 @@ public virtual void CorrectSimpleDoc1() { [NUnit.Framework.Test] public virtual void CorrectSimpleDoc2() { String filename = sourceFolder + "correctSimpleDoc2.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); + PdfReader reader = new PdfReader(filename); PdfDocument document = new PdfDocument(reader); NUnit.Framework.Assert.IsTrue(reader.HasFixedXref(), "Need fixXref()"); int pageCount = document.GetNumberOfPages(); NUnit.Framework.Assert.AreEqual(1, pageCount); PdfPage page = document.GetPage(1); NUnit.Framework.Assert.IsNotNull(page.GetContentStream(0).GetBytes()); - reader.Close(); document.Close(); } @@ -607,14 +572,13 @@ public virtual void CorrectSimpleDoc2() { [LogMessage(LogMessageConstant.XREF_ERROR, Count = 1)] public virtual void CorrectSimpleDoc3() { String filename = sourceFolder + "correctSimpleDoc3.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); + PdfReader reader = new PdfReader(filename); PdfDocument document = new PdfDocument(reader); NUnit.Framework.Assert.IsTrue(reader.HasRebuiltXref(), "Need rebuildXref()"); int pageCount = document.GetNumberOfPages(); NUnit.Framework.Assert.AreEqual(1, pageCount); PdfPage page = document.GetPage(1); NUnit.Framework.Assert.IsNotNull(page.GetContentStream(0).GetBytes()); - reader.Close(); document.Close(); } @@ -624,14 +588,13 @@ public virtual void CorrectSimpleDoc3() { public virtual void CorrectSimpleDoc4() { //test with abnormal object declaration String filename = sourceFolder + "correctSimpleDoc4.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); + PdfReader reader = new PdfReader(filename); PdfDocument document = new PdfDocument(reader); NUnit.Framework.Assert.IsTrue(reader.HasRebuiltXref(), "Need rebuildXref()"); int pageCount = document.GetNumberOfPages(); NUnit.Framework.Assert.AreEqual(1, pageCount); PdfPage page = document.GetPage(1); NUnit.Framework.Assert.IsNotNull(page.GetContentStream(0).GetBytes()); - reader.Close(); document.Close(); } @@ -640,7 +603,7 @@ public virtual void CorrectSimpleDoc4() { [LogMessage(LogMessageConstant.XREF_ERROR, Count = 1)] public virtual void FixPdfTest01() { String filename = sourceFolder + "OnlyTrailer.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); + PdfReader reader = new PdfReader(filename); PdfDocument document = new PdfDocument(reader); NUnit.Framework.Assert.IsTrue(reader.HasRebuiltXref(), "Need rebuildXref()"); int pageCount = document.GetNumberOfPages(); @@ -650,7 +613,6 @@ public virtual void FixPdfTest01() { String content = iText.IO.Util.JavaUtil.GetStringForBytes(page.GetContentStream(0).GetBytes()); NUnit.Framework.Assert.IsTrue(content.Contains("(" + i + ")")); } - reader.Close(); document.Close(); } @@ -658,7 +620,7 @@ public virtual void FixPdfTest01() { [NUnit.Framework.Test] public virtual void FixPdfTest02() { String filename = sourceFolder + "CompressionShift1.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); + PdfReader reader = new PdfReader(filename); PdfDocument document = new PdfDocument(reader); NUnit.Framework.Assert.IsFalse(reader.HasFixedXref(), "No need in fixXref()"); NUnit.Framework.Assert.IsFalse(reader.HasRebuiltXref(), "No need in rebuildXref()"); @@ -669,7 +631,6 @@ public virtual void FixPdfTest02() { String content = iText.IO.Util.JavaUtil.GetStringForBytes(page.GetContentStream(0).GetBytes()); NUnit.Framework.Assert.IsTrue(content.Contains("(" + i + ")")); } - reader.Close(); document.Close(); } @@ -677,7 +638,7 @@ public virtual void FixPdfTest02() { [NUnit.Framework.Test] public virtual void FixPdfTest03() { String filename = sourceFolder + "CompressionShift2.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); + PdfReader reader = new PdfReader(filename); PdfDocument document = new PdfDocument(reader); NUnit.Framework.Assert.IsFalse(reader.HasFixedXref(), "No need in fixXref()"); NUnit.Framework.Assert.IsFalse(reader.HasRebuiltXref(), "No need in rebuildXref()"); @@ -688,7 +649,6 @@ public virtual void FixPdfTest03() { String content = iText.IO.Util.JavaUtil.GetStringForBytes(page.GetContentStream(0).GetBytes()); NUnit.Framework.Assert.IsTrue(content.Contains("(" + i + ")")); } - reader.Close(); document.Close(); } @@ -696,7 +656,7 @@ public virtual void FixPdfTest03() { [NUnit.Framework.Test] public virtual void FixPdfTest04() { String filename = sourceFolder + "CompressionWrongObjStm.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); + PdfReader reader = new PdfReader(filename); bool exception = false; try { new PdfDocument(reader); @@ -713,7 +673,7 @@ public virtual void FixPdfTest04() { [LogMessage(LogMessageConstant.XREF_ERROR, Count = 1)] public virtual void FixPdfTest05() { String filename = sourceFolder + "CompressionWrongShift.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); + PdfReader reader = new PdfReader(filename); bool exception = false; try { new PdfDocument(reader); @@ -729,7 +689,7 @@ public virtual void FixPdfTest05() { [NUnit.Framework.Test] public virtual void FixPdfTest06() { String filename = sourceFolder + "InvalidOffsets.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); + PdfReader reader = new PdfReader(filename); PdfDocument document = new PdfDocument(reader); NUnit.Framework.Assert.IsTrue(reader.HasFixedXref(), "Need fixXref()"); int pageCount = document.GetNumberOfPages(); @@ -739,7 +699,6 @@ public virtual void FixPdfTest06() { String content = iText.IO.Util.JavaUtil.GetStringForBytes(page.GetContentStream(0).GetBytes()); NUnit.Framework.Assert.IsTrue(content.Contains("(" + i + ")")); } - reader.Close(); document.Close(); } @@ -747,7 +706,7 @@ public virtual void FixPdfTest06() { [NUnit.Framework.Test] public virtual void FixPdfTest07() { String filename = sourceFolder + "XRefSectionWithFreeReferences1.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); + PdfReader reader = new PdfReader(filename); bool exception = false; try { new PdfDocument(reader); @@ -764,7 +723,7 @@ public virtual void FixPdfTest07() { [LogMessage(LogMessageConstant.XREF_ERROR, Count = 1)] public virtual void FixPdfTest08() { String filename = sourceFolder + "XRefSectionWithFreeReferences2.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); + PdfReader reader = new PdfReader(filename); PdfDocument document = new PdfDocument(reader); NUnit.Framework.Assert.IsTrue(reader.HasRebuiltXref(), "Need rebuildXref()"); NUnit.Framework.Assert.AreEqual(author, document.GetDocumentInfo().GetAuthor()); @@ -777,7 +736,6 @@ public virtual void FixPdfTest08() { String content = iText.IO.Util.JavaUtil.GetStringForBytes(page.GetContentStream(0).GetBytes()); NUnit.Framework.Assert.IsTrue(content.Contains("(" + i + ")")); } - reader.Close(); document.Close(); } @@ -786,7 +744,7 @@ public virtual void FixPdfTest08() { [LogMessage(LogMessageConstant.XREF_ERROR, Count = 1)] public virtual void FixPdfTest09() { String filename = sourceFolder + "XRefSectionWithFreeReferences3.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); + PdfReader reader = new PdfReader(filename); PdfDocument document = new PdfDocument(reader); NUnit.Framework.Assert.IsTrue(reader.HasRebuiltXref(), "Need rebuildXref()"); NUnit.Framework.Assert.AreEqual(author, document.GetDocumentInfo().GetAuthor()); @@ -799,7 +757,6 @@ public virtual void FixPdfTest09() { String content = iText.IO.Util.JavaUtil.GetStringForBytes(page.GetContentStream(0).GetBytes()); NUnit.Framework.Assert.IsTrue(content.Contains("(" + i + ")")); } - reader.Close(); document.Close(); } @@ -807,7 +764,7 @@ public virtual void FixPdfTest09() { [NUnit.Framework.Test] public virtual void FixPdfTest10() { String filename = sourceFolder + "XRefSectionWithFreeReferences4.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); + PdfReader reader = new PdfReader(filename); PdfDocument document = new PdfDocument(reader); NUnit.Framework.Assert.IsFalse(reader.HasFixedXref(), "No need in fixXref()"); NUnit.Framework.Assert.IsFalse(reader.HasRebuiltXref(), "No need in rebuildXref()"); @@ -821,7 +778,6 @@ public virtual void FixPdfTest10() { String content = iText.IO.Util.JavaUtil.GetStringForBytes(page.GetContentStream(0).GetBytes()); NUnit.Framework.Assert.IsTrue(content.Contains("(" + i + ")")); } - reader.Close(); document.Close(); } @@ -830,7 +786,7 @@ public virtual void FixPdfTest10() { [LogMessage(LogMessageConstant.XREF_ERROR, Count = 1)] public virtual void FixPdfTest11() { String filename = sourceFolder + "XRefSectionWithoutSize.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); + PdfReader reader = new PdfReader(filename); PdfDocument document = new PdfDocument(reader); NUnit.Framework.Assert.IsTrue(reader.HasRebuiltXref(), "Need rebuildXref()"); int pageCount = document.GetNumberOfPages(); @@ -840,7 +796,6 @@ public virtual void FixPdfTest11() { String content = iText.IO.Util.JavaUtil.GetStringForBytes(page.GetContentStream(0).GetBytes()); NUnit.Framework.Assert.IsTrue(content.Contains("(" + i + ")")); } - reader.Close(); document.Close(); } @@ -849,7 +804,7 @@ public virtual void FixPdfTest11() { [LogMessage(LogMessageConstant.XREF_ERROR, Count = 1)] public virtual void FixPdfTest12() { String filename = sourceFolder + "XRefWithBreaks.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); + PdfReader reader = new PdfReader(filename); PdfDocument document = new PdfDocument(reader); NUnit.Framework.Assert.IsTrue(reader.HasRebuiltXref(), "Need rebuildXref()"); int pageCount = document.GetNumberOfPages(); @@ -859,7 +814,6 @@ public virtual void FixPdfTest12() { String content = iText.IO.Util.JavaUtil.GetStringForBytes(page.GetContentStream(0).GetBytes()); NUnit.Framework.Assert.IsTrue(content.Contains("(" + i + ")")); } - reader.Close(); document.Close(); } @@ -868,7 +822,7 @@ public virtual void FixPdfTest12() { [LogMessage(LogMessageConstant.INVALID_INDIRECT_REFERENCE)] public virtual void FixPdfTest13() { String filename = sourceFolder + "XRefWithInvalidGenerations1.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); + PdfReader reader = new PdfReader(filename); PdfDocument document = new PdfDocument(reader); NUnit.Framework.Assert.IsFalse(reader.HasFixedXref(), "No need in fixXref()"); NUnit.Framework.Assert.IsFalse(reader.HasRebuiltXref(), "No need in rebuildXref()"); @@ -903,7 +857,6 @@ public virtual void FixPdfTest13() { exception = true; } NUnit.Framework.Assert.IsFalse(exception); - reader.Close(); document.Close(); } @@ -912,7 +865,7 @@ public virtual void FixPdfTest13() { [LogMessage(LogMessageConstant.INVALID_INDIRECT_REFERENCE)] public virtual void FixPdfTest14() { String filename = sourceFolder + "XRefWithInvalidGenerations2.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); + PdfReader reader = new PdfReader(filename); bool exception = false; try { new PdfDocument(reader); @@ -929,7 +882,7 @@ public virtual void FixPdfTest14() { [LogMessage(LogMessageConstant.XREF_ERROR, Count = 1)] public virtual void FixPdfTest15() { String filename = sourceFolder + "XRefWithInvalidGenerations3.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); + PdfReader reader = new PdfReader(filename); PdfDocument document = new PdfDocument(reader); NUnit.Framework.Assert.IsTrue(reader.HasRebuiltXref(), "Need rebuildXref()"); int pageCount = document.GetNumberOfPages(); @@ -939,7 +892,6 @@ public virtual void FixPdfTest15() { String content = iText.IO.Util.JavaUtil.GetStringForBytes(page.GetContentStream(0).GetBytes()); NUnit.Framework.Assert.IsTrue(content.Contains("(" + i + ")")); } - reader.Close(); document.Close(); } @@ -947,7 +899,7 @@ public virtual void FixPdfTest15() { [NUnit.Framework.Test] public virtual void FixPdfTest16() { String filename = sourceFolder + "XrefWithInvalidOffsets.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); + PdfReader reader = new PdfReader(filename); PdfDocument document = new PdfDocument(reader); NUnit.Framework.Assert.IsFalse(reader.HasFixedXref(), "No need in fixXref()"); int pageCount = document.GetNumberOfPages(); @@ -958,7 +910,6 @@ public virtual void FixPdfTest16() { NUnit.Framework.Assert.IsTrue(content.Contains("(" + i + ")")); } NUnit.Framework.Assert.IsTrue(reader.HasFixedXref(), "Need live fixXref()"); - reader.Close(); document.Close(); } @@ -967,7 +918,7 @@ public virtual void FixPdfTest16() { [LogMessage(LogMessageConstant.XREF_ERROR, Count = 1)] public virtual void FixPdfTest17() { String filename = sourceFolder + "XrefWithNullOffsets.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); + PdfReader reader = new PdfReader(filename); PdfDocument document = new PdfDocument(reader); NUnit.Framework.Assert.IsTrue(reader.HasRebuiltXref(), "Need rebuildXref()"); int pageCount = document.GetNumberOfPages(); @@ -977,7 +928,6 @@ public virtual void FixPdfTest17() { String content = iText.IO.Util.JavaUtil.GetStringForBytes(page.GetContentStream(0).GetBytes()); NUnit.Framework.Assert.IsTrue(content.Contains("(" + i + ")")); } - reader.Close(); document.Close(); } @@ -985,7 +935,7 @@ public virtual void FixPdfTest17() { [NUnit.Framework.Test] public virtual void AppendModeWith1000Pages() { String filename = sourceFolder + "1000PagesDocumentAppended.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); + PdfReader reader = new PdfReader(filename); PdfDocument document = new PdfDocument(reader); int pageCount = document.GetNumberOfPages(); NUnit.Framework.Assert.AreEqual(1000, pageCount); @@ -999,7 +949,6 @@ public virtual void AppendModeWith1000Pages() { NUnit.Framework.Assert.IsTrue(content.Contains("Append mode")); } NUnit.Framework.Assert.IsFalse(reader.HasRebuiltXref(), "No need in rebuildXref()"); - reader.Close(); document.Close(); } @@ -1007,7 +956,7 @@ public virtual void AppendModeWith1000Pages() { [NUnit.Framework.Test] public virtual void AppendModeWith1000PagesWithCompression() { String filename = sourceFolder + "1000PagesDocumentWithFullCompressionAppended.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); + PdfReader reader = new PdfReader(filename); PdfDocument document = new PdfDocument(reader); int pageCount = document.GetNumberOfPages(); NUnit.Framework.Assert.AreEqual(1000, pageCount); @@ -1021,7 +970,6 @@ public virtual void AppendModeWith1000PagesWithCompression() { NUnit.Framework.Assert.IsTrue(content.Contains("Append mode")); } NUnit.Framework.Assert.IsFalse(reader.HasRebuiltXref(), "No need in rebuildXref()"); - reader.Close(); document.Close(); } @@ -1029,7 +977,7 @@ public virtual void AppendModeWith1000PagesWithCompression() { [NUnit.Framework.Test] public virtual void AppendModeWith10Pages() { String filename = sourceFolder + "10PagesDocumentAppended.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); + PdfReader reader = new PdfReader(filename); PdfDocument document = new PdfDocument(reader); int pageCount = document.GetNumberOfPages(); NUnit.Framework.Assert.AreEqual(10, pageCount); @@ -1043,7 +991,6 @@ public virtual void AppendModeWith10Pages() { NUnit.Framework.Assert.IsTrue(content.Contains("Append mode")); } NUnit.Framework.Assert.IsFalse(reader.HasRebuiltXref(), "No need in rebuildXref()"); - reader.Close(); document.Close(); } @@ -1051,7 +998,7 @@ public virtual void AppendModeWith10Pages() { [NUnit.Framework.Test] public virtual void AppendModeWith10PagesWithCompression() { String filename = sourceFolder + "10PagesDocumentWithFullCompressionAppended.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); + PdfReader reader = new PdfReader(filename); PdfDocument document = new PdfDocument(reader); int pageCount = document.GetNumberOfPages(); NUnit.Framework.Assert.AreEqual(10, pageCount); @@ -1065,7 +1012,6 @@ public virtual void AppendModeWith10PagesWithCompression() { NUnit.Framework.Assert.IsTrue(content.Contains("Append mode")); } NUnit.Framework.Assert.IsFalse(reader.HasRebuiltXref(), "No need in rebuildXref()"); - reader.Close(); document.Close(); } @@ -1074,7 +1020,7 @@ public virtual void AppendModeWith10PagesWithCompression() { [LogMessage(LogMessageConstant.XREF_ERROR, Count = 1)] public virtual void AppendModeWith10PagesFix1() { String filename = sourceFolder + "10PagesDocumentAppendedFix1.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); + PdfReader reader = new PdfReader(filename); PdfDocument document = new PdfDocument(reader); int pageCount = document.GetNumberOfPages(); NUnit.Framework.Assert.AreEqual(10, pageCount); @@ -1089,7 +1035,6 @@ public virtual void AppendModeWith10PagesFix1() { } NUnit.Framework.Assert.IsTrue(reader.HasRebuiltXref(), "Need rebuildXref()"); NUnit.Framework.Assert.IsNotNull(document.GetTrailer().Get(PdfName.ID), "Invalid trailer"); - reader.Close(); document.Close(); } @@ -1098,7 +1043,7 @@ public virtual void AppendModeWith10PagesFix1() { [LogMessage(LogMessageConstant.XREF_ERROR, Count = 1)] public virtual void AppendModeWith10PagesFix2() { String filename = sourceFolder + "10PagesDocumentAppendedFix2.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); + PdfReader reader = new PdfReader(filename); PdfDocument document = new PdfDocument(reader); int pageCount = document.GetNumberOfPages(); NUnit.Framework.Assert.AreEqual(10, pageCount); @@ -1113,7 +1058,6 @@ public virtual void AppendModeWith10PagesFix2() { } NUnit.Framework.Assert.IsTrue(reader.HasRebuiltXref(), "Need rebuildXref()"); NUnit.Framework.Assert.IsNotNull(document.GetTrailer().Get(PdfName.ID), "Invalid trailer"); - reader.Close(); document.Close(); } @@ -1124,9 +1068,7 @@ public virtual void StreamLengthCorrection1() { lock (this) { String filename = sourceFolder + "10PagesDocumentWithInvalidStreamLength.pdf"; PdfReader.correctStreamLength = true; - FileStream fis = new FileStream(filename, FileMode.Open, FileAccess.Read); - PdfReader reader = new PdfReader(fis); - PdfDocument pdfDoc = new PdfDocument(reader); + PdfDocument pdfDoc = new PdfDocument(new PdfReader(filename)); int pageCount = pdfDoc.GetNumberOfPages(); for (int k = 1; k < pageCount + 1; k++) { PdfPage page = pdfDoc.GetPage(k); @@ -1134,7 +1076,6 @@ public virtual void StreamLengthCorrection1() { byte[] content = page.GetFirstContentStream().GetBytes(); NUnit.Framework.Assert.AreEqual(57, content.Length); } - reader.Close(); pdfDoc.Close(); } } @@ -1146,14 +1087,11 @@ public virtual void StreamLengthCorrection2() { lock (this) { String filename = sourceFolder + "simpleCanvasWithDrawingLength1.pdf"; PdfReader.correctStreamLength = true; - FileStream fis = new FileStream(filename, FileMode.Open, FileAccess.Read); - PdfReader reader = new PdfReader(fis); - PdfDocument pdfDoc = new PdfDocument(reader); + PdfDocument pdfDoc = new PdfDocument(new PdfReader(filename)); PdfPage page = pdfDoc.GetPage(1); page.GetPdfObject().Get(PdfName.MediaBox); byte[] content = page.GetFirstContentStream().GetBytes(); NUnit.Framework.Assert.AreEqual(696, content.Length); - reader.Close(); pdfDoc.Close(); } } @@ -1165,14 +1103,11 @@ public virtual void StreamLengthCorrection3() { lock (this) { String filename = sourceFolder + "simpleCanvasWithDrawingLength2.pdf"; PdfReader.correctStreamLength = true; - FileStream fis = new FileStream(filename, FileMode.Open, FileAccess.Read); - PdfReader reader = new PdfReader(fis); - PdfDocument pdfDoc = new PdfDocument(reader); + PdfDocument pdfDoc = new PdfDocument(new PdfReader(filename)); PdfPage page = pdfDoc.GetPage(1); page.GetPdfObject().Get(PdfName.MediaBox); byte[] content = page.GetFirstContentStream().GetBytes(); NUnit.Framework.Assert.AreEqual(697, content.Length); - reader.Close(); pdfDoc.Close(); } } @@ -1184,14 +1119,11 @@ public virtual void StreamLengthCorrection4() { lock (this) { String filename = sourceFolder + "simpleCanvasWithDrawingLength3.pdf"; PdfReader.correctStreamLength = true; - FileStream fis = new FileStream(filename, FileMode.Open, FileAccess.Read); - PdfReader reader = new PdfReader(fis); - PdfDocument pdfDoc = new PdfDocument(reader); + PdfDocument pdfDoc = new PdfDocument(new PdfReader(filename)); PdfPage page = pdfDoc.GetPage(1); page.GetPdfObject().Get(PdfName.MediaBox); byte[] content = page.GetFirstContentStream().GetBytes(); NUnit.Framework.Assert.AreEqual(696, content.Length); - reader.Close(); pdfDoc.Close(); } } @@ -1203,14 +1135,11 @@ public virtual void StreamLengthCorrection5() { lock (this) { String filename = sourceFolder + "simpleCanvasWithDrawingLength4.pdf"; PdfReader.correctStreamLength = true; - FileStream fis = new FileStream(filename, FileMode.Open, FileAccess.Read); - PdfReader reader = new PdfReader(fis); - PdfDocument pdfDoc = new PdfDocument(reader); + PdfDocument pdfDoc = new PdfDocument(new PdfReader(filename)); PdfPage page = pdfDoc.GetPage(1); page.GetPdfObject().Get(PdfName.MediaBox); byte[] content = page.GetFirstContentStream().GetBytes(); NUnit.Framework.Assert.AreEqual(696, content.Length); - reader.Close(); pdfDoc.Close(); } } @@ -1222,14 +1151,11 @@ public virtual void StreamLengthCorrection6() { lock (this) { String filename = sourceFolder + "simpleCanvasWithDrawingWithInvalidStreamLength1.pdf"; PdfReader.correctStreamLength = true; - FileStream fis = new FileStream(filename, FileMode.Open, FileAccess.Read); - PdfReader reader = new PdfReader(fis); - PdfDocument pdfDoc = new PdfDocument(reader); + PdfDocument pdfDoc = new PdfDocument(new PdfReader(filename)); PdfPage page = pdfDoc.GetPage(1); page.GetPdfObject().Get(PdfName.MediaBox); byte[] content = page.GetFirstContentStream().GetBytes(); NUnit.Framework.Assert.AreEqual(696, content.Length); - reader.Close(); pdfDoc.Close(); } } @@ -1241,14 +1167,11 @@ public virtual void StreamLengthCorrection7() { lock (this) { String filename = sourceFolder + "simpleCanvasWithDrawingWithInvalidStreamLength2.pdf"; PdfReader.correctStreamLength = true; - FileStream fis = new FileStream(filename, FileMode.Open, FileAccess.Read); - PdfReader reader = new PdfReader(fis); - PdfDocument pdfDoc = new PdfDocument(reader); + PdfDocument pdfDoc = new PdfDocument(new PdfReader(filename)); PdfPage page = pdfDoc.GetPage(1); page.GetPdfObject().Get(PdfName.MediaBox); byte[] content = page.GetFirstContentStream().GetBytes(); NUnit.Framework.Assert.AreEqual(696, content.Length); - reader.Close(); pdfDoc.Close(); } } @@ -1260,14 +1183,11 @@ public virtual void StreamLengthCorrection8() { lock (this) { String filename = sourceFolder + "simpleCanvasWithDrawingWithInvalidStreamLength3.pdf"; PdfReader.correctStreamLength = true; - FileStream fis = new FileStream(filename, FileMode.Open, FileAccess.Read); - PdfReader reader = new PdfReader(fis); - PdfDocument pdfDoc = new PdfDocument(reader); + PdfDocument pdfDoc = new PdfDocument(new PdfReader(filename)); PdfPage page = pdfDoc.GetPage(1); page.GetPdfObject().Get(PdfName.MediaBox); byte[] content = page.GetFirstContentStream().GetBytes(); NUnit.Framework.Assert.AreEqual(697, content.Length); - reader.Close(); pdfDoc.Close(); } } @@ -1279,9 +1199,7 @@ public virtual void StreamLengthCorrection9() { lock (this) { String filename = sourceFolder + "10PagesDocumentWithInvalidStreamLength2.pdf"; PdfReader.correctStreamLength = false; - FileStream fis = new FileStream(filename, FileMode.Open, FileAccess.Read); - PdfReader reader = new PdfReader(fis); - PdfDocument pdfDoc = new PdfDocument(reader); + PdfDocument pdfDoc = new PdfDocument(new PdfReader(filename)); int pageCount = pdfDoc.GetNumberOfPages(); for (int k = 1; k < pageCount + 1; k++) { PdfPage page = pdfDoc.GetPage(k); @@ -1289,7 +1207,6 @@ public virtual void StreamLengthCorrection9() { byte[] content = page.GetFirstContentStream().GetBytes(); NUnit.Framework.Assert.AreEqual(20, content.Length); } - reader.Close(); pdfDoc.Close(); PdfReader.correctStreamLength = true; } @@ -1299,9 +1216,7 @@ public virtual void StreamLengthCorrection9() { [NUnit.Framework.Test] public virtual void FreeReferencesTest() { String filename = sourceFolder + "freeReferences.pdf"; - FileStream fis = new FileStream(filename, FileMode.Open, FileAccess.Read); - PdfReader reader = new PdfReader(fis); - PdfDocument pdfDoc = new PdfDocument(reader); + PdfDocument pdfDoc = new PdfDocument(new PdfReader(filename)); NUnit.Framework.Assert.IsNull(pdfDoc.GetPdfObject(8)); //Assert.assertFalse(pdfDoc.getReader().fixedXref); NUnit.Framework.Assert.IsFalse(pdfDoc.GetReader().rebuiltXref); @@ -1312,9 +1227,7 @@ public virtual void FreeReferencesTest() { [NUnit.Framework.Test] public virtual void PdfVersionTest() { String filename = sourceFolder + "hello.pdf"; - FileStream fis = new FileStream(filename, FileMode.Open, FileAccess.Read); - PdfReader reader = new PdfReader(fis); - PdfDocument pdfDoc = new PdfDocument(reader); + PdfDocument pdfDoc = new PdfDocument(new PdfReader(filename)); NUnit.Framework.Assert.AreEqual(PdfVersion.PDF_1_4, pdfDoc.GetPdfVersion()); pdfDoc.Close(); } @@ -1323,8 +1236,7 @@ public virtual void PdfVersionTest() { [NUnit.Framework.Test] public virtual void ZeroUpdateTest() { String filename = sourceFolder + "stationery.pdf"; - FileStream fis = new FileStream(filename, FileMode.Open, FileAccess.Read); - PdfReader reader = new PdfReader(fis); + PdfReader reader = new PdfReader(filename); PdfDocument pdfDoc = new PdfDocument(reader); // Test such construction: // xref @@ -1342,8 +1254,7 @@ public virtual void ZeroUpdateTest() { [NUnit.Framework.Test] public virtual void IncrementalUpdateWithOnlyZeroObjectUpdate() { String filename = sourceFolder + "pdfReferenceUpdated.pdf"; - FileStream fis = new FileStream(filename, FileMode.Open, FileAccess.Read); - PdfReader reader = new PdfReader(fis); + PdfReader reader = new PdfReader(filename); PdfDocument pdfDoc = new PdfDocument(reader); NUnit.Framework.Assert.IsFalse(reader.HasFixedXref()); NUnit.Framework.Assert.IsFalse(reader.HasRebuiltXref()); diff --git a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfResourcesTest.cs b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfResourcesTest.cs index 0529bc4bdc..28a0f1ca4e 100644 --- a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfResourcesTest.cs +++ b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfResourcesTest.cs @@ -9,9 +9,7 @@ public class PdfResourcesTest { /// [NUnit.Framework.Test] public virtual void ResourcesTest1() { - MemoryStream baos = new MemoryStream(); - PdfWriter writer = new PdfWriter(baos); - PdfDocument document = new PdfDocument(writer); + PdfDocument document = new PdfDocument(new PdfWriter(new MemoryStream())); PdfPage page = document.AddNewPage(); PdfExtGState egs1 = new PdfExtGState(); PdfExtGState egs2 = new PdfExtGState(); @@ -29,8 +27,7 @@ public virtual void ResourcesTest1() { [NUnit.Framework.Test] public virtual void ResourcesTest2() { MemoryStream baos = new MemoryStream(); - PdfWriter writer = new PdfWriter(baos); - PdfDocument document = new PdfDocument(writer); + PdfDocument document = new PdfDocument(new PdfWriter(baos)); PdfPage page = document.AddNewPage(); PdfExtGState egs1 = new PdfExtGState(); PdfExtGState egs2 = new PdfExtGState(); @@ -54,13 +51,13 @@ public virtual void ResourcesTest2() { NUnit.Framework.Assert.AreEqual("Gs3", n3.GetValue()); PdfDictionary egsResources = page.GetPdfObject().GetAsDictionary(PdfName.Resources).GetAsDictionary(PdfName .ExtGState); - PdfObject e1 = egsResources.Get(new PdfName("Gs1"), false); + PdfDictionary e1 = egsResources.GetAsDictionary(new PdfName("Gs1")); PdfName n1 = resources.AddExtGState(e1); NUnit.Framework.Assert.AreEqual("Gs1", n1.GetValue()); - PdfObject e2 = egsResources.Get(new PdfName("Gs2")); + PdfDictionary e2 = egsResources.GetAsDictionary(new PdfName("Gs2")); PdfName n2 = resources.AddExtGState(e2); NUnit.Framework.Assert.AreEqual("Gs2", n2.GetValue()); - PdfObject e4 = (PdfObject)e2.Clone(); + PdfDictionary e4 = (PdfDictionary)e2.Clone(); PdfName n4 = resources.AddExtGState(e4); NUnit.Framework.Assert.AreEqual("Gs4", n4.GetValue()); document.Close(); diff --git a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfStampingTest.cs b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfStampingTest.cs index 4315fea55d..a3dcb1f93c 100644 --- a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfStampingTest.cs +++ b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfStampingTest.cs @@ -22,23 +22,19 @@ public static void BeforeClass() { public virtual void Stamping1() { String filename1 = destinationFolder + "stamping1_1.pdf"; String filename2 = destinationFolder + "stamping1_2.pdf"; - FileStream fos1 = new FileStream(filename1, FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1); - PdfDocument pdfDoc1 = new PdfDocument(writer1); + PdfDocument pdfDoc1 = new PdfDocument(new PdfWriter(filename1)); pdfDoc1.GetDocumentInfo().SetAuthor("Alexander Chingarev").SetCreator("iText 6").SetTitle("Empty iText 6 Document" ); PdfPage page1 = pdfDoc1.AddNewPage(); page1.GetContentStream(0).GetOutputStream().Write(ByteUtils.GetIsoBytes("%Hello World\n")); page1.Flush(); pdfDoc1.Close(); - FileStream fis2 = new FileStream(filename1, FileMode.Open, FileAccess.Read); - PdfReader reader2 = new PdfReader(fis2); - FileStream fos2 = new FileStream(filename2, FileMode.Create); - PdfWriter writer2 = new PdfWriter(fos2); + PdfReader reader2 = new PdfReader(filename1); + PdfWriter writer2 = new PdfWriter(filename2); PdfDocument pdfDoc2 = new PdfDocument(reader2, writer2); pdfDoc2.GetDocumentInfo().SetCreator("iText 7").SetTitle("Empty iText 7 Document"); pdfDoc2.Close(); - PdfReader reader3 = new PdfReader(new FileStream(filename2, FileMode.Open, FileAccess.Read)); + PdfReader reader3 = new PdfReader(filename2); PdfDocument pdfDoc3 = new PdfDocument(reader3); for (int i = 0; i < pdfDoc3.GetNumberOfPages(); i++) { pdfDoc3.GetPage(i + 1); @@ -61,7 +57,7 @@ public virtual void Stamping1() { double diff = DateTimeUtil.GetUtcMillisFromEpoch(null) - DateTimeUtil.GetUtcMillisFromEpoch(cl); String message = "Unexpected creation date. Different from now is " + (float)diff / 1000 + "s"; NUnit.Framework.Assert.IsTrue(diff < 5000, message); - reader.Close(); + document.Close(); } /// @@ -69,23 +65,19 @@ public virtual void Stamping1() { public virtual void Stamping2() { String filename1 = destinationFolder + "stamping2_1.pdf"; String filename2 = destinationFolder + "stamping2_2.pdf"; - FileStream fos1 = new FileStream(filename1, FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1); - PdfDocument pdfDoc1 = new PdfDocument(writer1); + PdfDocument pdfDoc1 = new PdfDocument(new PdfWriter(filename1)); PdfPage page1 = pdfDoc1.AddNewPage(); page1.GetContentStream(0).GetOutputStream().Write(ByteUtils.GetIsoBytes("%page 1\n")); page1.Flush(); pdfDoc1.Close(); - FileStream fis2 = new FileStream(filename1, FileMode.Open, FileAccess.Read); - PdfReader reader2 = new PdfReader(fis2); - FileStream fos2 = new FileStream(filename2, FileMode.Create); - PdfWriter writer2 = new PdfWriter(fos2); + PdfReader reader2 = new PdfReader(filename1); + PdfWriter writer2 = new PdfWriter(filename2); PdfDocument pdfDoc2 = new PdfDocument(reader2, writer2); PdfPage page2 = pdfDoc2.AddNewPage(); page2.GetContentStream(0).GetOutputStream().Write(ByteUtils.GetIsoBytes("%page 2\n")); page2.Flush(); pdfDoc2.Close(); - PdfReader reader3 = new PdfReader(new FileStream(filename2, FileMode.Open, FileAccess.Read)); + PdfReader reader3 = new PdfReader(filename2); PdfDocument pdfDoc3 = new PdfDocument(reader3); for (int i = 0; i < pdfDoc3.GetNumberOfPages(); i++) { pdfDoc3.GetPage(i + 1); @@ -109,23 +101,20 @@ public virtual void Stamping2() { public virtual void Stamping3() { String filename1 = destinationFolder + "stamping3_1.pdf"; String filename2 = destinationFolder + "stamping3_2.pdf"; - FileStream fos1 = new FileStream(filename1, FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1, new WriterProperties().SetFullCompressionMode(true)); + PdfWriter writer1 = new PdfWriter(filename1, new WriterProperties().SetFullCompressionMode(true)); PdfDocument pdfDoc1 = new PdfDocument(writer1); PdfPage page1 = pdfDoc1.AddNewPage(); page1.GetContentStream(0).GetOutputStream().Write(ByteUtils.GetIsoBytes("%page 1\n")); page1.Flush(); pdfDoc1.Close(); - FileStream fis2 = new FileStream(filename1, FileMode.Open, FileAccess.Read); - PdfReader reader2 = new PdfReader(fis2); - FileStream fos2 = new FileStream(filename2, FileMode.Create); - PdfWriter writer2 = new PdfWriter(fos2, new WriterProperties().SetFullCompressionMode(true)); + PdfReader reader2 = new PdfReader(filename1); + PdfWriter writer2 = new PdfWriter(filename2, new WriterProperties().SetFullCompressionMode(true)); PdfDocument pdfDoc2 = new PdfDocument(reader2, writer2); PdfPage page2 = pdfDoc2.AddNewPage(); page2.GetContentStream(0).GetOutputStream().Write(ByteUtils.GetIsoBytes("%page 2\n")); page2.Flush(); pdfDoc2.Close(); - PdfReader reader3 = new PdfReader(new FileStream(filename2, FileMode.Open, FileAccess.Read)); + PdfReader reader3 = new PdfReader(filename2); PdfDocument pdfDoc3 = new PdfDocument(reader3); for (int i = 0; i < pdfDoc3.GetNumberOfPages(); i++) { pdfDoc3.GetPage(i + 1); @@ -141,7 +130,7 @@ public virtual void Stamping3() { NUnit.Framework.Assert.AreEqual("%page 1\n", iText.IO.Util.JavaUtil.GetStringForBytes(bytes)); bytes = pdfDocument.GetPage(2).GetContentBytes(); NUnit.Framework.Assert.AreEqual("%page 2\n", iText.IO.Util.JavaUtil.GetStringForBytes(bytes)); - reader.Close(); + pdfDocument.Close(); } /// @@ -149,26 +138,20 @@ public virtual void Stamping3() { public virtual void Stamping4() { String filename1 = destinationFolder + "stamping4_1.pdf"; String filename2 = destinationFolder + "stamping4_2.pdf"; - FileStream fos1 = new FileStream(filename1, FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1); - PdfDocument pdfDoc1 = new PdfDocument(writer1); + PdfDocument pdfDoc1 = new PdfDocument(new PdfWriter(filename1)); PdfPage page1 = pdfDoc1.AddNewPage(); page1.GetContentStream(0).GetOutputStream().Write(ByteUtils.GetIsoBytes("%page 1\n")); page1.Flush(); pdfDoc1.Close(); int pageCount = 15; - FileStream fis2 = new FileStream(filename1, FileMode.Open, FileAccess.Read); - PdfReader reader2 = new PdfReader(fis2); - FileStream fos2 = new FileStream(filename2, FileMode.Create); - PdfWriter writer2 = new PdfWriter(fos2); - PdfDocument pdfDoc2 = new PdfDocument(reader2, writer2); + PdfDocument pdfDoc2 = new PdfDocument(new PdfReader(filename1), new PdfWriter(filename2)); for (int i = 2; i <= pageCount; i++) { PdfPage page2 = pdfDoc2.AddNewPage(); page2.GetContentStream(0).GetOutputStream().Write(ByteUtils.GetIsoBytes("%page " + i + "\n")); page2.Flush(); } pdfDoc2.Close(); - PdfReader reader3 = new PdfReader(new FileStream(filename2, FileMode.Open, FileAccess.Read)); + PdfReader reader3 = new PdfReader(filename2); PdfDocument pdfDoc3 = new PdfDocument(reader3); for (int i_1 = 0; i_1 < pdfDoc3.GetNumberOfPages(); i_1++) { pdfDoc3.GetPage(i_1 + 1); @@ -185,7 +168,7 @@ public virtual void Stamping4() { byte[] bytes = pdfDocument.GetPage(i_2).GetContentBytes(); NUnit.Framework.Assert.AreEqual("%page " + i_2 + "\n", iText.IO.Util.JavaUtil.GetStringForBytes(bytes)); } - reader.Close(); + pdfDocument.Close(); } /// @@ -193,18 +176,14 @@ public virtual void Stamping4() { public virtual void Stamping5() { String filename1 = destinationFolder + "stamping5_1.pdf"; String filename2 = destinationFolder + "stamping5_2.pdf"; - FileStream fos1 = new FileStream(filename1, FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1); - PdfDocument pdfDoc1 = new PdfDocument(writer1); + PdfDocument pdfDoc1 = new PdfDocument(new PdfWriter(filename1)); PdfPage page1 = pdfDoc1.AddNewPage(); page1.GetContentStream(0).GetOutputStream().Write(ByteUtils.GetIsoBytes("%page 1\n")); page1.Flush(); pdfDoc1.Close(); int pageCount = 15; - FileStream fis2 = new FileStream(filename1, FileMode.Open, FileAccess.Read); - PdfReader reader2 = new PdfReader(fis2); - FileStream fos2 = new FileStream(filename2, FileMode.Create); - PdfWriter writer2 = new PdfWriter(fos2, new WriterProperties().SetFullCompressionMode(true)); + PdfReader reader2 = new PdfReader(filename1); + PdfWriter writer2 = new PdfWriter(filename2, new WriterProperties().SetFullCompressionMode(true)); PdfDocument pdfDoc2 = new PdfDocument(reader2, writer2); for (int i = 2; i <= pageCount; i++) { PdfPage page2 = pdfDoc2.AddNewPage(); @@ -212,7 +191,7 @@ public virtual void Stamping5() { page2.Flush(); } pdfDoc2.Close(); - PdfReader reader3 = new PdfReader(new FileStream(filename2, FileMode.Open, FileAccess.Read)); + PdfReader reader3 = new PdfReader(filename2); PdfDocument pdfDoc3 = new PdfDocument(reader3); for (int i_1 = 0; i_1 < pdfDoc3.GetNumberOfPages(); i_1++) { pdfDoc3.GetPage(i_1 + 1); @@ -237,23 +216,18 @@ public virtual void Stamping5() { public virtual void Stamping6() { String filename1 = destinationFolder + "stamping6_1.pdf"; String filename2 = destinationFolder + "stamping6_2.pdf"; - FileStream fos1 = new FileStream(filename1, FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1, new WriterProperties().SetFullCompressionMode(true)); - PdfDocument pdfDoc1 = new PdfDocument(writer1); + PdfDocument pdfDoc1 = new PdfDocument(new PdfWriter(filename1, new WriterProperties().SetFullCompressionMode + (true))); PdfPage page1 = pdfDoc1.AddNewPage(); page1.GetContentStream(0).GetOutputStream().Write(ByteUtils.GetIsoBytes("%page 1\n")); page1.Flush(); pdfDoc1.Close(); - FileStream fis2 = new FileStream(filename1, FileMode.Open, FileAccess.Read); - PdfReader reader2 = new PdfReader(fis2); - FileStream fos2 = new FileStream(filename2, FileMode.Create); - PdfWriter writer2 = new PdfWriter(fos2); - PdfDocument pdfDoc2 = new PdfDocument(reader2, writer2); + PdfDocument pdfDoc2 = new PdfDocument(new PdfReader(filename1), new PdfWriter(filename2)); PdfPage page2 = pdfDoc2.AddNewPage(); page2.GetContentStream(0).GetOutputStream().Write(ByteUtils.GetIsoBytes("%page 2\n")); page2.Flush(); pdfDoc2.Close(); - PdfReader reader3 = new PdfReader(new FileStream(filename2, FileMode.Open, FileAccess.Read)); + PdfReader reader3 = new PdfReader(filename2); PdfDocument pdfDoc3 = new PdfDocument(reader3); for (int i = 0; i < pdfDoc3.GetNumberOfPages(); i++) { pdfDoc3.GetPage(i + 1); @@ -269,7 +243,7 @@ public virtual void Stamping6() { NUnit.Framework.Assert.AreEqual("%page 1\n", iText.IO.Util.JavaUtil.GetStringForBytes(bytes)); bytes = pdfDocument.GetPage(2).GetContentBytes(); NUnit.Framework.Assert.AreEqual("%page 2\n", iText.IO.Util.JavaUtil.GetStringForBytes(bytes)); - reader.Close(); + pdfDocument.Close(); } /// @@ -277,23 +251,19 @@ public virtual void Stamping6() { public virtual void Stamping7() { String filename1 = destinationFolder + "stamping7_1.pdf"; String filename2 = destinationFolder + "stamping7_2.pdf"; - FileStream fos1 = new FileStream(filename1, FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1); - PdfDocument pdfDoc1 = new PdfDocument(writer1); + PdfDocument pdfDoc1 = new PdfDocument(new PdfWriter(filename1)); PdfPage page1 = pdfDoc1.AddNewPage(); page1.GetContentStream(0).GetOutputStream().Write(ByteUtils.GetIsoBytes("%page 1\n")); page1.Flush(); pdfDoc1.Close(); - FileStream fis2 = new FileStream(filename1, FileMode.Open, FileAccess.Read); - PdfReader reader2 = new PdfReader(fis2); - FileStream fos2 = new FileStream(filename2, FileMode.Create); - PdfWriter writer2 = new PdfWriter(fos2, new WriterProperties().SetFullCompressionMode(true)); + PdfReader reader2 = new PdfReader(filename1); + PdfWriter writer2 = new PdfWriter(filename2, new WriterProperties().SetFullCompressionMode(true)); PdfDocument pdfDoc2 = new PdfDocument(reader2, writer2); PdfPage page2 = pdfDoc2.AddNewPage(); page2.GetContentStream(0).GetOutputStream().Write(ByteUtils.GetIsoBytes("%page 2\n")); page2.Flush(); pdfDoc2.Close(); - PdfReader reader3 = new PdfReader(new FileStream(filename2, FileMode.Open, FileAccess.Read)); + PdfReader reader3 = new PdfReader(filename2); PdfDocument pdfDoc3 = new PdfDocument(reader3); for (int i = 0; i < pdfDoc3.GetNumberOfPages(); i++) { pdfDoc3.GetPage(i + 1); @@ -309,7 +279,7 @@ public virtual void Stamping7() { NUnit.Framework.Assert.AreEqual("%page 1\n", iText.IO.Util.JavaUtil.GetStringForBytes(bytes)); bytes = pdfDocument.GetPage(2).GetContentBytes(); NUnit.Framework.Assert.AreEqual("%page 2\n", iText.IO.Util.JavaUtil.GetStringForBytes(bytes)); - reader.Close(); + pdfDocument.Close(); } /// @@ -318,8 +288,7 @@ public virtual void Stamping8() { String filename1 = destinationFolder + "stamping8_1.pdf"; String filename2 = destinationFolder + "stamping8_2.pdf"; int pageCount = 10; - FileStream fos1 = new FileStream(filename1, FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1, new WriterProperties().SetFullCompressionMode(true)); + PdfWriter writer1 = new PdfWriter(filename1, new WriterProperties().SetFullCompressionMode(true)); PdfDocument pdfDoc1 = new PdfDocument(writer1); for (int i = 1; i <= pageCount; i++) { PdfPage page = pdfDoc1.AddNewPage(); @@ -327,12 +296,11 @@ public virtual void Stamping8() { page.Flush(); } pdfDoc1.Close(); - PdfReader reader2 = new PdfReader(new FileStream(filename1, FileMode.Open, FileAccess.Read)); - PdfWriter writer2 = new PdfWriter(new FileStream(filename2, FileMode.Create), new WriterProperties().SetFullCompressionMode - (true)); + PdfReader reader2 = new PdfReader(filename1); + PdfWriter writer2 = new PdfWriter(filename2, new WriterProperties().SetFullCompressionMode(true)); PdfDocument pdfDoc2 = new PdfDocument(reader2, writer2); pdfDoc2.Close(); - PdfReader reader3 = new PdfReader(new FileStream(filename2, FileMode.Open, FileAccess.Read)); + PdfReader reader3 = new PdfReader(filename2); PdfDocument pdfDoc3 = new PdfDocument(reader3); for (int i_1 = 0; i_1 < pdfDoc3.GetNumberOfPages(); i_1++) { pdfDoc3.GetPage(i_1 + 1); @@ -350,7 +318,7 @@ public virtual void Stamping8() { NUnit.Framework.Assert.AreEqual("%page " + i_2 + "\n", iText.IO.Util.JavaUtil.GetStringForBytes(bytes), "Page content at page " + i_2); } - reader.Close(); + pdfDocument.Close(); } /// @@ -359,8 +327,7 @@ public virtual void Stamping9() { String filename1 = destinationFolder + "stamping9_1.pdf"; String filename2 = destinationFolder + "stamping9_2.pdf"; int pageCount = 10; - FileStream fos1 = new FileStream(filename1, FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1, new WriterProperties().SetFullCompressionMode(false)); + PdfWriter writer1 = new PdfWriter(filename1, new WriterProperties().SetFullCompressionMode(false)); PdfDocument pdfDoc1 = new PdfDocument(writer1); for (int i = 1; i <= pageCount; i++) { PdfPage page = pdfDoc1.AddNewPage(); @@ -368,12 +335,11 @@ public virtual void Stamping9() { page.Flush(); } pdfDoc1.Close(); - PdfReader reader2 = new PdfReader(new FileStream(filename1, FileMode.Open, FileAccess.Read)); - PdfWriter writer2 = new PdfWriter(new FileStream(filename2, FileMode.Create), new WriterProperties().SetFullCompressionMode - (true)); + PdfReader reader2 = new PdfReader(filename1); + PdfWriter writer2 = new PdfWriter(filename2, new WriterProperties().SetFullCompressionMode(true)); PdfDocument pdfDoc2 = new PdfDocument(reader2, writer2); pdfDoc2.Close(); - PdfReader reader3 = new PdfReader(new FileStream(filename2, FileMode.Open, FileAccess.Read)); + PdfReader reader3 = new PdfReader(filename2); PdfDocument pdfDoc3 = new PdfDocument(reader3); for (int i_1 = 0; i_1 < pdfDoc3.GetNumberOfPages(); i_1++) { pdfDoc3.GetPage(i_1 + 1); @@ -391,7 +357,7 @@ public virtual void Stamping9() { NUnit.Framework.Assert.AreEqual("%page " + i_2 + "\n", iText.IO.Util.JavaUtil.GetStringForBytes(bytes), "Page content at page " + i_2); } - reader.Close(); + pdfDocument.Close(); } /// @@ -400,8 +366,7 @@ public virtual void Stamping10() { String filename1 = destinationFolder + "stamping10_1.pdf"; String filename2 = destinationFolder + "stamping10_2.pdf"; int pageCount = 10; - FileStream fos1 = new FileStream(filename1, FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1, new WriterProperties().SetFullCompressionMode(true)); + PdfWriter writer1 = new PdfWriter(filename1, new WriterProperties().SetFullCompressionMode(true)); PdfDocument pdfDoc1 = new PdfDocument(writer1); for (int i = 1; i <= pageCount; i++) { PdfPage page = pdfDoc1.AddNewPage(); @@ -409,12 +374,11 @@ public virtual void Stamping10() { page.Flush(); } pdfDoc1.Close(); - PdfReader reader2 = new PdfReader(new FileStream(filename1, FileMode.Open, FileAccess.Read)); - PdfWriter writer2 = new PdfWriter(new FileStream(filename2, FileMode.Create), new WriterProperties().SetFullCompressionMode - (false)); + PdfReader reader2 = new PdfReader(filename1); + PdfWriter writer2 = new PdfWriter(filename2, new WriterProperties().SetFullCompressionMode(false)); PdfDocument pdfDoc2 = new PdfDocument(reader2, writer2); pdfDoc2.Close(); - PdfReader reader3 = new PdfReader(new FileStream(filename2, FileMode.Open, FileAccess.Read)); + PdfReader reader3 = new PdfReader(filename2); PdfDocument pdfDoc3 = new PdfDocument(reader3); for (int i_1 = 0; i_1 < pdfDoc3.GetNumberOfPages(); i_1++) { pdfDoc3.GetPage(i_1 + 1); @@ -432,7 +396,7 @@ public virtual void Stamping10() { NUnit.Framework.Assert.AreEqual("%page " + i_2 + "\n", iText.IO.Util.JavaUtil.GetStringForBytes(bytes), "Page content at page " + i_2); } - reader.Close(); + pdfDocument.Close(); } /// @@ -441,8 +405,7 @@ public virtual void Stamping11() { String filename1 = destinationFolder + "stamping11_1.pdf"; String filename2 = destinationFolder + "stamping11_2.pdf"; int pageCount = 10; - FileStream fos1 = new FileStream(filename1, FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1, new WriterProperties().SetFullCompressionMode(false)); + PdfWriter writer1 = new PdfWriter(filename1, new WriterProperties().SetFullCompressionMode(false)); PdfDocument pdfDoc1 = new PdfDocument(writer1); for (int i = 1; i <= pageCount; i++) { PdfPage page = pdfDoc1.AddNewPage(); @@ -450,12 +413,11 @@ public virtual void Stamping11() { page.Flush(); } pdfDoc1.Close(); - PdfReader reader2 = new PdfReader(new FileStream(filename1, FileMode.Open, FileAccess.Read)); - PdfWriter writer2 = new PdfWriter(new FileStream(filename2, FileMode.Create), new WriterProperties().SetFullCompressionMode - (false)); + PdfReader reader2 = new PdfReader(filename1); + PdfWriter writer2 = new PdfWriter(filename2, new WriterProperties().SetFullCompressionMode(false)); PdfDocument pdfDoc2 = new PdfDocument(reader2, writer2); pdfDoc2.Close(); - PdfReader reader3 = new PdfReader(new FileStream(filename2, FileMode.Open, FileAccess.Read)); + PdfReader reader3 = new PdfReader(filename2); PdfDocument pdfDoc3 = new PdfDocument(reader3); for (int i_1 = 0; i_1 < pdfDoc3.GetNumberOfPages(); i_1++) { pdfDoc3.GetPage(i_1 + 1); @@ -473,7 +435,7 @@ public virtual void Stamping11() { NUnit.Framework.Assert.AreEqual("%page " + i_2 + "\n", iText.IO.Util.JavaUtil.GetStringForBytes(bytes), "Page content at page " + i_2); } - reader.Close(); + pdfDocument.Close(); } /// @@ -482,24 +444,20 @@ public virtual void Stamping12() { String filename1 = destinationFolder + "stamping12_1.pdf"; String filename2 = destinationFolder + "stamping12_2.pdf"; int pageCount = 1010; - FileStream fos1 = new FileStream(filename1, FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1); - PdfDocument pdfDoc1 = new PdfDocument(writer1); + PdfDocument pdfDoc1 = new PdfDocument(new PdfWriter(filename1)); for (int i = 1; i <= pageCount; i++) { PdfPage page = pdfDoc1.AddNewPage(); page.GetContentStream(0).GetOutputStream().Write(ByteUtils.GetIsoBytes("%page " + i + "\n")); page.Flush(); } pdfDoc1.Close(); - PdfReader reader2 = new PdfReader(new FileStream(filename1, FileMode.Open, FileAccess.Read)); - PdfWriter writer2 = new PdfWriter(new FileStream(filename2, FileMode.Create)); - PdfDocument pdfDoc2 = new PdfDocument(reader2, writer2); + PdfDocument pdfDoc2 = new PdfDocument(new PdfReader(filename1), new PdfWriter(filename2)); int newPageCount = 10; for (int i_1 = pageCount; i_1 > newPageCount; i_1--) { NUnit.Framework.Assert.IsNotNull(pdfDoc2.RemovePage(i_1), "Remove page " + i_1); } pdfDoc2.Close(); - PdfReader reader3 = new PdfReader(new FileStream(filename2, FileMode.Open, FileAccess.Read)); + PdfReader reader3 = new PdfReader(filename2); PdfDocument pdfDoc3 = new PdfDocument(reader3); for (int i_2 = 1; i_2 <= pdfDoc3.GetNumberOfPages(); i_2++) { pdfDoc3.GetPage(i_2); @@ -520,7 +478,7 @@ public virtual void Stamping12() { NUnit.Framework.Assert.AreEqual("%page " + i_3 + "\n", iText.IO.Util.JavaUtil.GetStringForBytes(bytes), "Page content at page " + i_3); } - reader.Close(); + pdfDocument.Close(); } /// @@ -529,18 +487,14 @@ public virtual void Stamping13() { String filename1 = destinationFolder + "stamping13_1.pdf"; String filename2 = destinationFolder + "stamping13_2.pdf"; int pageCount = 1010; - FileStream fos1 = new FileStream(filename1, FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1); - PdfDocument pdfDoc1 = new PdfDocument(writer1); + PdfDocument pdfDoc1 = new PdfDocument(new PdfWriter(filename1)); for (int i = 1; i <= pageCount; i++) { PdfPage page = pdfDoc1.AddNewPage(); page.GetContentStream(0).GetOutputStream().Write(ByteUtils.GetIsoBytes("%page " + i + "\n")); page.Flush(); } pdfDoc1.Close(); - PdfReader reader2 = new PdfReader(new FileStream(filename1, FileMode.Open, FileAccess.Read)); - PdfWriter writer2 = new PdfWriter(new FileStream(filename2, FileMode.Create)); - PdfDocument pdfDoc2 = new PdfDocument(reader2, writer2); + PdfDocument pdfDoc2 = new PdfDocument(new PdfReader(filename1), new PdfWriter(filename2)); for (int i_1 = pageCount; i_1 > 1; i_1--) { NUnit.Framework.Assert.IsNotNull(pdfDoc2.RemovePage(i_1), "Remove page " + i_1); } @@ -551,7 +505,7 @@ public virtual void Stamping13() { page.Flush(); } pdfDoc2.Close(); - PdfReader reader3 = new PdfReader(new FileStream(filename2, FileMode.Open, FileAccess.Read)); + PdfReader reader3 = new PdfReader(filename2); PdfDocument pdfDoc3 = new PdfDocument(reader3); for (int i_3 = 1; i_3 <= pdfDoc3.GetNumberOfPages(); i_3++) { pdfDoc3.GetPage(i_3); @@ -571,7 +525,7 @@ public virtual void Stamping13() { NUnit.Framework.Assert.AreEqual("%page " + i_4 + "\n", iText.IO.Util.JavaUtil.GetStringForBytes(bytes), "Page content at page " + i_4); } - reader.Close(); + pdfDocument.Close(); } /// @@ -580,14 +534,12 @@ public virtual void Stamping13() { public virtual void Stamping14() { String filename1 = sourceFolder + "20000PagesDocument.pdf"; String filename2 = destinationFolder + "stamping14.pdf"; - PdfReader reader2 = new PdfReader(new FileStream(filename1, FileMode.Open, FileAccess.Read)); - PdfWriter writer2 = new PdfWriter(new FileStream(filename2, FileMode.Create)); - PdfDocument pdfDoc2 = new PdfDocument(reader2, writer2); + PdfDocument pdfDoc2 = new PdfDocument(new PdfReader(filename1), new PdfWriter(filename2)); for (int i = pdfDoc2.GetNumberOfPages(); i > 3; i--) { NUnit.Framework.Assert.IsNotNull(pdfDoc2.RemovePage(i), "Remove page " + i); } pdfDoc2.Close(); - PdfReader reader3 = new PdfReader(new FileStream(filename2, FileMode.Open, FileAccess.Read)); + PdfReader reader3 = new PdfReader(filename2); PdfDocument pdfDoc3 = new PdfDocument(reader3); for (int i_1 = 1; i_1 <= pdfDoc3.GetNumberOfPages(); i_1++) { pdfDoc3.GetPage(i_1); @@ -606,7 +558,7 @@ public virtual void Stamping14() { NUnit.Framework.Assert.AreEqual("%page " + i_2 + "\n", iText.IO.Util.JavaUtil.GetStringForBytes(bytes), "Page content at page " + i_2); } - reader.Close(); + pdfDocument.Close(); } /// @@ -659,9 +611,7 @@ public virtual void StampingStreamsCompression03() { // if user specified, stream may be recompressed String filenameIn = sourceFolder + "stampingStreamsCompression.pdf"; String filenameOut = destinationFolder + "stampingStreamsCompression03.pdf"; - PdfReader reader = new PdfReader(filenameIn); - PdfWriter writer = new PdfWriter(filenameOut); - PdfDocument doc = new PdfDocument(reader, writer); + PdfDocument doc = new PdfDocument(new PdfReader(filenameIn), new PdfWriter(filenameOut)); PdfStream stream = (PdfStream)doc.GetPdfObject(6); int lengthBefore = stream.GetLength(); stream.SetCompressionLevel(CompressionConstants.BEST_COMPRESSION); @@ -682,8 +632,7 @@ public virtual void StampingXmp1() { String filename1 = destinationFolder + "stampingXmp1_1.pdf"; String filename2 = destinationFolder + "stampingXmp1_2.pdf"; int pageCount = 10; - FileStream fos1 = new FileStream(filename1, FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1, new WriterProperties().SetFullCompressionMode(true)); + PdfWriter writer1 = new PdfWriter(filename1, new WriterProperties().SetFullCompressionMode(true)); PdfDocument pdfDoc1 = new PdfDocument(writer1); for (int i = 1; i <= pageCount; i++) { PdfPage page = pdfDoc1.AddNewPage(); @@ -691,13 +640,13 @@ public virtual void StampingXmp1() { page.Flush(); } pdfDoc1.Close(); - PdfReader reader2 = new PdfReader(new FileStream(filename1, FileMode.Open, FileAccess.Read)); - PdfWriter writer2 = new PdfWriter(new FileStream(filename2, FileMode.Create), new WriterProperties().SetFullCompressionMode - (false).AddXmpMetadata()); + PdfReader reader2 = new PdfReader(filename1); + PdfWriter writer2 = new PdfWriter(filename2, new WriterProperties().SetFullCompressionMode(false).AddXmpMetadata + ()); PdfDocument pdfDoc2 = new PdfDocument(reader2, writer2); pdfDoc2.GetDocumentInfo().SetAuthor("Alexander Chingarev"); pdfDoc2.Close(); - PdfReader reader3 = new PdfReader(new FileStream(filename2, FileMode.Open, FileAccess.Read)); + PdfReader reader3 = new PdfReader(filename2); PdfDocument pdfDoc3 = new PdfDocument(reader3); for (int i_1 = 0; i_1 < pdfDoc3.GetNumberOfPages(); i_1++) { pdfDoc3.GetPage(i_1 + 1); @@ -717,7 +666,7 @@ public virtual void StampingXmp1() { NUnit.Framework.Assert.AreEqual("%page " + i_2 + "\n", iText.IO.Util.JavaUtil.GetStringForBytes(bytes), "Page content at page " + i_2); } - reader.Close(); + pdfDocument.Close(); } /// @@ -727,8 +676,7 @@ public virtual void StampingXmp2() { String filename1 = destinationFolder + "stampingXmp2_1.pdf"; String filename2 = destinationFolder + "stampingXmp2_2.pdf"; int pageCount = 10; - FileStream fos1 = new FileStream(filename1, FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1, new WriterProperties().SetFullCompressionMode(false)); + PdfWriter writer1 = new PdfWriter(filename1, new WriterProperties().SetFullCompressionMode(false)); PdfDocument pdfDoc1 = new PdfDocument(writer1); for (int i = 1; i <= pageCount; i++) { PdfPage page = pdfDoc1.AddNewPage(); @@ -736,13 +684,13 @@ public virtual void StampingXmp2() { page.Flush(); } pdfDoc1.Close(); - PdfReader reader2 = new PdfReader(new FileStream(filename1, FileMode.Open, FileAccess.Read)); - PdfWriter writer2 = new PdfWriter(new FileStream(filename2, FileMode.Create), new WriterProperties().SetFullCompressionMode - (true).AddXmpMetadata()); + PdfReader reader2 = new PdfReader(filename1); + PdfWriter writer2 = new PdfWriter(filename2, new WriterProperties().SetFullCompressionMode(true).AddXmpMetadata + ()); PdfDocument pdfDoc2 = new PdfDocument(reader2, writer2); pdfDoc2.GetDocumentInfo().SetAuthor("Alexander Chingarev"); pdfDoc2.Close(); - PdfReader reader3 = new PdfReader(new FileStream(filename2, FileMode.Open, FileAccess.Read)); + PdfReader reader3 = new PdfReader(filename2); PdfDocument pdfDoc3 = new PdfDocument(reader3); for (int i_1 = 0; i_1 < pdfDoc3.GetNumberOfPages(); i_1++) { pdfDoc3.GetPage(i_1 + 1); @@ -762,7 +710,7 @@ public virtual void StampingXmp2() { NUnit.Framework.Assert.AreEqual("%page " + i_2 + "\n", iText.IO.Util.JavaUtil.GetStringForBytes(bytes), "Page content at page " + i_2); } - reader.Close(); + pdfDocument.Close(); } /// @@ -770,24 +718,19 @@ public virtual void StampingXmp2() { public virtual void StampingAppend1() { String filename1 = destinationFolder + "stampingAppend1_1.pdf"; String filename2 = destinationFolder + "stampingAppend1_2.pdf"; - FileStream fos1 = new FileStream(filename1, FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1); - PdfDocument pdfDoc1 = new PdfDocument(writer1); + PdfDocument pdfDoc1 = new PdfDocument(new PdfWriter(filename1)); pdfDoc1.GetDocumentInfo().SetAuthor("Alexander Chingarev").SetCreator("iText 6").SetTitle("Empty iText 6 Document" ); PdfPage page1 = pdfDoc1.AddNewPage(); page1.GetContentStream(0).GetOutputStream().Write(ByteUtils.GetIsoBytes("%Hello World\n")); page1.Flush(); pdfDoc1.Close(); - FileStream fis2 = new FileStream(filename1, FileMode.Open, FileAccess.Read); - PdfReader reader2 = new PdfReader(fis2); - FileStream fos2 = new FileStream(filename2, FileMode.Create); - PdfWriter writer2 = new PdfWriter(fos2); - PdfDocument pdfDoc2 = new PdfDocument(reader2, writer2, new StampingProperties().UseAppendMode()); + PdfDocument pdfDoc2 = new PdfDocument(new PdfReader(filename1), new PdfWriter(filename2), new StampingProperties + ().UseAppendMode()); pdfDoc2.GetDocumentInfo().SetCreator("iText 7").SetTitle("Empty iText 7 Document"); pdfDoc2.GetDocumentInfo().SetModified(); pdfDoc2.Close(); - PdfReader reader3 = new PdfReader(new FileStream(filename2, FileMode.Open, FileAccess.Read)); + PdfReader reader3 = new PdfReader(filename2); PdfDocument pdfDoc3 = new PdfDocument(reader3); for (int i = 0; i < pdfDoc3.GetNumberOfPages(); i++) { pdfDoc3.GetPage(i + 1); @@ -810,7 +753,7 @@ public virtual void StampingAppend1() { double diff = DateTimeUtil.GetUtcMillisFromEpoch(null) - DateTimeUtil.GetUtcMillisFromEpoch(cl); String message = "Unexpected creation date. Different from now is " + (float)diff / 1000 + "s"; NUnit.Framework.Assert.IsTrue(diff < 5000, message); - reader.Close(); + pdfDocument.Close(); } /// @@ -818,24 +761,19 @@ public virtual void StampingAppend1() { public virtual void StampingAppend2() { String filename1 = destinationFolder + "stampingAppend2_1.pdf"; String filename2 = destinationFolder + "stampingAppend2_2.pdf"; - FileStream fos1 = new FileStream(filename1, FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1); - PdfDocument pdfDoc1 = new PdfDocument(writer1); + PdfDocument pdfDoc1 = new PdfDocument(new PdfWriter(filename1)); PdfPage page1 = pdfDoc1.AddNewPage(); page1.GetContentStream(0).GetOutputStream().Write(ByteUtils.GetIsoBytes("%page 1\n")); page1.Flush(); pdfDoc1.Close(); - FileStream fis2 = new FileStream(filename1, FileMode.Open, FileAccess.Read); - PdfReader reader2 = new PdfReader(fis2); - FileStream fos2 = new FileStream(filename2, FileMode.Create); - PdfWriter writer2 = new PdfWriter(fos2); - PdfDocument pdfDoc2 = new PdfDocument(reader2, writer2, new StampingProperties().UseAppendMode()); + PdfDocument pdfDoc2 = new PdfDocument(new PdfReader(filename1), new PdfWriter(filename2), new StampingProperties + ().UseAppendMode()); PdfPage page2 = pdfDoc2.AddNewPage(); page2.GetContentStream(0).GetOutputStream().Write(ByteUtils.GetIsoBytes("%page 2\n")); page2.SetModified(); page2.Flush(); pdfDoc2.Close(); - PdfReader reader3 = new PdfReader(new FileStream(filename2, FileMode.Open, FileAccess.Read)); + PdfReader reader3 = new PdfReader(filename2); PdfDocument pdfDoc3 = new PdfDocument(reader3); for (int i = 0; i < pdfDoc3.GetNumberOfPages(); i++) { pdfDoc3.GetPage(i + 1); @@ -851,7 +789,7 @@ public virtual void StampingAppend2() { NUnit.Framework.Assert.AreEqual("%page 1\n", iText.IO.Util.JavaUtil.GetStringForBytes(bytes)); bytes = pdfDocument.GetPage(2).GetContentBytes(); NUnit.Framework.Assert.AreEqual("%page 2\n", iText.IO.Util.JavaUtil.GetStringForBytes(bytes)); - reader.Close(); + pdfDocument.Close(); } /// @@ -859,23 +797,19 @@ public virtual void StampingAppend2() { public virtual void StampingAppend3() { String filename1 = destinationFolder + "stampingAppend3_1.pdf"; String filename2 = destinationFolder + "stampingAppend3_2.pdf"; - FileStream fos1 = new FileStream(filename1, FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1, new WriterProperties().SetFullCompressionMode(true)); + PdfWriter writer1 = new PdfWriter(filename1, new WriterProperties().SetFullCompressionMode(true)); PdfDocument pdfDoc1 = new PdfDocument(writer1); PdfPage page1 = pdfDoc1.AddNewPage(); page1.GetContentStream(0).GetOutputStream().Write(ByteUtils.GetIsoBytes("%page 1\n")); page1.Flush(); pdfDoc1.Close(); - FileStream fis2 = new FileStream(filename1, FileMode.Open, FileAccess.Read); - PdfReader reader2 = new PdfReader(fis2); - FileStream fos2 = new FileStream(filename2, FileMode.Create); - PdfWriter writer2 = new PdfWriter(fos2); - PdfDocument pdfDoc2 = new PdfDocument(reader2, writer2, new StampingProperties().UseAppendMode()); + PdfDocument pdfDoc2 = new PdfDocument(new PdfReader(filename1), new PdfWriter(filename2), new StampingProperties + ().UseAppendMode()); PdfPage page2 = pdfDoc2.AddNewPage(); page2.GetContentStream(0).GetOutputStream().Write(ByteUtils.GetIsoBytes("%page 2\n")); page2.Flush(); pdfDoc2.Close(); - PdfReader reader3 = new PdfReader(new FileStream(filename2, FileMode.Open, FileAccess.Read)); + PdfReader reader3 = new PdfReader(filename2); PdfDocument pdfDoc3 = new PdfDocument(reader3); for (int i = 0; i < pdfDoc3.GetNumberOfPages(); i++) { pdfDoc3.GetPage(i + 1); @@ -891,7 +825,7 @@ public virtual void StampingAppend3() { NUnit.Framework.Assert.AreEqual("%page 1\n", iText.IO.Util.JavaUtil.GetStringForBytes(bytes)); bytes = pdfDocument.GetPage(2).GetContentBytes(); NUnit.Framework.Assert.AreEqual("%page 2\n", iText.IO.Util.JavaUtil.GetStringForBytes(bytes)); - reader.Close(); + pdfDocument.Close(); } /// @@ -899,26 +833,21 @@ public virtual void StampingAppend3() { public virtual void StampingAppend4() { String filename1 = destinationFolder + "stampingAppend4_1.pdf"; String filename2 = destinationFolder + "stampingAppend4_2.pdf"; - FileStream fos1 = new FileStream(filename1, FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1); - PdfDocument pdfDoc1 = new PdfDocument(writer1); + PdfDocument pdfDoc1 = new PdfDocument(new PdfWriter(filename1)); PdfPage page1 = pdfDoc1.AddNewPage(); page1.GetContentStream(0).GetOutputStream().Write(ByteUtils.GetIsoBytes("%page 1\n")); page1.Flush(); pdfDoc1.Close(); int pageCount = 15; - FileStream fis2 = new FileStream(filename1, FileMode.Open, FileAccess.Read); - PdfReader reader2 = new PdfReader(fis2); - FileStream fos2 = new FileStream(filename2, FileMode.Create); - PdfWriter writer2 = new PdfWriter(fos2); - PdfDocument pdfDoc2 = new PdfDocument(reader2, writer2, new StampingProperties().UseAppendMode()); + PdfDocument pdfDoc2 = new PdfDocument(new PdfReader(filename1), new PdfWriter(filename2), new StampingProperties + ().UseAppendMode()); for (int i = 2; i <= pageCount; i++) { PdfPage page2 = pdfDoc2.AddNewPage(); page2.GetContentStream(0).GetOutputStream().Write(ByteUtils.GetIsoBytes("%page " + i + "\n")); page2.Flush(); } pdfDoc2.Close(); - PdfReader reader3 = new PdfReader(new FileStream(filename2, FileMode.Open, FileAccess.Read)); + PdfReader reader3 = new PdfReader(filename2); PdfDocument pdfDoc3 = new PdfDocument(reader3); for (int i_1 = 0; i_1 < pdfDoc3.GetNumberOfPages(); i_1++) { pdfDoc3.GetPage(i_1 + 1); @@ -935,7 +864,7 @@ public virtual void StampingAppend4() { byte[] bytes = pdfDocument.GetPage(i_2).GetContentBytes(); NUnit.Framework.Assert.AreEqual("%page " + i_2 + "\n", iText.IO.Util.JavaUtil.GetStringForBytes(bytes)); } - reader.Close(); + pdfDocument.Close(); } /// @@ -943,18 +872,14 @@ public virtual void StampingAppend4() { public virtual void StampingAppend5() { String filename1 = destinationFolder + "stampingAppend5_1.pdf"; String filename2 = destinationFolder + "stampingAppend5_2.pdf"; - FileStream fos1 = new FileStream(filename1, FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1); - PdfDocument pdfDoc1 = new PdfDocument(writer1); + PdfDocument pdfDoc1 = new PdfDocument(new PdfWriter(filename1)); PdfPage page1 = pdfDoc1.AddNewPage(); page1.GetContentStream(0).GetOutputStream().Write(ByteUtils.GetIsoBytes("%page 1\n")); page1.Flush(); pdfDoc1.Close(); int pageCount = 15; - FileStream fis2 = new FileStream(filename1, FileMode.Open, FileAccess.Read); - PdfReader reader2 = new PdfReader(fis2); - FileStream fos2 = new FileStream(filename2, FileMode.Create); - PdfWriter writer2 = new PdfWriter(fos2, new WriterProperties().SetFullCompressionMode(true)); + PdfReader reader2 = new PdfReader(filename1); + PdfWriter writer2 = new PdfWriter(filename2, new WriterProperties().SetFullCompressionMode(true)); PdfDocument pdfDoc2 = new PdfDocument(reader2, writer2, new StampingProperties().UseAppendMode()); for (int i = 2; i <= pageCount; i++) { PdfPage page2 = pdfDoc2.AddNewPage(); @@ -962,7 +887,7 @@ public virtual void StampingAppend5() { page2.Flush(); } pdfDoc2.Close(); - PdfReader reader3 = new PdfReader(new FileStream(filename2, FileMode.Open, FileAccess.Read)); + PdfReader reader3 = new PdfReader(filename2); PdfDocument pdfDoc3 = new PdfDocument(reader3); for (int i_1 = 0; i_1 < pdfDoc3.GetNumberOfPages(); i_1++) { pdfDoc3.GetPage(i_1 + 1); @@ -979,7 +904,7 @@ public virtual void StampingAppend5() { byte[] bytes = pdfDocument.GetPage(i_2).GetContentBytes(); NUnit.Framework.Assert.AreEqual("%page " + i_2 + "\n", iText.IO.Util.JavaUtil.GetStringForBytes(bytes)); } - reader.Close(); + pdfDocument.Close(); } /// @@ -988,8 +913,7 @@ public virtual void StampingAppend8() { String filename1 = destinationFolder + "stampingAppend8_1.pdf"; String filename2 = destinationFolder + "stampingAppend8_2.pdf"; int pageCount = 10; - FileStream fos1 = new FileStream(filename1, FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1, new WriterProperties().SetFullCompressionMode(true)); + PdfWriter writer1 = new PdfWriter(filename1, new WriterProperties().SetFullCompressionMode(true)); PdfDocument pdfDoc1 = new PdfDocument(writer1); for (int i = 1; i <= pageCount; i++) { PdfPage page = pdfDoc1.AddNewPage(); @@ -997,11 +921,10 @@ public virtual void StampingAppend8() { page.Flush(); } pdfDoc1.Close(); - PdfReader reader2 = new PdfReader(new FileStream(filename1, FileMode.Open, FileAccess.Read)); - PdfWriter writer2 = new PdfWriter(new FileStream(filename2, FileMode.Create)); - PdfDocument pdfDoc2 = new PdfDocument(reader2, writer2, new StampingProperties().UseAppendMode()); + PdfDocument pdfDoc2 = new PdfDocument(new PdfReader(filename1), new PdfWriter(filename2), new StampingProperties + ().UseAppendMode()); pdfDoc2.Close(); - PdfReader reader3 = new PdfReader(new FileStream(filename2, FileMode.Open, FileAccess.Read)); + PdfReader reader3 = new PdfReader(filename2); PdfDocument pdfDoc3 = new PdfDocument(reader3); for (int i_1 = 0; i_1 < pdfDoc3.GetNumberOfPages(); i_1++) { pdfDoc3.GetPage(i_1 + 1); @@ -1019,7 +942,7 @@ public virtual void StampingAppend8() { NUnit.Framework.Assert.AreEqual("%page " + i_2 + "\n", iText.IO.Util.JavaUtil.GetStringForBytes(bytes), "Page content at page " + i_2); } - reader.Close(); + pdfDocument.Close(); } /// @@ -1028,8 +951,7 @@ public virtual void StampingAppend9() { String filename1 = destinationFolder + "stampingAppend9_1.pdf"; String filename2 = destinationFolder + "stampingAppend9_2.pdf"; int pageCount = 10; - FileStream fos1 = new FileStream(filename1, FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1, new WriterProperties().SetFullCompressionMode(false)); + PdfWriter writer1 = new PdfWriter(filename1, new WriterProperties().SetFullCompressionMode(false)); PdfDocument pdfDoc1 = new PdfDocument(writer1); for (int i = 1; i <= pageCount; i++) { PdfPage page = pdfDoc1.AddNewPage(); @@ -1037,12 +959,11 @@ public virtual void StampingAppend9() { page.Flush(); } pdfDoc1.Close(); - PdfReader reader2 = new PdfReader(new FileStream(filename1, FileMode.Open, FileAccess.Read)); - PdfWriter writer2 = new PdfWriter(new FileStream(filename2, FileMode.Create), new WriterProperties().SetFullCompressionMode - (true)); + PdfReader reader2 = new PdfReader(filename1); + PdfWriter writer2 = new PdfWriter(filename2, new WriterProperties().SetFullCompressionMode(true)); PdfDocument pdfDoc2 = new PdfDocument(reader2, writer2, new StampingProperties().UseAppendMode()); pdfDoc2.Close(); - PdfReader reader3 = new PdfReader(new FileStream(filename2, FileMode.Open, FileAccess.Read)); + PdfReader reader3 = new PdfReader(filename2); PdfDocument pdfDoc3 = new PdfDocument(reader3); for (int i_1 = 0; i_1 < pdfDoc3.GetNumberOfPages(); i_1++) { pdfDoc3.GetPage(i_1 + 1); @@ -1060,7 +981,7 @@ public virtual void StampingAppend9() { NUnit.Framework.Assert.AreEqual("%page " + i_2 + "\n", iText.IO.Util.JavaUtil.GetStringForBytes(bytes), "Page content at page " + i_2); } - reader.Close(); + pdfDocument.Close(); } /// @@ -1069,8 +990,7 @@ public virtual void StampingAppend10() { String filename1 = destinationFolder + "stampingAppend10_1.pdf"; String filename2 = destinationFolder + "stampingAppend10_2.pdf"; int pageCount = 10; - FileStream fos1 = new FileStream(filename1, FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1, new WriterProperties().SetFullCompressionMode(true)); + PdfWriter writer1 = new PdfWriter(filename1, new WriterProperties().SetFullCompressionMode(true)); PdfDocument pdfDoc1 = new PdfDocument(writer1); for (int i = 1; i <= pageCount; i++) { PdfPage page = pdfDoc1.AddNewPage(); @@ -1078,12 +998,11 @@ public virtual void StampingAppend10() { page.Flush(); } pdfDoc1.Close(); - PdfReader reader2 = new PdfReader(new FileStream(filename1, FileMode.Open, FileAccess.Read)); - PdfWriter writer2 = new PdfWriter(new FileStream(filename2, FileMode.Create), new WriterProperties().SetFullCompressionMode - (false)); + PdfReader reader2 = new PdfReader(filename1); + PdfWriter writer2 = new PdfWriter(filename2, new WriterProperties().SetFullCompressionMode(false)); PdfDocument pdfDoc2 = new PdfDocument(reader2, writer2, new StampingProperties().UseAppendMode()); pdfDoc2.Close(); - PdfReader reader3 = new PdfReader(new FileStream(filename2, FileMode.Open, FileAccess.Read)); + PdfReader reader3 = new PdfReader(filename2); PdfDocument pdfDoc3 = new PdfDocument(reader3); for (int i_1 = 0; i_1 < pdfDoc3.GetNumberOfPages(); i_1++) { pdfDoc3.GetPage(i_1 + 1); @@ -1101,7 +1020,7 @@ public virtual void StampingAppend10() { NUnit.Framework.Assert.AreEqual("%page " + i_2 + "\n", iText.IO.Util.JavaUtil.GetStringForBytes(bytes), "Page content at page " + i_2); } - reader.Close(); + pdfDocument.Close(); } /// @@ -1110,8 +1029,7 @@ public virtual void StampingAppend11() { String filename1 = destinationFolder + "stampingAppend11_1.pdf"; String filename2 = destinationFolder + "stampingAppend11_2.pdf"; int pageCount = 10; - FileStream fos1 = new FileStream(filename1, FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1, new WriterProperties().SetFullCompressionMode(false)); + PdfWriter writer1 = new PdfWriter(filename1, new WriterProperties().SetFullCompressionMode(false)); PdfDocument pdfDoc1 = new PdfDocument(writer1); for (int i = 1; i <= pageCount; i++) { PdfPage page = pdfDoc1.AddNewPage(); @@ -1119,12 +1037,11 @@ public virtual void StampingAppend11() { page.Flush(); } pdfDoc1.Close(); - PdfReader reader2 = new PdfReader(new FileStream(filename1, FileMode.Open, FileAccess.Read)); - PdfWriter writer2 = new PdfWriter(new FileStream(filename2, FileMode.Create), new WriterProperties().SetFullCompressionMode - (false)); + PdfReader reader2 = new PdfReader(filename1); + PdfWriter writer2 = new PdfWriter(filename2, new WriterProperties().SetFullCompressionMode(false)); PdfDocument pdfDoc2 = new PdfDocument(reader2, writer2, new StampingProperties().UseAppendMode()); pdfDoc2.Close(); - PdfReader reader3 = new PdfReader(new FileStream(filename2, FileMode.Open, FileAccess.Read)); + PdfReader reader3 = new PdfReader(filename2); PdfDocument pdfDoc3 = new PdfDocument(reader3); for (int i_1 = 0; i_1 < pdfDoc3.GetNumberOfPages(); i_1++) { pdfDoc3.GetPage(i_1 + 1); @@ -1142,7 +1059,7 @@ public virtual void StampingAppend11() { NUnit.Framework.Assert.AreEqual("%page " + i_2 + "\n", iText.IO.Util.JavaUtil.GetStringForBytes(bytes), "Page content at page " + i_2); } - reader.Close(); + pdfDocument.Close(); } /// @@ -1151,9 +1068,7 @@ public virtual void StampingVersionTest01() { // By default the version of the output file should be the same as the original one String @in = sourceFolder + "hello.pdf"; String @out = destinationFolder + "hello_stamped01.pdf"; - FileStream fis = new FileStream(@in, FileMode.Open, FileAccess.Read); - PdfReader reader = new PdfReader(fis); - PdfDocument pdfDoc = new PdfDocument(reader, new PdfWriter(@out)); + PdfDocument pdfDoc = new PdfDocument(new PdfReader(@in), new PdfWriter(@out)); NUnit.Framework.Assert.AreEqual(PdfVersion.PDF_1_4, pdfDoc.GetPdfVersion()); pdfDoc.Close(); PdfDocument assertPdfDoc = new PdfDocument(new PdfReader(@out)); @@ -1167,10 +1082,8 @@ public virtual void StampingVersionTest02() { // There is a possibility to override version in stamping mode String @in = sourceFolder + "hello.pdf"; String @out = destinationFolder + "hello_stamped02.pdf"; - FileStream fis = new FileStream(@in, FileMode.Open, FileAccess.Read); - PdfReader reader = new PdfReader(fis); - PdfDocument pdfDoc = new PdfDocument(reader, new PdfWriter(@out, new WriterProperties().SetPdfVersion(PdfVersion - .PDF_2_0))); + PdfDocument pdfDoc = new PdfDocument(new PdfReader(@in), new PdfWriter(@out, new WriterProperties().SetPdfVersion + (PdfVersion.PDF_2_0))); NUnit.Framework.Assert.AreEqual(PdfVersion.PDF_2_0, pdfDoc.GetPdfVersion()); pdfDoc.Close(); PdfDocument assertPdfDoc = new PdfDocument(new PdfReader(@out)); @@ -1184,8 +1097,7 @@ public virtual void StampingAppendVersionTest01() { // There is a possibility to override version in stamping mode String @in = sourceFolder + "hello.pdf"; String @out = destinationFolder + "stampingAppendVersionTest01.pdf"; - FileStream fis = new FileStream(@in, FileMode.Open, FileAccess.Read); - PdfReader reader = new PdfReader(fis); + PdfReader reader = new PdfReader(@in); PdfWriter writer = new PdfWriter(@out, new WriterProperties().SetPdfVersion(PdfVersion.PDF_2_0)); PdfDocument pdfDoc = new PdfDocument(reader, writer, new StampingProperties().UseAppendMode()); NUnit.Framework.Assert.AreEqual(PdfVersion.PDF_2_0, pdfDoc.GetPdfVersion()); @@ -1199,10 +1111,8 @@ public virtual void StampingAppendVersionTest01() { [NUnit.Framework.Test] public virtual void StampingTestWithTaggedStructure() { String filename = sourceFolder + "iphone_user_guide.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); - FileStream fos = new FileStream(destinationFolder + "stampingDocWithTaggedStructure.pdf", FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument pdfDoc = new PdfDocument(reader, writer); + PdfDocument pdfDoc = new PdfDocument(new PdfReader(filename), new PdfWriter(destinationFolder + "stampingDocWithTaggedStructure.pdf" + )); pdfDoc.Close(); } @@ -1210,9 +1120,8 @@ public virtual void StampingTestWithTaggedStructure() { /// [NUnit.Framework.Test] public virtual void StampingTestWithFullCompression01() { - PdfReader reader = new PdfReader(sourceFolder + "fullCompressedDocument.pdf"); - PdfDocument pdfDoc = new PdfDocument(reader, new PdfWriter(destinationFolder + "stampingTestWithFullCompression01.pdf" - )); + PdfDocument pdfDoc = new PdfDocument(new PdfReader(sourceFolder + "fullCompressedDocument.pdf"), new PdfWriter + (destinationFolder + "stampingTestWithFullCompression01.pdf")); pdfDoc.Close(); float result = new FileInfo(destinationFolder + "stampingTestWithFullCompression01.pdf").Length; float expected = new FileInfo(sourceFolder + "cmp_stampingTestWithFullCompression01.pdf").Length; @@ -1224,9 +1133,9 @@ public virtual void StampingTestWithFullCompression01() { /// [NUnit.Framework.Test] public virtual void StampingTestWithFullCompression02() { - PdfReader reader = new PdfReader(sourceFolder + "fullCompressedDocument.pdf"); - PdfDocument pdfDoc = new PdfDocument(reader, new PdfWriter(destinationFolder + "stampingTestWithFullCompression02.pdf" - , new WriterProperties().SetFullCompressionMode(false))); + PdfDocument pdfDoc = new PdfDocument(new PdfReader(sourceFolder + "fullCompressedDocument.pdf"), new PdfWriter + (destinationFolder + "stampingTestWithFullCompression02.pdf", new WriterProperties().SetFullCompressionMode + (false))); pdfDoc.Close(); float result = new FileInfo(destinationFolder + "stampingTestWithFullCompression02.pdf").Length; float expected = new FileInfo(sourceFolder + "cmp_stampingTestWithFullCompression02.pdf").Length; diff --git a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfStructElemTest.cs b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfStructElemTest.cs index 284bfe1e12..a855665583 100644 --- a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfStructElemTest.cs +++ b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfStructElemTest.cs @@ -3,6 +3,7 @@ using System.IO; using iText.IO; using iText.IO.Font; +using iText.Kernel; using iText.Kernel.Font; using iText.Kernel.Geom; using iText.Kernel.Pdf.Annot; @@ -27,8 +28,7 @@ public static void BeforeClass() { /// [NUnit.Framework.Test] public virtual void StructElemTest01() { - FileStream fos = new FileStream(destinationFolder + "structElemTest01.pdf", FileMode.Create); - PdfWriter writer = new PdfWriter(fos); + PdfWriter writer = new PdfWriter(destinationFolder + "structElemTest01.pdf"); writer.SetCompressionLevel(CompressionConstants.NO_COMPRESSION); PdfDocument document = new PdfDocument(writer); document.SetTagged(); @@ -73,8 +73,7 @@ public virtual void StructElemTest01() { /// [NUnit.Framework.Test] public virtual void StructElemTest02() { - FileStream fos = new FileStream(destinationFolder + "structElemTest02.pdf", FileMode.Create); - PdfWriter writer = new PdfWriter(fos); + PdfWriter writer = new PdfWriter(destinationFolder + "structElemTest02.pdf"); writer.SetCompressionLevel(CompressionConstants.NO_COMPRESSION); PdfDocument document = new PdfDocument(writer); document.SetTagged(); @@ -104,8 +103,7 @@ public virtual void StructElemTest02() { /// [NUnit.Framework.Test] public virtual void StructElemTest03() { - FileStream fos = new FileStream(destinationFolder + "structElemTest03.pdf", FileMode.Create); - PdfWriter writer = new PdfWriter(fos); + PdfWriter writer = new PdfWriter(destinationFolder + "structElemTest03.pdf"); writer.SetCompressionLevel(CompressionConstants.NO_COMPRESSION); PdfDocument document = new PdfDocument(writer); document.SetTagged(); @@ -146,9 +144,7 @@ public virtual void StructElemTest03() { page1.Flush(); page2.Flush(); document.Close(); - PdfReader reader = new PdfReader(new FileStream(destinationFolder + "structElemTest03.pdf", FileMode.Open, - FileAccess.Read)); - document = new PdfDocument(reader); + document = new PdfDocument(new PdfReader(destinationFolder + "structElemTest03.pdf")); NUnit.Framework.Assert.AreEqual(2, (int)document.GetNextStructParentIndex()); PdfPage page = document.GetPage(1); NUnit.Framework.Assert.AreEqual(0, page.GetStructParentIndex()); @@ -186,7 +182,7 @@ public virtual void StructElemTest04() { document.Close(); byte[] bytes = baos.ToArray(); PdfReader reader = new PdfReader(new MemoryStream(bytes)); - writer = new PdfWriter(new FileStream(destinationFolder + "structElemTest04.pdf", FileMode.Create)); + writer = new PdfWriter(destinationFolder + "structElemTest04.pdf"); writer.SetCompressionLevel(CompressionConstants.NO_COMPRESSION); document = new PdfDocument(reader, writer); page = document.GetPage(1); @@ -215,8 +211,7 @@ public virtual void StructElemTest04() { /// [NUnit.Framework.Test] public virtual void StructElemTest05() { - FileStream fos = new FileStream(destinationFolder + "structElemTest05.pdf", FileMode.Create); - PdfWriter writer = new PdfWriter(fos); + PdfWriter writer = new PdfWriter(destinationFolder + "structElemTest05.pdf"); writer.SetCompressionLevel(CompressionConstants.NO_COMPRESSION); PdfDocument document = new PdfDocument(writer); document.SetTagged(); @@ -253,8 +248,7 @@ public virtual void StructElemTest05() { /// [NUnit.Framework.Test] public virtual void StructElemTest06() { - FileStream fos = new FileStream(destinationFolder + "structElemTest06.pdf", FileMode.Create); - PdfWriter writer = new PdfWriter(fos); + PdfWriter writer = new PdfWriter(destinationFolder + "structElemTest06.pdf"); writer.SetCompressionLevel(CompressionConstants.NO_COMPRESSION); PdfDocument document = new PdfDocument(writer); document.SetTagged(); @@ -281,12 +275,9 @@ public virtual void StructElemTest06() { [NUnit.Framework.Test] [LogMessage(LogMessageConstant.SOURCE_DOCUMENT_HAS_ACROFORM_DICTIONARY)] public virtual void StructTreeCopyingTest01() { - FileStream fis = new FileStream(sourceFolder + "iphone_user_guide.pdf", FileMode.Open, FileAccess.Read); - PdfReader reader = new PdfReader(fis); - PdfDocument source = new PdfDocument(reader); - PdfWriter writer = new PdfWriter(new FileStream(destinationFolder + "structTreeCopyingTest01.pdf", FileMode.Create - )); - PdfDocument destination = new PdfDocument(writer); + PdfDocument source = new PdfDocument(new PdfReader(sourceFolder + "iphone_user_guide.pdf")); + PdfDocument destination = new PdfDocument(new PdfWriter(destinationFolder + "structTreeCopyingTest01.pdf") + ); destination.SetTagged(); destination.InitializeOutlines(); List pagesToCopy = new List(); @@ -305,12 +296,9 @@ public virtual void StructTreeCopyingTest01() { [NUnit.Framework.Test] [LogMessage(LogMessageConstant.SOURCE_DOCUMENT_HAS_ACROFORM_DICTIONARY)] public virtual void StructTreeCopyingTest02() { - FileStream fis = new FileStream(sourceFolder + "iphone_user_guide.pdf", FileMode.Open, FileAccess.Read); - PdfReader reader = new PdfReader(fis); - PdfDocument source = new PdfDocument(reader); - PdfWriter writer = new PdfWriter(new FileStream(destinationFolder + "structTreeCopyingTest02.pdf", FileMode.Create - )); - PdfDocument destination = new PdfDocument(writer); + PdfDocument source = new PdfDocument(new PdfReader(sourceFolder + "iphone_user_guide.pdf")); + PdfDocument destination = new PdfDocument(new PdfWriter(destinationFolder + "structTreeCopyingTest02.pdf") + ); destination.SetTagged(); destination.InitializeOutlines(); source.CopyPagesTo(6, source.GetNumberOfPages(), destination); @@ -324,12 +312,9 @@ public virtual void StructTreeCopyingTest02() { [NUnit.Framework.Test] [LogMessage(LogMessageConstant.SOURCE_DOCUMENT_HAS_ACROFORM_DICTIONARY)] public virtual void StructTreeCopyingTest03() { - FileStream fis = new FileStream(sourceFolder + "iphone_user_guide.pdf", FileMode.Open, FileAccess.Read); - PdfReader reader = new PdfReader(fis); - PdfDocument source = new PdfDocument(reader); - PdfWriter writer = new PdfWriter(new FileStream(destinationFolder + "structTreeCopyingTest03.pdf", FileMode.Create - )); - PdfDocument destination = new PdfDocument(writer); + PdfDocument source = new PdfDocument(new PdfReader(sourceFolder + "iphone_user_guide.pdf")); + PdfDocument destination = new PdfDocument(new PdfWriter(destinationFolder + "structTreeCopyingTest03.pdf") + ); destination.InitializeOutlines(); source.CopyPagesTo(6, source.GetNumberOfPages(), destination); source.CopyPagesTo(1, 5, destination); @@ -344,12 +329,9 @@ public virtual void StructTreeCopyingTest03() { [NUnit.Framework.Test] [LogMessage(LogMessageConstant.SOURCE_DOCUMENT_HAS_ACROFORM_DICTIONARY)] public virtual void StructTreeCopyingTest04() { - FileStream fis = new FileStream(sourceFolder + "iphone_user_guide.pdf", FileMode.Open, FileAccess.Read); - PdfReader reader = new PdfReader(fis); - PdfDocument source = new PdfDocument(reader); - PdfWriter writer = new PdfWriter(new FileStream(destinationFolder + "structTreeCopyingTest04.pdf", FileMode.Create - )); - PdfDocument destination = new PdfDocument(writer); + PdfDocument source = new PdfDocument(new PdfReader(sourceFolder + "iphone_user_guide.pdf")); + PdfDocument destination = new PdfDocument(new PdfWriter(destinationFolder + "structTreeCopyingTest04.pdf") + ); destination.SetTagged(); destination.InitializeOutlines(); for (int i = 1; i <= source.GetNumberOfPages(); i++) { @@ -363,18 +345,11 @@ public virtual void StructTreeCopyingTest04() { /// [NUnit.Framework.Test] public virtual void StructTreeCopyingTest05() { - PdfReader reader = new PdfReader(new FileStream(sourceFolder + "iphone_user_guide.pdf", FileMode.Open, FileAccess.Read - )); - PdfWriter writer = new PdfWriter(new FileStream(destinationFolder + "structTreeCopyingTest05.pdf", FileMode.Create - )); - PdfDocument document = new PdfDocument(reader, writer); - PdfReader reader1 = new PdfReader(new FileStream(sourceFolder + "quick-brown-fox.pdf", FileMode.Open, FileAccess.Read - )); - PdfDocument document1 = new PdfDocument(reader1); + PdfDocument document = new PdfDocument(new PdfReader(sourceFolder + "iphone_user_guide.pdf"), new PdfWriter + (destinationFolder + "structTreeCopyingTest05.pdf")); + PdfDocument document1 = new PdfDocument(new PdfReader(sourceFolder + "quick-brown-fox.pdf")); document1.CopyPagesTo(1, 1, document, 2); - PdfReader reader2 = new PdfReader(new FileStream(sourceFolder + "quick-brown-fox-table.pdf", FileMode.Open - , FileAccess.Read)); - PdfDocument document2 = new PdfDocument(reader2); + PdfDocument document2 = new PdfDocument(new PdfReader(sourceFolder + "quick-brown-fox-table.pdf")); document2.CopyPagesTo(1, 3, document, 4); document.Close(); document1.Close(); @@ -386,12 +361,9 @@ public virtual void StructTreeCopyingTest05() { [NUnit.Framework.Test] [LogMessage(LogMessageConstant.SOURCE_DOCUMENT_HAS_ACROFORM_DICTIONARY)] public virtual void StructTreeCopyingTest06() { - FileStream fis = new FileStream(sourceFolder + "iphone_user_guide.pdf", FileMode.Open, FileAccess.Read); - PdfReader reader = new PdfReader(fis); - PdfDocument source = new PdfDocument(reader); - PdfWriter writer = new PdfWriter(new FileStream(destinationFolder + "structTreeCopyingTest06.pdf", FileMode.Create - )); - PdfDocument destination = new PdfDocument(writer); + PdfDocument source = new PdfDocument(new PdfReader(sourceFolder + "iphone_user_guide.pdf")); + PdfDocument destination = new PdfDocument(new PdfWriter(destinationFolder + "structTreeCopyingTest06.pdf") + ); destination.SetTagged(); destination.InitializeOutlines(); source.CopyPagesTo(1, source.GetNumberOfPages(), destination); @@ -403,10 +375,8 @@ public virtual void StructTreeCopyingTest06() { /// [NUnit.Framework.Test] public virtual void StructTreeCopyingTest07() { - PdfReader reader = new PdfReader(new FileStream(sourceFolder + "quick-brown-fox.pdf", FileMode.Open, FileAccess.Read - )); - PdfWriter writer = new PdfWriter(new FileStream(destinationFolder + "structTreeCopyingTest07.pdf", FileMode.Create - )); + PdfReader reader = new PdfReader(sourceFolder + "quick-brown-fox.pdf"); + PdfWriter writer = new PdfWriter(destinationFolder + "structTreeCopyingTest07.pdf"); PdfDocument document = new PdfDocument(writer); document.SetTagged(); PdfStructElem doc = document.GetStructTreeRoot().AddKid(new PdfStructElem(document, PdfName.Document)); @@ -436,14 +406,9 @@ public virtual void StructTreeCopyingTest07() { /// [NUnit.Framework.Test] public virtual void StructTreeCopyingTest08() { - PdfReader reader = new PdfReader(new FileStream(sourceFolder + "quick-brown-fox-table.pdf", FileMode.Open, - FileAccess.Read)); - PdfWriter writer = new PdfWriter(new FileStream(destinationFolder + "structTreeCopyingTest08.pdf", FileMode.Create - )); - PdfDocument document = new PdfDocument(reader, writer); - PdfReader reader1 = new PdfReader(new FileStream(sourceFolder + "quick-brown-fox.pdf", FileMode.Open, FileAccess.Read - )); - PdfDocument document1 = new PdfDocument(reader1); + PdfDocument document = new PdfDocument(new PdfReader(sourceFolder + "quick-brown-fox-table.pdf"), new PdfWriter + (destinationFolder + "structTreeCopyingTest08.pdf")); + PdfDocument document1 = new PdfDocument(new PdfReader(sourceFolder + "quick-brown-fox.pdf")); document1.InitializeOutlines(); document1.CopyPagesTo(1, 1, document, 2); document.Close(); @@ -454,14 +419,9 @@ public virtual void StructTreeCopyingTest08() { /// [NUnit.Framework.Test] public virtual void StructTreeCopyingTest09() { - PdfReader reader = new PdfReader(new FileStream(sourceFolder + "quick-brown-fox-table.pdf", FileMode.Open, - FileAccess.Read)); - PdfWriter writer = new PdfWriter(new FileStream(destinationFolder + "structTreeCopyingTest09.pdf", FileMode.Create - )); - PdfDocument document = new PdfDocument(reader, writer); - PdfReader reader1 = new PdfReader(new FileStream(sourceFolder + "quick-brown-fox.pdf", FileMode.Open, FileAccess.Read - )); - PdfDocument document1 = new PdfDocument(reader1); + PdfDocument document = new PdfDocument(new PdfReader(sourceFolder + "quick-brown-fox-table.pdf"), new PdfWriter + (destinationFolder + "structTreeCopyingTest09.pdf")); + PdfDocument document1 = new PdfDocument(new PdfReader(sourceFolder + "quick-brown-fox.pdf")); document1.InitializeOutlines(); document1.CopyPagesTo(1, 1, document, 2); document1.CopyPagesTo(1, 1, document, 4); @@ -473,19 +433,12 @@ public virtual void StructTreeCopyingTest09() { /// [NUnit.Framework.Test] public virtual void StructTreeCopyingTest10() { - PdfReader reader = new PdfReader(new FileStream(sourceFolder + "88th_Academy_Awards.pdf", FileMode.Open, FileAccess.Read - )); - PdfWriter writer = new PdfWriter(new FileStream(destinationFolder + "structTreeCopyingTest10.pdf", FileMode.Create - )); - PdfDocument document = new PdfDocument(reader, writer); - PdfReader reader1 = new PdfReader(new FileStream(sourceFolder + "quick-brown-fox-table.pdf", FileMode.Open - , FileAccess.Read)); - PdfDocument document1 = new PdfDocument(reader1); + PdfDocument document = new PdfDocument(new PdfReader(sourceFolder + "88th_Academy_Awards.pdf"), new PdfWriter + (destinationFolder + "structTreeCopyingTest10.pdf")); + PdfDocument document1 = new PdfDocument(new PdfReader(sourceFolder + "quick-brown-fox-table.pdf")); document1.InitializeOutlines(); document1.CopyPagesTo(1, 3, document, 2); - PdfReader reader2 = new PdfReader(new FileStream(sourceFolder + "quick-brown-fox.pdf", FileMode.Open, FileAccess.Read - )); - PdfDocument document2 = new PdfDocument(reader2); + PdfDocument document2 = new PdfDocument(new PdfReader(sourceFolder + "quick-brown-fox.pdf")); document2.InitializeOutlines(); document2.CopyPagesTo(1, 1, document, 4); document.Close(); @@ -494,6 +447,66 @@ public virtual void StructTreeCopyingTest10() { CompareResult("structTreeCopyingTest10.pdf", "cmp_structTreeCopyingTest10.pdf", "diff_copying_10_"); } + /// + [NUnit.Framework.Test] + [LogMessage(LogMessageConstant.ENCOUNTERED_INVALID_MCR, Count = 72)] + public virtual void CorruptedTagStructureTest01() { + PdfDocument document = new PdfDocument(new PdfReader(sourceFolder + "cocacola_corruptedTagStruct.pdf")); + NUnit.Framework.Assert.IsTrue(document.IsTagged()); + document.Close(); + } + + /// + [NUnit.Framework.Test] + [LogMessage(LogMessageConstant.TAG_STRUCTURE_INIT_FAILED)] + public virtual void CorruptedTagStructureTest02() { + PdfDocument document = new PdfDocument(new PdfReader(sourceFolder + "directStructElem01.pdf")); + NUnit.Framework.Assert.IsFalse(document.IsTagged()); + document.Close(); + } + + /// + [NUnit.Framework.Test] + public virtual void CorruptedTagStructureTest03() { + PdfReader reader = new PdfReader(sourceFolder + "directStructElem02.pdf"); + PdfWriter writer = new PdfWriter(new ByteBufferOutputStream()); + PdfDocument document = new PdfDocument(reader, writer); + NUnit.Framework.Assert.IsTrue(document.IsTagged()); + bool isThrown = false; + try { + document.Close(); + } + catch (PdfException ex) { + NUnit.Framework.Assert.AreEqual(ex.Message, PdfException.TagStructureFlushingFailedItMightBeCorrupted); + isThrown = true; + } + if (!isThrown) { + NUnit.Framework.Assert.Fail("Exception is expected."); + } + } + + /// + [NUnit.Framework.Test] + public virtual void CorruptedTagStructureTest04() { + PdfDocument document = new PdfDocument(new PdfReader(sourceFolder + "directStructElem03.pdf")); + NUnit.Framework.Assert.IsTrue(document.IsTagged()); + bool isThrown = false; + try { + PdfDocument docToCopyTo = new PdfDocument(new PdfWriter(new MemoryStream())); + docToCopyTo.SetTagged(); + document.CopyPagesTo(1, 1, docToCopyTo); + } + catch (PdfException ex) { + NUnit.Framework.Assert.AreEqual(ex.Message, PdfException.TagStructureCopyingFailedItMightBeCorruptedInOneOfTheDocuments + ); + isThrown = true; + } + document.Close(); + if (!isThrown) { + NUnit.Framework.Assert.Fail("Exception is expected."); + } + } + /// /// /// diff --git a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfTokenizerTest.cs b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfTokenizerTest.cs index c6b1cb9a4d..cfa663dd1b 100644 --- a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfTokenizerTest.cs +++ b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfTokenizerTest.cs @@ -9,7 +9,8 @@ public class PdfTokenizerTest { /// private void CheckTokenTypes(String data, params PdfTokenizer.TokenType[] expectedTypes) { RandomAccessSourceFactory factory = new RandomAccessSourceFactory(); - PdfTokenizer tok = new PdfTokenizer(new RandomAccessFileOrArray(factory.CreateSource(data.GetBytes()))); + PdfTokenizer tok = new PdfTokenizer(new RandomAccessFileOrArray(factory.CreateSource(data.GetBytes(iText.IO.Util.EncodingUtil.ISO_8859_1 + )))); for (int i = 0; i < expectedTypes.Length; i++) { tok.NextValidToken(); //System.out.println(tok.getTokenType() + " -> " + tok.getStringValue()); @@ -17,6 +18,18 @@ private void CheckTokenTypes(String data, params PdfTokenizer.TokenType[] expect } } + /// + private void CheckTokenValues(String data, params byte[][] expectedValues) { + RandomAccessSourceFactory factory = new RandomAccessSourceFactory(); + PdfTokenizer tok = new PdfTokenizer(new RandomAccessFileOrArray(factory.CreateSource(data.GetBytes(iText.IO.Util.EncodingUtil.ISO_8859_1 + )))); + for (int i = 0; i < expectedValues.Length; i++) { + tok.NextValidToken(); + //System.out.println(tok.getTokenType() + " -> " + tok.getStringValue()); + NUnit.Framework.Assert.AreEqual(expectedValues[i], tok.GetByteContent(), "Position " + i); + } + } + /// [NUnit.Framework.Test] public virtual void TestOneNumber() { @@ -42,6 +55,13 @@ public virtual void TokenTypesTest() { .EndDic, PdfTokenizer.TokenType.EndOfFile); } + /// + [NUnit.Framework.Test] + public virtual void NumberValueInTheEndTest() { + CheckTokenValues("123", new byte[] { 49, 50, 51 }, new byte[] { }); + } + + //EndOfFile buffer /// [NUnit.Framework.Test] public virtual void EncodingTest() { @@ -51,35 +71,38 @@ public virtual void EncodingTest() { // hex string parse and check String testHexString = "<0D0A09557365729073204775696465>"; factory = new RandomAccessSourceFactory(); - tok = new PdfTokenizer(new RandomAccessFileOrArray(factory.CreateSource(testHexString.GetBytes()))); + tok = new PdfTokenizer(new RandomAccessFileOrArray(factory.CreateSource(testHexString.GetBytes(iText.IO.Util.EncodingUtil.ISO_8859_1 + )))); tok.NextToken(); pdfString = new PdfString(tok.GetByteContent(), tok.IsHexString()); NUnit.Framework.Assert.AreEqual("\r\n\tUser\u0090s Guide", pdfString.GetValue()); String testUnicodeString = "ΑΒΓΗ€•♣⋅"; pdfString = new PdfString(PdfEncodings.ConvertToBytes(testUnicodeString, PdfEncodings.UNICODE_BIG), false); NUnit.Framework.Assert.AreEqual(testUnicodeString, pdfString.ToUnicodeString()); - pdfString = new PdfString("FEFF041F04400438043204350442".GetBytes(), true); + pdfString = new PdfString("FEFF041F04400438043204350442".GetBytes(iText.IO.Util.EncodingUtil.ISO_8859_1), + true); NUnit.Framework.Assert.AreEqual("\u041F\u0440\u0438\u0432\u0435\u0442", pdfString.ToUnicodeString()); - pdfString = new PdfString("FEFF041F04400438043204350442".GetBytes(), false); + pdfString = new PdfString("FEFF041F04400438043204350442".GetBytes(iText.IO.Util.EncodingUtil.ISO_8859_1), + false); NUnit.Framework.Assert.AreEqual("FEFF041F04400438043204350442", pdfString.ToUnicodeString()); String specialCharacter = "\r\n\t\\n\\r\\t\\f"; - pdfString = new PdfString(specialCharacter.GetBytes(), false); + pdfString = new PdfString(specialCharacter.GetBytes(iText.IO.Util.EncodingUtil.ISO_8859_1), false); NUnit.Framework.Assert.AreEqual("\n\t\n\r\t\f", pdfString.ToUnicodeString()); String symbol = "\u0001\u0004\u0006\u000E\u001F"; - pdfString = new PdfString(symbol.GetBytes(), false); + pdfString = new PdfString(symbol.GetBytes(iText.IO.Util.EncodingUtil.ISO_8859_1), false); NUnit.Framework.Assert.AreEqual(symbol, pdfString.ToUnicodeString()); String testString1 = "These\\\n two\\\r strings\\\n are the same"; - pdfString = new PdfString(testString1.GetBytes(), false); + pdfString = new PdfString(testString1.GetBytes(iText.IO.Util.EncodingUtil.ISO_8859_1), false); NUnit.Framework.Assert.AreEqual("These two strings are the same", pdfString.GetValue()); String testString2 = "This string contains \\245two octal characters\\307"; - pdfString = new PdfString(testString2.GetBytes(), false); + pdfString = new PdfString(testString2.GetBytes(iText.IO.Util.EncodingUtil.ISO_8859_1), false); NUnit.Framework.Assert.AreEqual("This string contains \u00A5two octal characters\u00C7", pdfString.GetValue ()); String testString3 = "\\0053"; - pdfString = new PdfString(testString3.GetBytes(), false); + pdfString = new PdfString(testString3.GetBytes(iText.IO.Util.EncodingUtil.ISO_8859_1), false); NUnit.Framework.Assert.AreEqual("\u00053", pdfString.GetValue()); String testString4 = "\\053"; - pdfString = new PdfString(testString4.GetBytes(), false); + pdfString = new PdfString(testString4.GetBytes(iText.IO.Util.EncodingUtil.ISO_8859_1), false); NUnit.Framework.Assert.AreEqual("+", pdfString.GetValue()); byte[] b = new byte[] { (byte)46, (byte)56, (byte)40 }; pdfString = new PdfString(b, false); @@ -112,7 +135,8 @@ public virtual void PrimitivesTest() { String data = "<(some simple string )<8C2547D58D4BD2C6F3D32B830BE3259D2>-70.1--0.2]" + "/Name1 --15" + "/Prev ---116.23 >>"; RandomAccessSourceFactory factory = new RandomAccessSourceFactory(); - PdfTokenizer tok = new PdfTokenizer(new RandomAccessFileOrArray(factory.CreateSource(data.GetBytes()))); + PdfTokenizer tok = new PdfTokenizer(new RandomAccessFileOrArray(factory.CreateSource(data.GetBytes(iText.IO.Util.EncodingUtil.ISO_8859_1 + )))); tok.NextValidToken(); NUnit.Framework.Assert.AreEqual(tok.GetTokenType(), PdfTokenizer.TokenType.StartDic); tok.NextValidToken(); @@ -202,9 +226,11 @@ public virtual void PrimitivesTest() { public virtual void TokenValueEqualsToTest() { String data = "SomeString"; RandomAccessSourceFactory factory = new RandomAccessSourceFactory(); - PdfTokenizer tok = new PdfTokenizer(new RandomAccessFileOrArray(factory.CreateSource(data.GetBytes()))); + PdfTokenizer tok = new PdfTokenizer(new RandomAccessFileOrArray(factory.CreateSource(data.GetBytes(iText.IO.Util.EncodingUtil.ISO_8859_1 + )))); tok.NextToken(); - NUnit.Framework.Assert.IsTrue(tok.TokenValueEqualsTo(data.GetBytes())); + NUnit.Framework.Assert.IsTrue(tok.TokenValueEqualsTo(data.GetBytes(iText.IO.Util.EncodingUtil.ISO_8859_1)) + ); } } } diff --git a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfWriterTest.cs b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfWriterTest.cs index 5e321fe116..6808f79a96 100644 --- a/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfWriterTest.cs +++ b/itext.tests/itext.kernel.tests/itext/kernel/pdf/PdfWriterTest.cs @@ -19,9 +19,7 @@ public static void BeforeClass() { /// [NUnit.Framework.Test] public virtual void CreateEmptyDocument() { - FileStream fos = new FileStream(destinationFolder + "emptyDocument.pdf", FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(destinationFolder + "emptyDocument.pdf")); pdfDoc.GetDocumentInfo().SetAuthor("Alexander Chingarev").SetCreator("iText 6").SetTitle("Empty iText 6 Document" ); PdfPage page = pdfDoc.AddNewPage(); @@ -36,15 +34,13 @@ public virtual void CreateEmptyDocument() { double diff = DateTimeUtil.GetUtcMillisFromEpoch(null) - DateTimeUtil.GetUtcMillisFromEpoch(cl); String message = "Unexpected creation date. Different from now is " + (float)diff / 1000 + "s"; NUnit.Framework.Assert.IsTrue(diff < 5000, message); - reader.Close(); + pdfDocument.Close(); } /// [NUnit.Framework.Test] public virtual void UseObjectForMultipleTimes1() { - FileStream fos = new FileStream(destinationFolder + "useObjectForMultipleTimes1.pdf", FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(destinationFolder + "useObjectForMultipleTimes1.pdf")); PdfDictionary helloWorld = ((PdfDictionary)new PdfDictionary().MakeIndirect(pdfDoc)); helloWorld.Put(new PdfName("Hello"), new PdfString("World")); PdfPage page = pdfDoc.AddNewPage(); @@ -58,9 +54,7 @@ public virtual void UseObjectForMultipleTimes1() { /// [NUnit.Framework.Test] public virtual void UseObjectForMultipleTimes2() { - FileStream fos = new FileStream(destinationFolder + "useObjectForMultipleTimes2.pdf", FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(destinationFolder + "useObjectForMultipleTimes2.pdf")); PdfDictionary helloWorld = ((PdfDictionary)new PdfDictionary().MakeIndirect(pdfDoc)); helloWorld.Put(new PdfName("Hello"), new PdfString("World")); helloWorld.Flush(); @@ -75,9 +69,7 @@ public virtual void UseObjectForMultipleTimes2() { /// [NUnit.Framework.Test] public virtual void UseObjectForMultipleTimes3() { - FileStream fos = new FileStream(destinationFolder + "useObjectForMultipleTimes3.pdf", FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(destinationFolder + "useObjectForMultipleTimes3.pdf")); PdfDictionary helloWorld = ((PdfDictionary)new PdfDictionary().MakeIndirect(pdfDoc)); helloWorld.Put(new PdfName("Hello"), new PdfString("World")); PdfPage page = pdfDoc.AddNewPage(); @@ -92,9 +84,7 @@ public virtual void UseObjectForMultipleTimes3() { /// [NUnit.Framework.Test] public virtual void UseObjectForMultipleTimes4() { - FileStream fos = new FileStream(destinationFolder + "useObjectForMultipleTimes4.pdf", FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(destinationFolder + "useObjectForMultipleTimes4.pdf")); PdfDictionary helloWorld = ((PdfDictionary)new PdfDictionary().MakeIndirect(pdfDoc)); helloWorld.Put(new PdfName("Hello"), new PdfString("World")); PdfPage page = pdfDoc.AddNewPage(); @@ -121,18 +111,15 @@ private void ValidateUseObjectForMultipleTimesTest(String filename) { NUnit.Framework.Assert.IsNotNull(helloWorld); world = helloWorld.GetAsString(new PdfName("Hello")); NUnit.Framework.Assert.AreEqual("World", world.ToString()); - reader.Close(); + pdfDoc.Close(); } /// Copying direct objects. /// Copying direct objects. Objects of all types are added into document catalog. /// - /// [NUnit.Framework.Test] public virtual void CopyObject1() { - FileStream fos1 = new FileStream(destinationFolder + "copyObject1_1.pdf", FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1); - PdfDocument pdfDoc1 = new PdfDocument(writer1); + PdfDocument pdfDoc1 = new PdfDocument(new PdfWriter(destinationFolder + "copyObject1_1.pdf")); PdfPage page1 = pdfDoc1.AddNewPage(); page1.Flush(); PdfDictionary catalog1 = pdfDoc1.GetCatalog().GetPdfObject(); @@ -151,9 +138,7 @@ public virtual void CopyObject1() { aDirect.Add(new PdfNumber(100)); aDirect.Add(new PdfString("string")); catalog1.Put(new PdfName("aDirect"), aDirect); - FileStream fos2 = new FileStream(destinationFolder + "copyObject1_2.pdf", FileMode.Create); - PdfWriter writer2 = new PdfWriter(fos2); - PdfDocument pdfDoc2 = new PdfDocument(writer2); + PdfDocument pdfDoc2 = new PdfDocument(new PdfWriter(destinationFolder + "copyObject1_2.pdf")); PdfPage page2 = pdfDoc2.AddNewPage(); page2.Flush(); PdfDictionary catalog2 = pdfDoc2.GetCatalog().GetPdfObject(); @@ -177,19 +162,16 @@ public virtual void CopyObject1() { NUnit.Framework.Assert.IsTrue(a.Get(4).IsNull()); NUnit.Framework.Assert.AreEqual(100, ((PdfNumber)a.Get(5)).IntValue()); NUnit.Framework.Assert.AreEqual("string", ((PdfString)a.Get(6)).ToUnicodeString()); - reader.Close(); + pdfDocument.Close(); } /// Copying objects, some of those are indirect. /// Copying objects, some of those are indirect. Objects of all types are added into document catalog. /// /// - /// [NUnit.Framework.Test] public virtual void CopyObject2() { - FileStream fos1 = new FileStream(destinationFolder + "copyObject2_1.pdf", FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1); - PdfDocument pdfDoc1 = new PdfDocument(writer1); + PdfDocument pdfDoc1 = new PdfDocument(new PdfWriter(destinationFolder + "copyObject2_1.pdf")); PdfPage page1 = pdfDoc1.AddNewPage(); page1.Flush(); PdfDictionary catalog1 = pdfDoc1.GetCatalog().GetPdfObject(); @@ -212,9 +194,7 @@ public virtual void CopyObject2() { pdfDoc1.Close(); PdfDocument pdfDoc1R = new PdfDocument(new PdfReader(destinationFolder + "copyObject2_1.pdf")); aDirect = (PdfArray)pdfDoc1R.GetCatalog().GetPdfObject().Get(aDirectName); - FileStream fos2 = new FileStream(destinationFolder + "copyObject2_2.pdf", FileMode.Create); - PdfWriter writer2 = new PdfWriter(fos2); - PdfDocument pdfDoc2 = new PdfDocument(writer2); + PdfDocument pdfDoc2 = new PdfDocument(new PdfWriter(destinationFolder + "copyObject2_2.pdf")); PdfPage page2 = pdfDoc2.AddNewPage(); page2.Flush(); PdfDictionary catalog2 = pdfDoc2.GetCatalog().GetPdfObject(); @@ -237,18 +217,15 @@ public virtual void CopyObject2() { NUnit.Framework.Assert.IsTrue(a.Get(4).IsNull()); NUnit.Framework.Assert.AreEqual(100, ((PdfNumber)a.Get(5)).IntValue()); NUnit.Framework.Assert.AreEqual("string", ((PdfString)a.Get(6)).ToUnicodeString()); - reader.Close(); + pdfDocument.Close(); } /// Copy objects recursively. /// - /// [NUnit.Framework.Test] public virtual void CopyObject3() { { - FileStream fos1 = new FileStream(destinationFolder + "copyObject3_1.pdf", FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1); - PdfDocument pdfDoc1 = new PdfDocument(writer1); + PdfDocument pdfDoc1 = new PdfDocument(new PdfWriter(destinationFolder + "copyObject3_1.pdf")); PdfPage page1 = pdfDoc1.AddNewPage(); page1.Flush(); PdfDictionary catalog1 = pdfDoc1.GetCatalog().GetPdfObject(); @@ -265,9 +242,7 @@ public virtual void CopyObject3() { pdfDoc1.Close(); PdfDocument pdfDoc1R = new PdfDocument(new PdfReader(destinationFolder + "copyObject3_1.pdf")); arr1 = (PdfArray)pdfDoc1R.GetCatalog().GetPdfObject().Get(arr1Name); - FileStream fos2 = new FileStream(destinationFolder + "copyObject3_2.pdf", FileMode.Create); - PdfWriter writer2 = new PdfWriter(fos2); - PdfDocument pdfDoc2 = new PdfDocument(writer2); + PdfDocument pdfDoc2 = new PdfDocument(new PdfWriter(destinationFolder + "copyObject3_2.pdf")); PdfPage page2 = pdfDoc2.AddNewPage(); page2.Flush(); PdfDictionary catalog2 = pdfDoc2.GetCatalog().GetPdfObject(); @@ -285,18 +260,15 @@ public virtual void CopyObject3() { PdfDictionary dic1 = arr2.GetAsDictionary(0); PdfDictionary dic2 = dic1.GetAsDictionary(new PdfName("dic2")); NUnit.Framework.Assert.AreEqual(arr1, dic2.GetAsArray(new PdfName("arr1"))); - reader.Close(); + pdfDocument.Close(); } } /// Copies stream. /// - /// [NUnit.Framework.Test] public virtual void CopyObject4() { - FileStream fos1 = new FileStream(destinationFolder + "copyObject4_1.pdf", FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1); - PdfDocument pdfDoc1 = new PdfDocument(writer1); + PdfDocument pdfDoc1 = new PdfDocument(new PdfWriter(destinationFolder + "copyObject4_1.pdf")); PdfPage page1 = pdfDoc1.AddNewPage(); page1.Flush(); PdfDictionary catalog1 = pdfDoc1.GetCatalog().GetPdfObject(); @@ -310,9 +282,7 @@ public virtual void CopyObject4() { pdfDoc1.Close(); PdfDocument pdfDoc1R = new PdfDocument(new PdfReader(destinationFolder + "copyObject4_1.pdf")); stream1 = (PdfStream)pdfDoc1R.GetCatalog().GetPdfObject().Get(new PdfName("stream")); - FileStream fos2 = new FileStream(destinationFolder + "copyObject4_2.pdf", FileMode.Create); - PdfWriter writer2 = new PdfWriter(fos2); - PdfDocument pdfDoc2 = new PdfDocument(writer2); + PdfDocument pdfDoc2 = new PdfDocument(new PdfWriter(destinationFolder + "copyObject4_2.pdf")); PdfPage page2 = pdfDoc2.AddNewPage(); page2.Flush(); PdfDictionary catalog2 = pdfDoc2.GetCatalog().GetPdfObject(); @@ -326,26 +296,21 @@ public virtual void CopyObject4() { PdfStream stream = (PdfStream)catalog.GetAsStream(new PdfName("stream")); byte[] bytes = stream.GetBytes(); NUnit.Framework.Assert.AreEqual(ByteUtils.GetIsoBytes("[1 2 3]"), bytes); - reader.Close(); + pdfDocument.Close(); } /// Copies page. /// - /// [NUnit.Framework.Test] public virtual void CopyObject5() { - FileStream fos1 = new FileStream(destinationFolder + "copyObject5_1.pdf", FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1); - PdfDocument pdfDoc1 = new PdfDocument(writer1); + PdfDocument pdfDoc1 = new PdfDocument(new PdfWriter(destinationFolder + "copyObject5_1.pdf")); PdfPage page1 = pdfDoc1.AddNewPage(); page1.GetContentStream(0).GetOutputStream().Write(ByteUtils.GetIsoBytes("%Page_1")); page1.Flush(); pdfDoc1.Close(); PdfDocument pdfDoc1R = new PdfDocument(new PdfReader(destinationFolder + "copyObject5_1.pdf")); page1 = pdfDoc1R.GetPage(1); - FileStream fos2 = new FileStream(destinationFolder + "copyObject5_2.pdf", FileMode.Create); - PdfWriter writer2 = new PdfWriter(fos2); - PdfDocument pdfDoc2 = new PdfDocument(writer2); + PdfDocument pdfDoc2 = new PdfDocument(new PdfWriter(destinationFolder + "copyObject5_2.pdf")); PdfPage page2 = page1.CopyTo(pdfDoc2); pdfDoc2.AddPage(page2); page2.Flush(); @@ -359,19 +324,19 @@ public virtual void CopyObject5() { NUnit.Framework.Assert.AreEqual(false, reader.HasRebuiltXref(), "Rebuilt"); NUnit.Framework.Assert.AreEqual(8, reader.trailer.GetAsNumber(PdfName.Size).IntValue()); byte[] bytes = pdfDocument.GetPage(1).GetContentBytes(); - NUnit.Framework.Assert.AreEqual(ByteUtils.GetIsoBytes("%Page_1"), bytes); + // getting content bytes results in adding '\n' for each content stream + // so we should compare String with '\n' at the end + NUnit.Framework.Assert.AreEqual(ByteUtils.GetIsoBytes("%Page_1\n"), bytes); bytes = pdfDocument.GetPage(2).GetContentBytes(); - NUnit.Framework.Assert.AreEqual(ByteUtils.GetIsoBytes("%Page_2"), bytes); - reader.Close(); + NUnit.Framework.Assert.AreEqual(ByteUtils.GetIsoBytes("%Page_2\n"), bytes); + pdfDocument.Close(); } /// Copies object with different method overloads. /// [NUnit.Framework.Test] public virtual void CopyObject6() { - FileStream fos = new FileStream(destinationFolder + "copyObject6_1.pdf", FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(destinationFolder + "copyObject6_1.pdf")); PdfDictionary helloWorld = ((PdfDictionary)new PdfDictionary().MakeIndirect(pdfDoc)); helloWorld.Put(new PdfName("Hello"), new PdfString("World")); PdfPage page = pdfDoc.AddNewPage(); @@ -379,8 +344,7 @@ public virtual void CopyObject6() { pdfDoc.Close(); pdfDoc = new PdfDocument(new PdfReader(destinationFolder + "copyObject6_1.pdf")); helloWorld = (PdfDictionary)pdfDoc.GetPage(1).GetPdfObject().Get(new PdfName("HelloWorld")); - PdfDocument pdfDoc1 = new PdfDocument(new PdfWriter(new FileStream(destinationFolder + "copyObject6_2.pdf" - , FileMode.Create))); + PdfDocument pdfDoc1 = new PdfDocument(new PdfWriter(destinationFolder + "copyObject6_2.pdf")); PdfPage page1 = pdfDoc1.AddNewPage(); page1.GetPdfObject().Put(new PdfName("HelloWorldCopy1"), ((PdfDictionary)helloWorld.CopyTo(pdfDoc1))); page1.GetPdfObject().Put(new PdfName("HelloWorldCopy2"), ((PdfDictionary)helloWorld.CopyTo(pdfDoc1, true)) @@ -405,7 +369,7 @@ public virtual void CopyObject6() { PdfIndirectReference ref3 = obj3.GetIndirectReference(); NUnit.Framework.Assert.AreEqual(7, ref3.GetObjNumber()); NUnit.Framework.Assert.AreEqual(0, ref3.GetGenNumber()); - reader.Close(); + pdfDocument.Close(); } /// Attempts to copy from the document that is being written. @@ -413,14 +377,8 @@ public virtual void CopyObject6() { [NUnit.Framework.Test] public virtual void CopyObject7() { String exceptionMessage = null; - PdfDocument pdfDoc1; - PdfDocument pdfDoc2; - FileStream fos1 = new FileStream(destinationFolder + "copyObject6_1.pdf", FileMode.Create); - FileStream fos2 = new FileStream(destinationFolder + "copyObject6_2.pdf", FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1); - PdfWriter writer2 = new PdfWriter(fos2); - pdfDoc1 = new PdfDocument(writer1); - pdfDoc2 = new PdfDocument(writer2); + PdfDocument pdfDoc1 = new PdfDocument(new PdfWriter(destinationFolder + "copyObject6_1.pdf")); + PdfDocument pdfDoc2 = new PdfDocument(new PdfWriter(destinationFolder + "copyObject6_2.pdf")); try { PdfPage page1 = pdfDoc1.AddNewPage(); PdfDictionary directDict = new PdfDictionary(); @@ -447,14 +405,11 @@ public virtual void CopyObject7() { [NUnit.Framework.Test] public virtual void CopyObject8() { String exceptionMessage = null; - PdfDocument pdfDoc1; - FileStream fos1 = new FileStream(destinationFolder + "copyObject6_1.pdf", FileMode.Create); - PdfWriter writer1 = new PdfWriter(fos1); - pdfDoc1 = new PdfDocument(writer1); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(destinationFolder + "copyObject6_1.pdf")); try { - PdfPage page1 = pdfDoc1.AddNewPage(); + PdfPage page1 = pdfDoc.AddNewPage(); PdfDictionary directDict = new PdfDictionary(); - PdfObject indirectDict = ((PdfDictionary)new PdfDictionary().MakeIndirect(pdfDoc1)); + PdfObject indirectDict = ((PdfDictionary)new PdfDictionary().MakeIndirect(pdfDoc)); page1.GetPdfObject().Put(new PdfName("HelloWorldDirect"), directDict); page1.GetPdfObject().Put(new PdfName("HelloWorldIndirect"), indirectDict); indirectDict.CopyTo(null); @@ -463,9 +418,9 @@ public virtual void CopyObject8() { exceptionMessage = ex.Message; } finally { - pdfDoc1.Close(); + pdfDoc.Close(); } - NUnit.Framework.Assert.AreEqual(exceptionMessage, PdfException.DocumentToCopyToCannotBeNull); + NUnit.Framework.Assert.AreEqual(exceptionMessage, PdfException.DocumentForCopyToCannotBeNull); } /// @@ -500,8 +455,7 @@ public virtual void CloseStream2() { [NUnit.Framework.Test] public virtual void DirectInIndirectChain() { String filename = destinationFolder + "directInIndirectChain.pdf"; - PdfWriter writer = new PdfWriter(new FileStream(filename, FileMode.Create)); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(filename)); PdfArray level1 = new PdfArray(); level1.Add(((PdfNumber)new PdfNumber(1).MakeIndirect(pdfDoc))); PdfDictionary level2 = new PdfDictionary(); @@ -523,16 +477,14 @@ public virtual void DirectInIndirectChain() { NUnit.Framework.Assert.AreEqual(1, pdfDocument.GetNumberOfPages(), "Page count"); PdfDictionary page = pdfDocument.GetPage(1).GetPdfObject(); NUnit.Framework.Assert.AreEqual(PdfName.Page, page.Get(PdfName.Type)); - reader.Close(); + pdfDocument.Close(); } /// [NUnit.Framework.Test] public virtual void CreatePdfStreamByInputStream() { String filename = destinationFolder + "createPdfStreamByInputStream.pdf"; - FileStream fos = new FileStream(filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument document = new PdfDocument(writer); + PdfDocument document = new PdfDocument(new PdfWriter(filename)); document.GetDocumentInfo().SetAuthor("Alexander Chingarev").SetCreator("iText 6").SetTitle("Empty iText 6 Document" ); PdfPage page = document.AddNewPage(); diff --git a/itext.tests/itext.kernel.tests/itext/kernel/pdf/XMPMetadataTest.cs b/itext.tests/itext.kernel.tests/itext/kernel/pdf/XMPMetadataTest.cs index 471c8bebe2..bb1b47ed15 100644 --- a/itext.tests/itext.kernel.tests/itext/kernel/pdf/XMPMetadataTest.cs +++ b/itext.tests/itext.kernel.tests/itext/kernel/pdf/XMPMetadataTest.cs @@ -18,8 +18,7 @@ public static void BeforeClass() { [NUnit.Framework.Test] public virtual void CreateEmptyDocumentWithXmp() { String filename = "emptyDocumentWithXmp.pdf"; - FileStream fos = new FileStream(destinationFolder + filename, FileMode.Create); - PdfWriter writer = new PdfWriter(fos, new WriterProperties().AddXmpMetadata()); + PdfWriter writer = new PdfWriter(destinationFolder + filename, new WriterProperties().AddXmpMetadata()); PdfDocument pdfDoc = new PdfDocument(writer); pdfDoc.GetDocumentInfo().SetAuthor("Alexander Chingarev").SetCreator("iText 7").SetTitle("Empty iText 7 Document" ); @@ -51,12 +50,13 @@ public virtual void CreateEmptyDocumentWithAbcXmp() { pdfDoc.GetDocumentInfo().GetPdfObject().Remove(PdfName.ModDate); PdfPage page = pdfDoc.AddNewPage(); page.Flush(); - pdfDoc.SetXmpMetadata("abc".GetBytes()); + pdfDoc.SetXmpMetadata("abc".GetBytes(iText.IO.Util.EncodingUtil.ISO_8859_1)); pdfDoc.Close(); PdfReader reader = new PdfReader(new MemoryStream(fos.ToArray())); PdfDocument pdfDocument = new PdfDocument(reader); NUnit.Framework.Assert.AreEqual(false, reader.HasRebuiltXref(), "Rebuilt"); - NUnit.Framework.Assert.AreEqual("abc".GetBytes(), pdfDocument.GetXmpMetadata()); + NUnit.Framework.Assert.AreEqual("abc".GetBytes(iText.IO.Util.EncodingUtil.ISO_8859_1), pdfDocument.GetXmpMetadata + ()); NUnit.Framework.Assert.IsNotNull(pdfDocument.GetPage(1)); reader.Close(); } diff --git a/itext.tests/itext.kernel.tests/itext/kernel/pdf/canvas/parser/FilteredEventListenerTest.cs b/itext.tests/itext.kernel.tests/itext/kernel/pdf/canvas/parser/FilteredEventListenerTest.cs index 6d5cc1191c..e2ed9efb75 100644 --- a/itext.tests/itext.kernel.tests/itext/kernel/pdf/canvas/parser/FilteredEventListenerTest.cs +++ b/itext.tests/itext.kernel.tests/itext/kernel/pdf/canvas/parser/FilteredEventListenerTest.cs @@ -1,5 +1,4 @@ using System; -using System.IO; using iText.Kernel.Geom; using iText.Kernel.Pdf; using iText.Kernel.Pdf.Canvas.Parser.Filter; @@ -13,8 +12,7 @@ public class FilteredEventListenerTest : ExtendedITextTest { /// [NUnit.Framework.Test] public virtual void Test() { - PdfDocument pdfDocument = new PdfDocument(new PdfReader(new FileStream(sourceFolder + "test.pdf", FileMode.Open - , FileAccess.Read))); + PdfDocument pdfDocument = new PdfDocument(new PdfReader(sourceFolder + "test.pdf")); String[] expectedText = new String[] { "PostScript Compatibility", "Because the PostScript language does not support the transparent imaging \n" + "model, PDF 1.4 consumer applications must have some means for converting the \n" + "appearance of a document that uses transparency to a purely opaque description \n" + "for printing on PostScript output devices. Similar techniques can also be used to \n" + "convert such documents to a form that can be correctly viewed by PDF 1.3 and \n" @@ -44,8 +42,7 @@ public virtual void Test() { /// [NUnit.Framework.Test] public virtual void MultipleFiltersForOneRegionTest() { - PdfDocument pdfDocument = new PdfDocument(new PdfReader(new FileStream(sourceFolder + "test.pdf", FileMode.Open - , FileAccess.Read))); + PdfDocument pdfDocument = new PdfDocument(new PdfReader(sourceFolder + "test.pdf")); Rectangle[] regions = new Rectangle[] { new Rectangle(0, 0, 500, 650), new Rectangle(0, 0, 400, 400), new Rectangle(200, 200, 300, 400), new Rectangle(100, 100, 350, 300) }; TextRegionEventFilter[] regionFilters = new TextRegionEventFilter[regions.Length]; diff --git a/itext.tests/itext.kernel.tests/itext/kernel/utils/PdfMergerTest.cs b/itext.tests/itext.kernel.tests/itext/kernel/utils/PdfMergerTest.cs index f54d587370..b86c63f271 100644 --- a/itext.tests/itext.kernel.tests/itext/kernel/utils/PdfMergerTest.cs +++ b/itext.tests/itext.kernel.tests/itext/kernel/utils/PdfMergerTest.cs @@ -26,9 +26,9 @@ public virtual void MergeDocumentTest01() { String filename1 = sourceFolder + "helveticaTest.pdf"; String filename2 = sourceFolder + "timesRomanTest.pdf"; String resultFile = destinationFolder + "mergedResult01.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); - PdfReader reader1 = new PdfReader(new FileStream(filename1, FileMode.Open, FileAccess.Read)); - PdfReader reader2 = new PdfReader(new FileStream(filename2, FileMode.Open, FileAccess.Read)); + PdfReader reader = new PdfReader(filename); + PdfReader reader1 = new PdfReader(filename1); + PdfReader reader2 = new PdfReader(filename2); FileStream fos1 = new FileStream(resultFile, FileMode.Create); PdfWriter writer1 = new PdfWriter(fos1); PdfDocument pdfDoc = new PdfDocument(reader); @@ -56,9 +56,9 @@ public virtual void MergeDocumentTest02() { String filename1 = sourceFolder + "doc2.pdf"; String filename2 = sourceFolder + "doc3.pdf"; String resultFile = destinationFolder + "mergedResult02.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); - PdfReader reader1 = new PdfReader(new FileStream(filename1, FileMode.Open, FileAccess.Read)); - PdfReader reader2 = new PdfReader(new FileStream(filename2, FileMode.Open, FileAccess.Read)); + PdfReader reader = new PdfReader(filename); + PdfReader reader1 = new PdfReader(filename1); + PdfReader reader2 = new PdfReader(filename2); FileStream fos1 = new FileStream(resultFile, FileMode.Create); PdfWriter writer1 = new PdfWriter(fos1); PdfDocument pdfDoc = new PdfDocument(reader); @@ -85,8 +85,8 @@ public virtual void MergeDocumentTest03() { String filename = sourceFolder + "pdf_open_parameters.pdf"; String filename1 = sourceFolder + "iphone_user_guide.pdf"; String resultFile = destinationFolder + "mergedResult03.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); - PdfReader reader1 = new PdfReader(new FileStream(filename1, FileMode.Open, FileAccess.Read)); + PdfReader reader = new PdfReader(filename); + PdfReader reader1 = new PdfReader(filename1); FileStream fos1 = new FileStream(resultFile, FileMode.Create); PdfWriter writer1 = new PdfWriter(fos1); PdfDocument pdfDoc = new PdfDocument(reader); @@ -119,8 +119,8 @@ public virtual void MergeDocumentTest04() { String filename = sourceFolder + "pdf_open_parameters.pdf"; String filename1 = sourceFolder + "iphone_user_guide.pdf"; String resultFile = destinationFolder + "mergedResult04.pdf"; - PdfReader reader = new PdfReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); - PdfReader reader1 = new PdfReader(new FileStream(filename1, FileMode.Open, FileAccess.Read)); + PdfReader reader = new PdfReader(filename); + PdfReader reader1 = new PdfReader(filename1); FileStream fos1 = new FileStream(resultFile, FileMode.Create); PdfWriter writer1 = new PdfWriter(fos1); PdfDocument pdfDoc = new PdfDocument(reader); diff --git a/itext.tests/itext.kernel.tests/itext/kernel/utils/PdfSplitterTest.cs b/itext.tests/itext.kernel.tests/itext/kernel/utils/PdfSplitterTest.cs index 2b33102049..10eb125739 100644 --- a/itext.tests/itext.kernel.tests/itext/kernel/utils/PdfSplitterTest.cs +++ b/itext.tests/itext.kernel.tests/itext/kernel/utils/PdfSplitterTest.cs @@ -47,8 +47,8 @@ public _PdfSplitter_44(PdfDocument baseArg1) protected internal override PdfWriter GetNextPdfWriter(PageRange documentPageRange) { try { - return new PdfWriter(new FileStream(PdfSplitterTest.destinationFolder + "splitDocument1_" + (this.partNumber - ++).ToString() + ".pdf", FileMode.Create)); + return new PdfWriter(PdfSplitterTest.destinationFolder + "splitDocument1_" + (this.partNumber++).ToString( + ) + ".pdf"); } catch (FileNotFoundException) { throw new Exception(); @@ -81,8 +81,8 @@ public _PdfSplitter_74(PdfDocument baseArg1) protected internal override PdfWriter GetNextPdfWriter(PageRange documentPageRange) { try { - return new PdfWriter(new FileStream(PdfSplitterTest.destinationFolder + "splitDocument2_" + (this.partNumber - ++).ToString() + ".pdf", FileMode.Create)); + return new PdfWriter(PdfSplitterTest.destinationFolder + "splitDocument2_" + (this.partNumber++).ToString( + ) + ".pdf"); } catch (FileNotFoundException) { throw new Exception(); @@ -133,8 +133,8 @@ public _PdfSplitter_113(PdfDocument baseArg1) protected internal override PdfWriter GetNextPdfWriter(PageRange documentPageRange) { try { - return new PdfWriter(new FileStream(PdfSplitterTest.destinationFolder + "splitDocument3_" + (this.partNumber - ++).ToString() + ".pdf", FileMode.Create)); + return new PdfWriter(PdfSplitterTest.destinationFolder + "splitDocument3_" + (this.partNumber++).ToString( + ) + ".pdf"); } catch (FileNotFoundException) { throw new Exception(); @@ -187,8 +187,8 @@ public _PdfSplitter_159(PdfDocument baseArg1) protected internal override PdfWriter GetNextPdfWriter(PageRange documentPageRange) { try { - return new PdfWriter(new FileStream(PdfSplitterTest.destinationFolder + "splitBySize_part" + (this.partNumber - ++).ToString() + ".pdf", FileMode.Create)); + return new PdfWriter(PdfSplitterTest.destinationFolder + "splitBySize_part" + (this.partNumber++).ToString + () + ".pdf"); } catch (FileNotFoundException) { throw new Exception(); diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfAnnotationTest/cmp_screenAnnotation01.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfAnnotationTest/cmp_screenAnnotation01.pdf index 0ae3af7762..6cae7529c9 100644 Binary files a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfAnnotationTest/cmp_screenAnnotation01.pdf and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfAnnotationTest/cmp_screenAnnotation01.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfAnnotationTest/cmp_screenAnnotation02.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfAnnotationTest/cmp_screenAnnotation02.pdf index e35a726594..1f58c20701 100644 Binary files a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfAnnotationTest/cmp_screenAnnotation02.pdf and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfAnnotationTest/cmp_screenAnnotation02.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfCopyTest/cmp_copySamePageWithAnnotationsSeveralTimes.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfCopyTest/cmp_copySamePageWithAnnotationsSeveralTimes.pdf new file mode 100644 index 0000000000..42693d69ad Binary files /dev/null and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfCopyTest/cmp_copySamePageWithAnnotationsSeveralTimes.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfCopyTest/rotated_annotation.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfCopyTest/rotated_annotation.pdf new file mode 100644 index 0000000000..da1ccdfb69 Binary files /dev/null and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfCopyTest/rotated_annotation.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfDocumentTest/cmp_outlinesWithNamedDestinations01.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfDocumentTest/cmp_outlinesWithNamedDestinations01.pdf index ffdee7b6f9..c4c3bbd969 100644 Binary files a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfDocumentTest/cmp_outlinesWithNamedDestinations01.pdf and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfDocumentTest/cmp_outlinesWithNamedDestinations01.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithCertificateAes128.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithCertificateAes128.pdf new file mode 100644 index 0000000000..ea99e50386 Binary files /dev/null and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithCertificateAes128.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithCertificateAes128NoCompression.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithCertificateAes128NoCompression.pdf new file mode 100644 index 0000000000..548cee71da Binary files /dev/null and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithCertificateAes128NoCompression.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithCertificateAes256.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithCertificateAes256.pdf new file mode 100644 index 0000000000..03cf21523f Binary files /dev/null and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithCertificateAes256.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithCertificateAes256NoCompression.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithCertificateAes256NoCompression.pdf new file mode 100644 index 0000000000..2ff35169a6 Binary files /dev/null and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithCertificateAes256NoCompression.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithCertificateStandard128.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithCertificateStandard128.pdf new file mode 100644 index 0000000000..81602637be Binary files /dev/null and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithCertificateStandard128.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithCertificateStandard128NoCompression.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithCertificateStandard128NoCompression.pdf new file mode 100644 index 0000000000..b82b32f403 Binary files /dev/null and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithCertificateStandard128NoCompression.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithCertificateStandard40.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithCertificateStandard40.pdf new file mode 100644 index 0000000000..97ba9620d4 Binary files /dev/null and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithCertificateStandard40.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithCertificateStandard40NoCompression.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithCertificateStandard40NoCompression.pdf new file mode 100644 index 0000000000..ca03c49a4a Binary files /dev/null and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithCertificateStandard40NoCompression.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithPasswordAes128.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithPasswordAes128.pdf index a201766850..b90b743aaa 100644 Binary files a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithPasswordAes128.pdf and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithPasswordAes128.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithPasswordAes128NoCompression.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithPasswordAes128NoCompression.pdf index 0fcf94ac2e..f90938dd9e 100644 Binary files a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithPasswordAes128NoCompression.pdf and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithPasswordAes128NoCompression.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithPasswordAes256.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithPasswordAes256.pdf index cfeb12b2b1..309f3ef73b 100644 Binary files a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithPasswordAes256.pdf and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithPasswordAes256.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithPasswordAes256NoCompression.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithPasswordAes256NoCompression.pdf index f25dcfc5f6..9c792509b3 100644 Binary files a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithPasswordAes256NoCompression.pdf and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithPasswordAes256NoCompression.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithPasswordStandard128.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithPasswordStandard128.pdf index 6efdf81a32..3185a68de8 100644 Binary files a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithPasswordStandard128.pdf and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithPasswordStandard128.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithPasswordStandard128NoCompression.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithPasswordStandard128NoCompression.pdf index 9cbf513b2b..bc0854b94e 100644 Binary files a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithPasswordStandard128NoCompression.pdf and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithPasswordStandard128NoCompression.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithPasswordStandard40.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithPasswordStandard40.pdf index 26a45ad982..a50a7943c9 100644 Binary files a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithPasswordStandard40.pdf and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithPasswordStandard40.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithPasswordStandard40NoCompression.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithPasswordStandard40NoCompression.pdf index 7b674c65af..b116a40de7 100644 Binary files a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithPasswordStandard40NoCompression.pdf and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_appended_encryptWithPasswordStandard40NoCompression.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithCertificateAes128.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithCertificateAes128.pdf new file mode 100644 index 0000000000..762ada8275 Binary files /dev/null and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithCertificateAes128.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithCertificateAes128NoCompression.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithCertificateAes128NoCompression.pdf new file mode 100644 index 0000000000..0d6b720e0b Binary files /dev/null and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithCertificateAes128NoCompression.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithCertificateAes256.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithCertificateAes256.pdf new file mode 100644 index 0000000000..c6f012668e Binary files /dev/null and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithCertificateAes256.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithCertificateAes256NoCompression.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithCertificateAes256NoCompression.pdf new file mode 100644 index 0000000000..5a3e1a3840 Binary files /dev/null and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithCertificateAes256NoCompression.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithCertificateStandard128.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithCertificateStandard128.pdf new file mode 100644 index 0000000000..c08ade440a Binary files /dev/null and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithCertificateStandard128.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithCertificateStandard128NoCompression.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithCertificateStandard128NoCompression.pdf new file mode 100644 index 0000000000..3958f8430f Binary files /dev/null and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithCertificateStandard128NoCompression.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithCertificateStandard40.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithCertificateStandard40.pdf new file mode 100644 index 0000000000..b3868aaaa2 Binary files /dev/null and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithCertificateStandard40.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithCertificateStandard40NoCompression.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithCertificateStandard40NoCompression.pdf new file mode 100644 index 0000000000..83ddc62702 Binary files /dev/null and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithCertificateStandard40NoCompression.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithPasswordAes128.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithPasswordAes128.pdf index 85a046b3cd..7d641fa2a2 100644 Binary files a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithPasswordAes128.pdf and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithPasswordAes128.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithPasswordAes128NoCompression.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithPasswordAes128NoCompression.pdf index 97937b25d8..8efb45d2be 100644 Binary files a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithPasswordAes128NoCompression.pdf and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithPasswordAes128NoCompression.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithPasswordAes256.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithPasswordAes256.pdf index 2b7b08e005..ee2186e174 100644 Binary files a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithPasswordAes256.pdf and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithPasswordAes256.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithPasswordAes256NoCompression.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithPasswordAes256NoCompression.pdf index d41505d35b..c3e840d116 100644 Binary files a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithPasswordAes256NoCompression.pdf and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithPasswordAes256NoCompression.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithPasswordStandard128.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithPasswordStandard128.pdf index e6314c7e39..b235bde1e4 100644 Binary files a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithPasswordStandard128.pdf and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithPasswordStandard128.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithPasswordStandard128NoCompression.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithPasswordStandard128NoCompression.pdf index 0b0b880c2f..2ce77aba67 100644 Binary files a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithPasswordStandard128NoCompression.pdf and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithPasswordStandard128NoCompression.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithPasswordStandard40.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithPasswordStandard40.pdf index 9c218a62b3..2681f579ea 100644 Binary files a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithPasswordStandard40.pdf and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithPasswordStandard40.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithPasswordStandard40NoCompression.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithPasswordStandard40NoCompression.pdf index 0f3dea4e54..551103a27f 100644 Binary files a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithPasswordStandard40NoCompression.pdf and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/cmp_encryptWithPasswordStandard40NoCompression.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/encryptedWithCertificateAes128.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/encryptedWithCertificateAes128.pdf new file mode 100644 index 0000000000..dac5b72b7e Binary files /dev/null and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/encryptedWithCertificateAes128.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/encryptedWithPasswordStandard40.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/encryptedWithPasswordStandard40.pdf new file mode 100644 index 0000000000..2681f579ea Binary files /dev/null and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/encryptedWithPasswordStandard40.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/test.cer b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/test.cer new file mode 100644 index 0000000000..fbaad2b382 Binary files /dev/null and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/test.cer differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/test.p12 b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/test.p12 new file mode 100644 index 0000000000..dc8d373503 Binary files /dev/null and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/test.p12 differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/wrong.cer b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/wrong.cer new file mode 100644 index 0000000000..b342dbc046 Binary files /dev/null and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/wrong.cer differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/wrong.p12 b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/wrong.p12 new file mode 100644 index 0000000000..62c98fa0d6 Binary files /dev/null and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfEncryptionTest/wrong.p12 differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfOutlineTest/cmp_outlinesWithNamedDestinations01.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfOutlineTest/cmp_outlinesWithNamedDestinations01.pdf index 3f04051664..2dcdc52de6 100644 Binary files a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfOutlineTest/cmp_outlinesWithNamedDestinations01.pdf and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfOutlineTest/cmp_outlinesWithNamedDestinations01.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfOutlineTest/cmp_outlinesWithNamedDestinations02.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfOutlineTest/cmp_outlinesWithNamedDestinations02.pdf index 4fa722ff69..116c45cef4 100644 Binary files a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfOutlineTest/cmp_outlinesWithNamedDestinations02.pdf and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfOutlineTest/cmp_outlinesWithNamedDestinations02.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfPagesTest/cmp_1000PagesDocument_reversed.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfPagesTest/cmp_1000PagesDocument_reversed.pdf new file mode 100644 index 0000000000..5ec1aefa61 Binary files /dev/null and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfPagesTest/cmp_1000PagesDocument_reversed.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfPagesTest/cmp_updateInheritedResources.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfPagesTest/cmp_updateInheritedResources.pdf new file mode 100644 index 0000000000..80040e8dff Binary files /dev/null and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfPagesTest/cmp_updateInheritedResources.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfPagesTest/inheritedMediaBox.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfPagesTest/inheritedMediaBox.pdf new file mode 100644 index 0000000000..ebc8277f4f Binary files /dev/null and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfPagesTest/inheritedMediaBox.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfPagesTest/simpleInheritedResources.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfPagesTest/simpleInheritedResources.pdf new file mode 100644 index 0000000000..f764090aee Binary files /dev/null and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfPagesTest/simpleInheritedResources.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfStructElemTest/cmp_structTreeCopyingTest01.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfStructElemTest/cmp_structTreeCopyingTest01.pdf index a6c6107b80..589d0e1ab9 100644 Binary files a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfStructElemTest/cmp_structTreeCopyingTest01.pdf and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfStructElemTest/cmp_structTreeCopyingTest01.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfStructElemTest/cmp_structTreeCopyingTest02.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfStructElemTest/cmp_structTreeCopyingTest02.pdf index 3fa9a30947..78ed29d9be 100644 Binary files a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfStructElemTest/cmp_structTreeCopyingTest02.pdf and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfStructElemTest/cmp_structTreeCopyingTest02.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfStructElemTest/cmp_structTreeCopyingTest03.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfStructElemTest/cmp_structTreeCopyingTest03.pdf index f4bae2bd00..418ca02886 100644 Binary files a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfStructElemTest/cmp_structTreeCopyingTest03.pdf and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfStructElemTest/cmp_structTreeCopyingTest03.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfStructElemTest/cmp_structTreeCopyingTest04.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfStructElemTest/cmp_structTreeCopyingTest04.pdf index e2c49b1a49..ea5a87e4a5 100644 Binary files a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfStructElemTest/cmp_structTreeCopyingTest04.pdf and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfStructElemTest/cmp_structTreeCopyingTest04.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfStructElemTest/cmp_structTreeCopyingTest06.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfStructElemTest/cmp_structTreeCopyingTest06.pdf index 31eb6b0235..dfa4b71515 100644 Binary files a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfStructElemTest/cmp_structTreeCopyingTest06.pdf and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfStructElemTest/cmp_structTreeCopyingTest06.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfStructElemTest/cocacola_corruptedTagStruct.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfStructElemTest/cocacola_corruptedTagStruct.pdf new file mode 100644 index 0000000000..65f86c1e90 Binary files /dev/null and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfStructElemTest/cocacola_corruptedTagStruct.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfStructElemTest/directStructElem01.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfStructElemTest/directStructElem01.pdf new file mode 100644 index 0000000000..17ad45aa13 Binary files /dev/null and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfStructElemTest/directStructElem01.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfStructElemTest/directStructElem02.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfStructElemTest/directStructElem02.pdf new file mode 100644 index 0000000000..db6aca6f3e Binary files /dev/null and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfStructElemTest/directStructElem02.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfStructElemTest/directStructElem03.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfStructElemTest/directStructElem03.pdf new file mode 100644 index 0000000000..c52700d1b3 Binary files /dev/null and b/itext.tests/itext.kernel.tests/resources/itext/kernel/pdf/PdfStructElemTest/directStructElem03.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfMergerTest/cmp_mergedResult03.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfMergerTest/cmp_mergedResult03.pdf index 104758882a..d9c2bab06c 100644 Binary files a/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfMergerTest/cmp_mergedResult03.pdf and b/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfMergerTest/cmp_mergedResult03.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfMergerTest/cmp_mergedResult04.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfMergerTest/cmp_mergedResult04.pdf index bd70cd098d..53af1c4095 100644 Binary files a/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfMergerTest/cmp_mergedResult04.pdf and b/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfMergerTest/cmp_mergedResult04.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfSplitterTest/cmp/splitBySize_part1.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfSplitterTest/cmp/splitBySize_part1.pdf index 36551fb67c..915fe0fcbe 100644 Binary files a/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfSplitterTest/cmp/splitBySize_part1.pdf and b/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfSplitterTest/cmp/splitBySize_part1.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfSplitterTest/cmp/splitBySize_part2.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfSplitterTest/cmp/splitBySize_part2.pdf index 4848f9a4ff..76021d15ad 100644 Binary files a/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfSplitterTest/cmp/splitBySize_part2.pdf and b/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfSplitterTest/cmp/splitBySize_part2.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfSplitterTest/cmp/splitBySize_part3.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfSplitterTest/cmp/splitBySize_part3.pdf index b5e01759ea..ba31dc3af6 100644 Binary files a/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfSplitterTest/cmp/splitBySize_part3.pdf and b/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfSplitterTest/cmp/splitBySize_part3.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfSplitterTest/cmp/splitBySize_part4.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfSplitterTest/cmp/splitBySize_part4.pdf index be3596a2b1..cc5c951365 100644 Binary files a/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfSplitterTest/cmp/splitBySize_part4.pdf and b/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfSplitterTest/cmp/splitBySize_part4.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfSplitterTest/cmp/splitDocument1_1.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfSplitterTest/cmp/splitDocument1_1.pdf index 908f8ffc75..9c3baa1f5c 100644 Binary files a/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfSplitterTest/cmp/splitDocument1_1.pdf and b/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfSplitterTest/cmp/splitDocument1_1.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfSplitterTest/cmp/splitDocument1_2.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfSplitterTest/cmp/splitDocument1_2.pdf index 0df4b9a849..741a8a45b8 100644 Binary files a/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfSplitterTest/cmp/splitDocument1_2.pdf and b/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfSplitterTest/cmp/splitDocument1_2.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfSplitterTest/cmp/splitDocument1_3.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfSplitterTest/cmp/splitDocument1_3.pdf index ed8fc585e4..95e90b12ec 100644 Binary files a/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfSplitterTest/cmp/splitDocument1_3.pdf and b/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfSplitterTest/cmp/splitDocument1_3.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfSplitterTest/cmp/splitDocument2_1.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfSplitterTest/cmp/splitDocument2_1.pdf index 59e5f29d83..3ede301dfe 100644 Binary files a/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfSplitterTest/cmp/splitDocument2_1.pdf and b/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfSplitterTest/cmp/splitDocument2_1.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfSplitterTest/cmp/splitDocument2_2.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfSplitterTest/cmp/splitDocument2_2.pdf index b3ddf0ffb9..1e5dac40a0 100644 Binary files a/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfSplitterTest/cmp/splitDocument2_2.pdf and b/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfSplitterTest/cmp/splitDocument2_2.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfSplitterTest/cmp/splitDocument2_3.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfSplitterTest/cmp/splitDocument2_3.pdf index 855933b64c..ff8597b226 100644 Binary files a/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfSplitterTest/cmp/splitDocument2_3.pdf and b/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfSplitterTest/cmp/splitDocument2_3.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfSplitterTest/cmp/splitDocument3_1.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfSplitterTest/cmp/splitDocument3_1.pdf index 3adf94c9ee..7ac0df8946 100644 Binary files a/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfSplitterTest/cmp/splitDocument3_1.pdf and b/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfSplitterTest/cmp/splitDocument3_1.pdf differ diff --git a/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfSplitterTest/cmp/splitDocument3_2.pdf b/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfSplitterTest/cmp/splitDocument3_2.pdf index 046f9c3c4c..fd7fbedaa8 100644 Binary files a/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfSplitterTest/cmp/splitDocument3_2.pdf and b/itext.tests/itext.kernel.tests/resources/itext/kernel/utils/PdfSplitterTest/cmp/splitDocument3_2.pdf differ diff --git a/itext.tests/itext.layout.tests/Properties/AssemblyInfo.cs b/itext.tests/itext.layout.tests/Properties/AssemblyInfo.cs index 6321d16e04..3dbf022143 100644 --- a/itext.tests/itext.layout.tests/Properties/AssemblyInfo.cs +++ b/itext.tests/itext.layout.tests/Properties/AssemblyInfo.cs @@ -15,5 +15,7 @@ [assembly: Guid("9ad347a8-ea5b-462b-810c-998f04471bb7")] -[assembly: AssemblyVersion("7.0.0.0")] -[assembly: AssemblyFileVersion("7.0.0.0")] +[assembly: AssemblyVersion("7.0.1.0")] +[assembly: AssemblyFileVersion("7.0.1.0")] + +[assembly: NUnit.Framework.Timeout(300000)] diff --git a/itext.tests/itext.layout.tests/itext.layout.tests.csproj b/itext.tests/itext.layout.tests/itext.layout.tests.csproj index e3a0079604..9885d52905 100644 --- a/itext.tests/itext.layout.tests/itext.layout.tests.csproj +++ b/itext.tests/itext.layout.tests/itext.layout.tests.csproj @@ -36,7 +36,7 @@ - ..\..\packages\NUnit.3.2.1\lib\net40\nunit.framework.dll + $(SolutionDir)\packages\NUnit.3.2.1\lib\net40\nunit.framework.dll
diff --git a/itext.tests/itext.layout.tests/itext/layout/AlignmentTest.cs b/itext.tests/itext.layout.tests/itext/layout/AlignmentTest.cs index 3876e90fdf..c067a3dd26 100644 --- a/itext.tests/itext.layout.tests/itext/layout/AlignmentTest.cs +++ b/itext.tests/itext.layout.tests/itext/layout/AlignmentTest.cs @@ -1,5 +1,4 @@ using System; -using System.IO; using iText.IO.Image; using iText.IO.Util; using iText.Kernel.Colors; @@ -29,7 +28,7 @@ public static void BeforeClass() { public virtual void JustifyAlignmentTest01() { String outFileName = destinationFolder + "justifyAlignmentTest01.pdf"; String cmpFileName = sourceFolder + "cmp_justifyAlignmentTest01.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); Paragraph paragraph = new Paragraph().SetTextAlignment(TextAlignment.JUSTIFIED); for (int i = 0; i < 21; i++) { @@ -48,7 +47,7 @@ public virtual void JustifyAlignmentTest01() { public virtual void JustifyAlignmentTest02() { String outFileName = destinationFolder + "justifyAlignmentTest02.pdf"; String cmpFileName = sourceFolder + "cmp_justifyAlignmentTest02.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); Paragraph paragraph = new Paragraph().SetTextAlignment(TextAlignment.JUSTIFIED); paragraph.Add(new Text("Hello World!")).Add(new Text(" ")).Add(new Text("Hello People! ")).Add("End"); @@ -64,7 +63,7 @@ public virtual void JustifyAlignmentTest02() { public virtual void JustifyAlignmentTest03() { String outFileName = destinationFolder + "justifyAlignmentTest03.pdf"; String cmpFileName = sourceFolder + "cmp_justifyAlignmentTest03.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); Paragraph paragraph = new Paragraph().SetTextAlignment(TextAlignment.JUSTIFIED); for (int i = 0; i < 21; i++) { @@ -83,7 +82,7 @@ public virtual void JustifyAlignmentTest03() { public virtual void JustifyAlignmentTest04() { String outFileName = destinationFolder + "justifyAlignmentTest04.pdf"; String cmpFileName = sourceFolder + "cmp_justifyAlignmentTest04.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); Paragraph paragraph = new Paragraph().SetTextAlignment(TextAlignment.JUSTIFIED); for (int i = 0; i < 21; i++) { @@ -102,7 +101,7 @@ public virtual void JustifyAlignmentTest04() { public virtual void JustifyAlignmentForcedNewlinesTest01() { String outFileName = destinationFolder + "justifyAlignmentForcedNewlinesTest01.pdf"; String cmpFileName = sourceFolder + "cmp_justifyAlignmentForcedNewlinesTest01.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); Paragraph paragraph = new Paragraph().SetTextAlignment(TextAlignment.JUSTIFIED); paragraph.Add("Video provides a powerful way to help you prove your point. When you click Online Video, you can paste in the embed code for the video you want to add. You can also type a keyword to search online for the video that best fits your document.\n" @@ -123,7 +122,7 @@ public virtual void JustifyAlignmentForcedNewlinesTest01() { public virtual void JustifyAllTest01() { String outFileName = destinationFolder + "justifyAllTest01.pdf"; String cmpFileName = sourceFolder + "cmp_justifyAllTest01.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); Paragraph paragraph = new Paragraph().SetTextAlignment(TextAlignment.JUSTIFIED_ALL); paragraph.Add("Video provides a powerful way to help you prove your point. When you click Online Video, you can paste in the embed code for the video you want to add. You can also type a keyword to search online for the video that best fits your document.\n" @@ -144,7 +143,7 @@ public virtual void JustifyAllTest01() { public virtual void BlockAlignmentTest01() { String outFileName = destinationFolder + "blockAlignmentTest01.pdf"; String cmpFileName = sourceFolder + "cmp_blockAlignmentTest01.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); List list = new List(ListNumberingType.GREEK_LOWER); for (int i = 0; i < 10; i++) { @@ -168,7 +167,7 @@ public virtual void BlockAlignmentTest01() { public virtual void BlockAlignmentTest02() { String outFileName = destinationFolder + "blockAlignmentTest02.pdf"; String cmpFileName = sourceFolder + "cmp_blockAlignmentTest02.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); Div div = new Div(); PdfImageXObject xObject = new PdfImageXObject(ImageDataFactory.CreateJpeg(UrlUtil.ToURL(sourceFolder + "Desert.jpg" @@ -192,8 +191,7 @@ public virtual void BlockAlignmentTest02() { public virtual void ImageAlignmentTest01() { String outFileName = destinationFolder + "imageAlignmentTest01.pdf"; String cmpFileName = sourceFolder + "cmp_imageAlignmentTest01.pdf"; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); + PdfWriter writer = new PdfWriter(outFileName); PdfDocument pdfDoc = new PdfDocument(writer); Document doc = new Document(pdfDoc); PdfImageXObject xObject = new PdfImageXObject(ImageDataFactory.CreateJpeg(UrlUtil.ToURL(sourceFolder + "Desert.jpg" diff --git a/itext.tests/itext.layout.tests/itext/layout/AreaBreakTest.cs b/itext.tests/itext.layout.tests/itext/layout/AreaBreakTest.cs index 9f4558d973..3a9350f0d1 100644 --- a/itext.tests/itext.layout.tests/itext/layout/AreaBreakTest.cs +++ b/itext.tests/itext.layout.tests/itext/layout/AreaBreakTest.cs @@ -1,5 +1,4 @@ using System; -using System.IO; using iText.Kernel.Geom; using iText.Kernel.Pdf; using iText.Kernel.Utils; @@ -25,7 +24,7 @@ public static void BeforeClass() { public virtual void PageBreakTest1() { String outFileName = destinationFolder + "pageBreak1.pdf"; String cmpFileName = sourceFolder + "cmp_pageBreak1.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); document.Add(new AreaBreak()); document.Close(); @@ -39,7 +38,7 @@ public virtual void PageBreakTest1() { public virtual void PageBreakTest2() { String outFileName = destinationFolder + "pageBreak2.pdf"; String cmpFileName = sourceFolder + "cmp_pageBreak2.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); document.Add(new Paragraph("Hello World!")).Add(new AreaBreak(new PageSize(200, 200))); document.Close(); @@ -53,7 +52,7 @@ public virtual void PageBreakTest2() { public virtual void PageBreakTest03() { String outFileName = destinationFolder + "pageBreak3.pdf"; String cmpFileName = sourceFolder + "cmp_pageBreak3.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); document.SetRenderer(new ColumnDocumentRenderer(document, new Rectangle[] { new Rectangle(30, 30, 200, 600 ), new Rectangle(300, 30, 200, 600) })); diff --git a/itext.tests/itext.layout.tests/itext/layout/AutoTaggingTest.cs b/itext.tests/itext.layout.tests/itext/layout/AutoTaggingTest.cs index 493e24f6ba..22e91806a5 100644 --- a/itext.tests/itext.layout.tests/itext/layout/AutoTaggingTest.cs +++ b/itext.tests/itext.layout.tests/itext/layout/AutoTaggingTest.cs @@ -1,5 +1,4 @@ using System; -using System.IO; using System.Text; using iText.IO.Font; using iText.IO.Image; @@ -32,8 +31,7 @@ public static void BeforeClass() { /// [NUnit.Framework.Test] public virtual void TextInParagraphTest01() { - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(destinationFolder + "textInParagraphTest01.pdf" - , FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(destinationFolder + "textInParagraphTest01.pdf")); pdfDocument.SetTagged(); Document document = new Document(pdfDocument); Paragraph p = CreateParagraph1(); @@ -51,8 +49,7 @@ public virtual void TextInParagraphTest01() { /// [NUnit.Framework.Test] public virtual void ImageTest01() { - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(destinationFolder + "imageTest01.pdf" - , FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(destinationFolder + "imageTest01.pdf")); pdfDocument.SetTagged(); Document document = new Document(pdfDocument); iText.Layout.Element.Image image = new Image(ImageDataFactory.Create(sourceFolder + imageName)); @@ -67,8 +64,7 @@ public virtual void ImageTest01() { /// [NUnit.Framework.Test] public virtual void DivTest01() { - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(destinationFolder + "divTest01.pdf" - , FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(destinationFolder + "divTest01.pdf")); pdfDocument.SetTagged(); Document document = new Document(pdfDocument); Div div = new Div(); @@ -91,8 +87,7 @@ public virtual void DivTest01() { /// [NUnit.Framework.Test] public virtual void TableTest01() { - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(destinationFolder + "tableTest01.pdf" - , FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(destinationFolder + "tableTest01.pdf")); pdfDocument.SetTagged(); Document document = new Document(pdfDocument); Table table = new Table(3); @@ -120,8 +115,7 @@ public virtual void TableTest01() { /// [NUnit.Framework.Test] public virtual void TableTest02() { - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(destinationFolder + "tableTest02.pdf" - , FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(destinationFolder + "tableTest02.pdf")); pdfDocument.SetTagged(); Document document = new Document(pdfDocument); Table table = new Table(3); @@ -140,8 +134,7 @@ public virtual void TableTest02() { /// [NUnit.Framework.Test] public virtual void TableTest03() { - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(destinationFolder + "tableTest03.pdf" - , FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(destinationFolder + "tableTest03.pdf")); pdfDocument.SetTagged(); Document document = new Document(pdfDocument); Table table = new Table(3); @@ -166,8 +159,7 @@ public virtual void TableTest03() { /// [NUnit.Framework.Test] public virtual void TableTest04() { - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(destinationFolder + "tableTest04.pdf" - , FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(destinationFolder + "tableTest04.pdf")); pdfDocument.SetTagged(); Document doc = new Document(pdfDocument); Table table = new Table(5, true); @@ -195,8 +187,7 @@ public virtual void TableTest04() { public virtual void TableTest05() { String outFileName = destinationFolder + "tableTest05.pdf"; String cmpFileName = sourceFolder + "cmp_tableTest05.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(destinationFolder + "tableTest05.pdf" - , FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(destinationFolder + "tableTest05.pdf")); pdfDocument.SetTagged(); Document doc = new Document(pdfDocument); Table table = new Table(5, true); @@ -225,8 +216,7 @@ public virtual void TableTest05() { /// [NUnit.Framework.Test] public virtual void TableTest06() { - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(destinationFolder + "tableTest06.pdf" - , FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(destinationFolder + "tableTest06.pdf")); pdfDocument.SetTagged(); Document doc = new Document(pdfDocument); String textContent = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis urna.\n" @@ -257,8 +247,7 @@ public virtual void TableTest06() { /// [NUnit.Framework.Test] public virtual void ListTest01() { - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(destinationFolder + "listTest01.pdf" - , FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(destinationFolder + "listTest01.pdf")); pdfDocument.SetTagged(); Document doc = new Document(pdfDocument); List list = new List(); @@ -276,8 +265,7 @@ public virtual void ListTest01() { /// [NUnit.Framework.Test] public virtual void ArtifactTest01() { - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(destinationFolder + "artifactTest01.pdf" - , FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(destinationFolder + "artifactTest01.pdf")); pdfDocument.SetTagged(); Document document = new Document(pdfDocument); String watermarkText = "WATERMARK"; @@ -299,8 +287,7 @@ public virtual void ArtifactTest01() { /// [NUnit.Framework.Test] public virtual void ArtifactTest02() { - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(destinationFolder + "artifactTest02.pdf" - , FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(destinationFolder + "artifactTest02.pdf")); pdfDocument.SetTagged(); Document document = new Document(pdfDocument); document.Add(new Paragraph("Hello world")); @@ -328,8 +315,7 @@ public virtual void ArtifactTest02() { /// [NUnit.Framework.Test] public virtual void FlushingTest01() { - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(destinationFolder + "flushingTest01.pdf" - , FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(destinationFolder + "flushingTest01.pdf")); pdfDocument.SetTagged(); Document document = new Document(pdfDocument); Paragraph p = CreateParagraph1(); @@ -359,8 +345,7 @@ public virtual void FlushingTest01() { /// [NUnit.Framework.Test] public virtual void FlushingTest02() { - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(destinationFolder + "flushingTest02.pdf" - , FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(destinationFolder + "flushingTest02.pdf")); pdfDocument.SetTagged(); Document doc = new Document(pdfDocument); Table table = new Table(5, true); @@ -398,8 +383,7 @@ public virtual void FlushingTest02() { /// [NUnit.Framework.Test] public virtual void FlushingTest03() { - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(destinationFolder + "flushingTest03.pdf" - , FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(destinationFolder + "flushingTest03.pdf")); pdfDocument.SetTagged(); Document doc = new Document(pdfDocument); Table table = new Table(5, true); diff --git a/itext.tests/itext.layout.tests/itext/layout/BackgroundColorTest.cs b/itext.tests/itext.layout.tests/itext/layout/BackgroundColorTest.cs new file mode 100644 index 0000000000..79ebb5df53 --- /dev/null +++ b/itext.tests/itext.layout.tests/itext/layout/BackgroundColorTest.cs @@ -0,0 +1,57 @@ +using System; +using System.IO; +using iText.Kernel.Colors; +using iText.Kernel.Pdf; +using iText.Kernel.Utils; +using iText.Layout.Element; +using iText.Test; + +namespace iText.Layout { + public class BackgroundColorTest : ExtendedITextTest { + public static readonly String sourceFolder = NUnit.Framework.TestContext.CurrentContext.TestDirectory + "/../../resources/itext/layout/BackgroundColorTest/"; + + public static readonly String destinationFolder = NUnit.Framework.TestContext.CurrentContext.TestDirectory + + "/test/itext/layout/BackgroundColorTest/"; + + public const String cmpPrefix = "cmp_"; + + internal String fileName; + + internal String outFileName; + + internal String cmpFileName; + + [NUnit.Framework.TestFixtureSetUp] + public static void BeforeClass() { + CreateDestinationFolder(destinationFolder); + } + + /// + /// + /// + [NUnit.Framework.Test] + public virtual void ShouldAddBackgroundColorAttributeToAccessiblityWhenBackgroundColorIsSet() { + fileName = "simpleBackgroundColorTest.pdf"; + outFileName = destinationFolder + fileName; + cmpFileName = sourceFolder + cmpPrefix + fileName; + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + pdfDocument.SetTagged(); + Document doc = new Document(pdfDocument); + Text foo = new Text("foo"); + foo.SetBackgroundColor(Color.BLUE); + doc.Add(new Paragraph(foo)); + CloseDocumentAndCompareOutputs(doc); + } + + /// + /// + private void CloseDocumentAndCompareOutputs(Document document) { + document.Close(); + String compareResult = new CompareTool().CompareByContent(outFileName, cmpFileName, destinationFolder, "diff" + ); + if (compareResult != null) { + NUnit.Framework.Assert.Fail(compareResult); + } + } + } +} diff --git a/itext.tests/itext.layout.tests/itext/layout/BorderTest.cs b/itext.tests/itext.layout.tests/itext/layout/BorderTest.cs index 7c49a859d4..8ff3c493b5 100644 --- a/itext.tests/itext.layout.tests/itext/layout/BorderTest.cs +++ b/itext.tests/itext.layout.tests/itext/layout/BorderTest.cs @@ -1,11 +1,12 @@ using System; -using System.IO; +using iText.IO; using iText.Kernel.Colors; using iText.Kernel.Pdf; using iText.Kernel.Utils; using iText.Layout.Borders; using iText.Layout.Element; using iText.Test; +using iText.Test.Attributes; namespace iText.Layout { public class BorderTest : ExtendedITextTest { @@ -178,11 +179,196 @@ public virtual void BorderBoxTest() { CloseDocumentAndCompareOutputs(doc); } + /// + /// + [NUnit.Framework.Test] + public virtual void NoVerticalBorderTest() { + fileName = "noVerticalBorderTest.pdf"; + Document doc = CreateDocument(); + Table mainTable = new Table(1); + Cell cell = new Cell().SetBorder(Border.NO_BORDER).SetBorderTop(new SolidBorder(Color.BLACK, 0.5f)); + cell.Add("TESCHTINK"); + mainTable.AddCell(cell); + doc.Add(mainTable); + doc.Close(); + CloseDocumentAndCompareOutputs(doc); + } + + /// + /// + [NUnit.Framework.Test] + public virtual void WideBorderTest01() { + fileName = "wideBorderTest01.pdf"; + Document doc = CreateDocument(); + doc.Add(new Paragraph("ROWS SHOULD BE THE SAME")); + Table table = new Table(new float[] { 1, 3 }); + table.SetWidthPercent(50); + Cell cell; + // row 21, cell 1 + cell = new Cell().Add("BORDERS"); + table.AddCell(cell); + // row 1, cell 2 + cell = new Cell().Add("ONE"); + cell.SetBorderLeft(new SolidBorder(Color.RED, 16f)); + table.AddCell(cell); + // row 2, cell 1 + cell = new Cell().Add("BORDERS"); + table.AddCell(cell); + // row 2, cell 2 + cell = new Cell().Add("TWO"); + cell.SetBorderLeft(new SolidBorder(Color.RED, 16f)); + table.AddCell(cell); + doc.Add(table); + CloseDocumentAndCompareOutputs(doc); + } + + /// + /// + [NUnit.Framework.Test] + [NUnit.Framework.Ignore("DEVSIX-798")] + public virtual void WideBorderTest02() { + fileName = "wideBorderTest02.pdf"; + Document doc = CreateDocument(); + Table table = new Table(1); + table.SetWidthPercent(50); + Cell cell; + cell = new Cell().Add("Borders shouldn't be layouted outside the layout area."); + cell.SetBorder(new SolidBorder(Color.RED, 100f)); + table.AddCell(cell); + doc.Add(table); + CloseDocumentAndCompareOutputs(doc); + } + + /// + /// + [NUnit.Framework.Test] + [LogMessage(LogMessageConstant.ELEMENT_DOES_NOT_FIT_AREA)] + public virtual void InfiniteLoopTest01() { + fileName = "infiniteLoopTest01.pdf"; + Document doc = CreateDocument(); + Table table = new Table(new float[] { 1, 3 }); + table.SetWidthPercent(50); + Cell cell; + // row 1, cell 1 + cell = new Cell().Add("1ORD"); + cell.SetBorderLeft(new SolidBorder(Color.BLUE, 5)); + table.AddCell(cell); + // row 1, cell 2 + cell = new Cell().Add("ONE"); + cell.SetBorderLeft(new SolidBorder(Color.RED, 100f)); + table.AddCell(cell); + // row 2, cell 1 + cell = new Cell().Add("2ORD"); + cell.SetBorderTop(new SolidBorder(Color.YELLOW, 100f)); + table.AddCell(cell); + // row 2, cell 2 + cell = new Cell().Add("TWO"); + cell.SetBorderLeft(new SolidBorder(Color.RED, 0.5f)); + table.AddCell(cell); + doc.Add(table); + CloseDocumentAndCompareOutputs(doc); + } + + /// + /// + [NUnit.Framework.Test] + [NUnit.Framework.Ignore("DEVSIX-818")] + public virtual void SplitCellsTest01() { + fileName = "splitCellsTest01.pdf"; + Document doc = CreateDocument(); + String longText = "Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text." + + "Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text." + + "Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text." + + "Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text." + + "Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text." + + "Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text." + + "Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text." + + "Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text." + + "Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text." + + "Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text." + + "Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text." + + "Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text." + + "Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text." + + "Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text." + + "Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text." + + "Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text." + + "Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text." + + "Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text." + + "Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text." + + "Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text." + + "Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text." + + "Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text." + + "Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text." + + "Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text." + + "Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text." + + "Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text." + + "Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text." + + "Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text." + + "Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text." + + "Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text." + + "Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text." + + "Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text.Very very very very very very very very very very very very very very very very very very long text."; + Table table = new Table(2); + Cell cell; + cell = new Cell().Add("Some text"); + cell.SetBorderRight(new SolidBorder(Color.RED, 2f)); + table.AddCell(cell); + cell = new Cell().Add("Some text"); + cell.SetBorderLeft(new SolidBorder(Color.GREEN, 4f)); + table.AddCell(cell); + cell = new Cell().Add(longText); + cell.SetBorderBottom(new SolidBorder(Color.RED, 5f)); + table.AddCell(cell); + table.AddCell(new Cell().Add("Hello").SetBorderBottom(new SolidBorder(Color.BLUE, 5f))); + cell = new Cell().Add("Some text."); + cell.SetBorderTop(new SolidBorder(Color.GREEN, 6f)); + table.AddCell(cell); + table.AddCell(new Cell().Add("World").SetBorderTop(new SolidBorder(Color.YELLOW, 6f))); + doc.Add(table); + CloseDocumentAndCompareOutputs(doc); + } + + /// + /// + [NUnit.Framework.Test] + [LogMessage(LogMessageConstant.ELEMENT_DOES_NOT_FIT_AREA, Count = 2)] + public virtual void ForcedPlacementTest01() { + fileName = "forcedPlacementTest01.pdf"; + Document doc = CreateDocument(); + Table table = new Table(1); + table.SetWidth(10); + Cell cell; + // row 1, cell 1 + cell = new Cell().Add("1ORD"); + table.AddCell(cell); + // row 2, cell 1 + cell = new Cell().Add("2ORD"); + cell.SetBorderTop(new SolidBorder(Color.YELLOW, 100f)); + table.AddCell(cell); + doc.Add(table); + CloseDocumentAndCompareOutputs(doc); + } + + /// + /// + [NUnit.Framework.Test] + public virtual void NoHorizontalBorderTest() { + fileName = "noHorizontalBorderTest.pdf"; + Document doc = CreateDocument(); + Table mainTable = new Table(1); + Cell cell = new Cell().SetBorder(Border.NO_BORDER).SetBorderRight(new SolidBorder(Color.BLACK, 0.5f)); + cell.Add("TESCHTINK"); + mainTable.AddCell(cell); + doc.Add(mainTable); + doc.Close(); + CloseDocumentAndCompareOutputs(doc); + } + /// private Document CreateDocument() { outFileName = destinationFolder + fileName; cmpFileName = sourceFolder + cmpPrefix + fileName; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); return new Document(pdfDocument); } diff --git a/itext.tests/itext.layout.tests/itext/layout/DefaultLayoutTest.cs b/itext.tests/itext.layout.tests/itext/layout/DefaultLayoutTest.cs index 414fada7dd..74ea0e91ce 100644 --- a/itext.tests/itext.layout.tests/itext/layout/DefaultLayoutTest.cs +++ b/itext.tests/itext.layout.tests/itext/layout/DefaultLayoutTest.cs @@ -1,5 +1,4 @@ using System; -using System.IO; using iText.IO; using iText.Kernel.Colors; using iText.Kernel.Geom; @@ -28,7 +27,7 @@ public static void BeforeClass() { public virtual void MultipleAdditionsOfSameModelElementTest() { String outFileName = destinationFolder + "multipleAdditionsOfSameModelElementTest1.pdf"; String cmpFileName = sourceFolder + "cmp_multipleAdditionsOfSameModelElementTest1.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); Paragraph p = new Paragraph("Hello. I am a paragraph. I want you to process me correctly"); document.Add(p).Add(p).Add(new AreaBreak(PageSize.Default)).Add(p); @@ -43,7 +42,7 @@ public virtual void MultipleAdditionsOfSameModelElementTest() { public virtual void RendererTest01() { String outFileName = destinationFolder + "rendererTest01.pdf"; String cmpFileName = sourceFolder + "cmp_rendererTest01.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); String str = "Hello. I am a fairly long paragraph. I really want you to process me correctly. You heard that? Correctly!!! Even if you will have to wrap me."; document.Add(new Paragraph(new Text(str).SetBackgroundColor(Color.RED)).SetBackgroundColor(Color.GREEN)).Add @@ -60,7 +59,7 @@ public virtual void RendererTest01() { public virtual void EmptyParagraphsTest01() { String outFileName = destinationFolder + "emptyParagraphsTest01.pdf"; String cmpFileName = sourceFolder + "cmp_emptyParagraphsTest01.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); // the next 3 lines should not cause any effect document.Add(new Paragraph()); @@ -80,7 +79,7 @@ public virtual void EmptyParagraphsTest01() { public virtual void EmptyParagraphsTest02() { String outFileName = destinationFolder + "emptyParagraphsTest02.pdf"; String cmpFileName = sourceFolder + "cmp_emptyParagraphsTest02.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); document.Add(new Paragraph("Hello, i'm the text of the first paragraph on the first line. Let's break me and meet on the next line!\nSee? I'm on the second line. Now let's create some empty lines,\n for example one\n\nor two\n\n\nor three\n\n\n\nNow let's do something else" )); @@ -90,5 +89,44 @@ public virtual void EmptyParagraphsTest02() { NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFileName, cmpFileName, destinationFolder , "diff")); } + + /// + /// + [NUnit.Framework.Test] + [LogMessage(LogMessageConstant.ELEMENT_DOES_NOT_FIT_AREA, Count = 2)] + public virtual void AddParagraphOnShortPage1() { + String outFileName = destinationFolder + "addParagraphOnShortPage1.pdf"; + String cmpFileName = sourceFolder + "cmp_addParagraphOnShortPage1.pdf"; + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); + Document doc = new Document(pdfDoc, new PageSize(500, 70)); + Paragraph p = new Paragraph(); + p.Add("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"); + p.Add(new Text("BBB").SetFontSize(30)); + p.Add("CCC"); + p.Add("DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD"); + p.Add("EEE"); + doc.Add(p); + doc.Close(); + NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFileName, cmpFileName, destinationFolder + , "diff")); + } + + /// + /// + [NUnit.Framework.Test] + [LogMessage(LogMessageConstant.ELEMENT_DOES_NOT_FIT_AREA)] + public virtual void AddParagraphOnShortPage2() { + String outFileName = destinationFolder + "addParagraphOnShortPage2.pdf"; + String cmpFileName = sourceFolder + "cmp_addParagraphOnShortPage2.pdf"; + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); + Document doc = new Document(pdfDoc, new PageSize(300, 50)); + Paragraph p = new Paragraph(); + p.Add("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + ); + doc.Add(p); + doc.Close(); + NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFileName, cmpFileName, destinationFolder + , "diff")); + } } } diff --git a/itext.tests/itext.layout.tests/itext/layout/ImageTest.cs b/itext.tests/itext.layout.tests/itext/layout/ImageTest.cs index d5d025f39d..b8ecb26d47 100644 --- a/itext.tests/itext.layout.tests/itext/layout/ImageTest.cs +++ b/itext.tests/itext.layout.tests/itext/layout/ImageTest.cs @@ -1,12 +1,13 @@ using System; -using System.IO; using iText.IO; using iText.IO.Image; using iText.IO.Util; +using iText.Kernel.Geom; using iText.Kernel.Pdf; using iText.Kernel.Pdf.Xobject; using iText.Kernel.Utils; using iText.Layout.Element; +using iText.Layout.Properties; using iText.Test; using iText.Test.Attributes; @@ -28,8 +29,7 @@ public static void BeforeClass() { public virtual void ImageTest01() { String outFileName = destinationFolder + "imageTest01.pdf"; String cmpFileName = sourceFolder + "cmp_imageTest01.pdf"; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); + PdfWriter writer = new PdfWriter(outFileName); PdfDocument pdfDoc = new PdfDocument(writer); Document doc = new Document(pdfDoc); PdfImageXObject xObject = new PdfImageXObject(ImageDataFactory.Create(sourceFolder + "Desert.jpg")); @@ -50,8 +50,7 @@ public virtual void ImageTest01() { public virtual void ImageTest02() { String outFileName = destinationFolder + "imageTest02.pdf"; String cmpFileName = sourceFolder + "cmp_imageTest02.pdf"; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); + PdfWriter writer = new PdfWriter(outFileName); PdfDocument pdfDoc = new PdfDocument(writer); Document doc = new Document(pdfDoc); PdfImageXObject xObject = new PdfImageXObject(ImageDataFactory.CreateJpeg(UrlUtil.ToURL(sourceFolder + "Desert.jpg" @@ -73,8 +72,7 @@ public virtual void ImageTest02() { public virtual void ImageTest03() { String outFileName = destinationFolder + "imageTest03.pdf"; String cmpFileName = sourceFolder + "cmp_imageTest03.pdf"; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); + PdfWriter writer = new PdfWriter(outFileName); PdfDocument pdfDoc = new PdfDocument(writer); Document doc = new Document(pdfDoc); PdfImageXObject xObject = new PdfImageXObject(ImageDataFactory.Create(sourceFolder + "Desert.jpg")); @@ -96,8 +94,7 @@ public virtual void ImageTest03() { public virtual void ImageTest04() { String outFileName = destinationFolder + "imageTest04.pdf"; String cmpFileName = sourceFolder + "cmp_imageTest04.pdf"; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); + PdfWriter writer = new PdfWriter(outFileName); PdfDocument pdfDoc = new PdfDocument(writer); Document doc = new Document(pdfDoc); PdfImageXObject xObject = new PdfImageXObject(ImageDataFactory.Create(sourceFolder + "Desert.jpg")); @@ -119,8 +116,7 @@ public virtual void ImageTest04() { public virtual void ImageTest05() { String outFileName = destinationFolder + "imageTest05.pdf"; String cmpFileName = sourceFolder + "cmp_imageTest05.pdf"; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); + PdfWriter writer = new PdfWriter(outFileName); PdfDocument pdfDoc = new PdfDocument(writer); Document doc = new Document(pdfDoc); PdfImageXObject xObject = new PdfImageXObject(ImageDataFactory.Create(sourceFolder + "Desert.jpg")); @@ -142,8 +138,7 @@ public virtual void ImageTest05() { public virtual void ImageTest06() { String outFileName = destinationFolder + "imageTest06.pdf"; String cmpFileName = sourceFolder + "cmp_imageTest06.pdf"; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); + PdfWriter writer = new PdfWriter(outFileName); PdfDocument pdfDoc = new PdfDocument(writer); Document doc = new Document(pdfDoc); PdfImageXObject xObject = new PdfImageXObject(ImageDataFactory.Create(sourceFolder + "Desert.jpg")); @@ -166,8 +161,7 @@ public virtual void ImageTest06() { public virtual void ImageTest07() { String outFileName = destinationFolder + "imageTest07.pdf"; String cmpFileName = sourceFolder + "cmp_imageTest07.pdf"; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); + PdfWriter writer = new PdfWriter(outFileName); PdfDocument pdfDoc = new PdfDocument(writer); Document doc = new Document(pdfDoc); iText.Layout.Element.Image image = new iText.Layout.Element.Image(ImageDataFactory.Create(sourceFolder + "Desert.jpg" @@ -187,8 +181,7 @@ public virtual void ImageTest07() { public virtual void ImageTest08() { String outFileName = destinationFolder + "imageTest08.pdf"; String cmpFileName = sourceFolder + "cmp_imageTest08.pdf"; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); + PdfWriter writer = new PdfWriter(outFileName); PdfDocument pdfDoc = new PdfDocument(writer); Document doc = new Document(pdfDoc); iText.Layout.Element.Image image = new iText.Layout.Element.Image(ImageDataFactory.Create(sourceFolder + "Desert.jpg" @@ -202,6 +195,114 @@ public virtual void ImageTest08() { , "diff")); } + /// + /// + [NUnit.Framework.Test] + public virtual void ImageTest09() { + String outFileName = destinationFolder + "imageTest09.pdf"; + String cmpFileName = sourceFolder + "cmp_imageTest09.pdf"; + PdfWriter writer = new PdfWriter(outFileName); + PdfDocument pdfDoc = new PdfDocument(writer); + Document doc = new Document(pdfDoc, new PageSize(500, 300)); + iText.Layout.Element.Image image = new iText.Layout.Element.Image(ImageDataFactory.Create(sourceFolder + "Desert.jpg" + )); + image.SetWidthPercent(100); + doc.Add(image); + doc.Close(); + NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFileName, cmpFileName, destinationFolder + , "diff")); + } + + /// + /// + [NUnit.Framework.Test] + public virtual void ImageTest10() { + String outFileName = destinationFolder + "imageTest10.pdf"; + String cmpFileName = sourceFolder + "cmp_imageTest10.pdf"; + PdfWriter writer = new PdfWriter(outFileName); + PdfDocument pdfDoc = new PdfDocument(writer); + Document doc = new Document(pdfDoc, new PageSize(500, 300)); + iText.Layout.Element.Image image = new iText.Layout.Element.Image(ImageDataFactory.Create(sourceFolder + "Desert.jpg" + )); + image.SetAutoScale(true); + doc.Add(image); + doc.Close(); + NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFileName, cmpFileName, destinationFolder + , "diff")); + } + + /// + /// + [NUnit.Framework.Test] + public virtual void ImageTest11() { + String outFileName = destinationFolder + "imageTest11.pdf"; + String cmpFileName = sourceFolder + "cmp_imageTest11.pdf"; + PdfWriter writer = new PdfWriter(outFileName); + PdfDocument pdfDoc = new PdfDocument(writer); + Document doc = new Document(pdfDoc); + iText.Layout.Element.Image image = new iText.Layout.Element.Image(ImageDataFactory.Create(sourceFolder + "Desert.jpg" + )); + image.SetAutoScale(true); + doc.Add(image); + doc.Close(); + NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFileName, cmpFileName, destinationFolder + , "diff")); + } + + /// + /// + [NUnit.Framework.Test] + public virtual void ImageTest12_HorizontalAlignment_CENTER() { + String outFileName = destinationFolder + "imageTest12.pdf"; + String cmpFileName = sourceFolder + "cmp_imageTest12.pdf"; + PdfWriter writer = new PdfWriter(outFileName); + PdfDocument pdfDoc = new PdfDocument(writer); + Document doc = new Document(pdfDoc); + iText.Layout.Element.Image image = new iText.Layout.Element.Image(ImageDataFactory.Create(sourceFolder + "itis.jpg" + )); + image.SetHorizontalAlignment(HorizontalAlignment.CENTER); + doc.Add(image); + doc.Close(); + NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFileName, cmpFileName, destinationFolder + , "diff")); + } + + /// + /// + [NUnit.Framework.Test] + public virtual void ImageTest13_HorizontalAlignment_RIGHT() { + String outFileName = destinationFolder + "imageTest13.pdf"; + String cmpFileName = sourceFolder + "cmp_imageTest13.pdf"; + PdfWriter writer = new PdfWriter(outFileName); + PdfDocument pdfDoc = new PdfDocument(writer); + Document doc = new Document(pdfDoc); + iText.Layout.Element.Image image = new iText.Layout.Element.Image(ImageDataFactory.Create(sourceFolder + "itis.jpg" + )); + image.SetHorizontalAlignment(HorizontalAlignment.RIGHT); + doc.Add(image); + doc.Close(); + NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFileName, cmpFileName, destinationFolder + , "diff")); + } + + /// + /// + [NUnit.Framework.Test] + public virtual void ImageTest14_HorizontalAlignment_LEFT() { + String outFileName = destinationFolder + "imageTest14.pdf"; + String cmpFileName = sourceFolder + "cmp_imageTest14.pdf"; + PdfWriter writer = new PdfWriter(outFileName); + PdfDocument pdfDoc = new PdfDocument(writer); + Document doc = new Document(pdfDoc); + iText.Layout.Element.Image image = new iText.Layout.Element.Image(ImageDataFactory.Create(sourceFolder + "itis.jpg" + )); + image.SetHorizontalAlignment(HorizontalAlignment.LEFT); + doc.Add(image); + doc.Close(); + NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFileName, cmpFileName, destinationFolder + , "diff")); + } + /// Image can be reused in layout, so flushing it on the very first draw is a bad thing. /// /// @@ -210,8 +311,7 @@ public virtual void FlushOnDrawTest() { String outFileName = destinationFolder + "flushOnDrawTest.pdf"; String cmpFileName = sourceFolder + "cmp_flushOnDrawTest.pdf"; int rowCount = 60; - FileStream fos = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); + PdfWriter writer = new PdfWriter(outFileName); PdfDocument pdfDoc = new PdfDocument(writer); Document document = new Document(pdfDoc); iText.Layout.Element.Image img = new iText.Layout.Element.Image(ImageDataFactory.Create(sourceFolder + "Desert.jpg" diff --git a/itext.tests/itext.layout.tests/itext/layout/KeepTogetherTest.cs b/itext.tests/itext.layout.tests/itext/layout/KeepTogetherTest.cs index a3ae38f7e1..692f0a4d0a 100644 --- a/itext.tests/itext.layout.tests/itext/layout/KeepTogetherTest.cs +++ b/itext.tests/itext.layout.tests/itext/layout/KeepTogetherTest.cs @@ -1,5 +1,4 @@ using System; -using System.IO; using iText.IO; using iText.Kernel.Geom; using iText.Kernel.Pdf; @@ -27,7 +26,7 @@ public static void BeforeClass() { public virtual void KeepTogetherParagraphTest01() { String cmpFileName = sourceFolder + "cmp_keepTogetherParagraphTest01.pdf"; String outFile = destinationFolder + "keepTogetherParagraphTest01.pdf"; - PdfWriter writer = new PdfWriter(new FileStream(outFile, FileMode.Create)); + PdfWriter writer = new PdfWriter(outFile); PdfDocument pdfDoc = new PdfDocument(writer); Document doc = new Document(pdfDoc); for (int i = 0; i < 29; i++) { @@ -49,7 +48,7 @@ public virtual void KeepTogetherParagraphTest01() { public virtual void KeepTogetherParagraphTest02() { String cmpFileName = sourceFolder + "cmp_keepTogetherParagraphTest02.pdf"; String outFile = destinationFolder + "keepTogetherParagraphTest02.pdf"; - PdfWriter writer = new PdfWriter(new FileStream(outFile, FileMode.Create)); + PdfWriter writer = new PdfWriter(outFile); PdfDocument pdfDoc = new PdfDocument(writer); Document doc = new Document(pdfDoc); for (int i = 0; i < 28; i++) { @@ -73,8 +72,7 @@ public virtual void KeepTogetherParagraphTest02() { public virtual void KeepTogetherListTest01() { String cmpFileName = sourceFolder + "cmp_keepTogetherListTest01.pdf"; String outFile = destinationFolder + "keepTogetherListTest01.pdf"; - PdfWriter writer = new PdfWriter(new FileStream(outFile, FileMode.Create)); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFile)); Document doc = new Document(pdfDoc); for (int i = 0; i < 28; i++) { doc.Add(new Paragraph("String number" + i)); @@ -94,7 +92,7 @@ public virtual void KeepTogetherListTest01() { public virtual void KeepTogetherDivTest01() { String cmpFileName = sourceFolder + "cmp_keepTogetherDivTest01.pdf"; String outFile = destinationFolder + "keepTogetherDivTest01.pdf"; - PdfWriter writer = new PdfWriter(new FileStream(outFile, FileMode.Create)); + PdfWriter writer = new PdfWriter(outFile); PdfDocument pdfDoc = new PdfDocument(writer); Document doc = new Document(pdfDoc); Paragraph p = new Paragraph("Test String"); @@ -119,8 +117,7 @@ public virtual void KeepTogetherDivTest01() { public virtual void KeepTogetherDivTest02() { String cmpFileName = sourceFolder + "cmp_keepTogetherDivTest02.pdf"; String outFile = destinationFolder + "keepTogetherDivTest02.pdf"; - PdfWriter writer = new PdfWriter(new FileStream(outFile, FileMode.Create)); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFile)); Document doc = new Document(pdfDoc); Rectangle[] columns = new Rectangle[] { new Rectangle(100, 100, 100, 500), new Rectangle(400, 100, 100, 500 ) }; diff --git a/itext.tests/itext.layout.tests/itext/layout/KeepWithNextTest.cs b/itext.tests/itext.layout.tests/itext/layout/KeepWithNextTest.cs new file mode 100644 index 0000000000..f067aef474 --- /dev/null +++ b/itext.tests/itext.layout.tests/itext/layout/KeepWithNextTest.cs @@ -0,0 +1,245 @@ +using System; +using iText.IO.Font; +using iText.Kernel.Font; +using iText.Kernel.Geom; +using iText.Kernel.Pdf; +using iText.Kernel.Utils; +using iText.Layout.Element; +using iText.Layout.Properties; +using iText.Test; + +namespace iText.Layout { + public class KeepWithNextTest : ExtendedITextTest { + public static readonly String sourceFolder = NUnit.Framework.TestContext.CurrentContext.TestDirectory + "/../../resources/itext/layout/KeepWithNextTest/"; + + public static readonly String destinationFolder = NUnit.Framework.TestContext.CurrentContext.TestDirectory + + "/test/itext/layout/KeepWithNextTest/"; + + private const String MIDDLE_TEXT = "Video provides a powerful way to help you prove your point. When you click Online Video, you can paste in the embed code for the video you want to add. You can also type a keyword to search online for the video that best fits your document. To make your document look professionally produced, Word provides header, footer, cover page, and text box designs that complement each other. For example, you can add a matching cover page, header, and sidebar. Click Insert and then choose the elements you want from the different galleries. Themes and styles also help keep your document coordinated. When you click Design and choose a new Theme, the pictures, charts, and SmartArt graphics change to match your new theme. When you apply styles, your headings change to match the new theme. Save time in Word with new buttons that show up where you need them."; + + private const String SHORT_TEXT = "Reading is easier, too, in the new Reading view. You can collapse parts of the document and focus on the text you want. If you need to stop reading before you reach the end, Word remembers where you left off - even on another device."; + + private const String LONG_TEXT = "Video provides a powerful way to help you prove your point. When you click Online Video, you can paste in the embed code for the video you want to add. You can also type a keyword to search online for the video that best fits your document.\n" + + "To make your document look professionally produced, Word provides header, footer, cover page, and text box designs that complement each other. For example, you can add a matching cover page, header, and sidebar. Click Insert and then choose the elements you want from the different galleries.\n" + + "Themes and styles also help keep your document coordinated. When you click Design and choose a new Theme, the pictures, charts, and SmartArt graphics change to match your new theme. When you apply styles, your headings change to match the new theme.\n" + + "Save time in Word with new buttons that show up where you need them. To change the way a picture fits in your document, click it and a button for layout options appears next to it. When you work on a table, click where you want to add a row or a column, and then click the plus sign.\n" + + "Reading is easier, too, in the new Reading view. You can collapse parts of the document and focus on the text you want. If you need to stop reading before you reach the end, Word remembers where you left off - even on another device.\n" + + "Video provides a powerful way to help you prove your point. When you click Online Video, you can paste in the embed code for the video you want to add. You can also type a keyword to search online for the video that best fits your document. To make your document look professionally produced, Word provides header, footer, cover page, and text box designs that complement each other. For example, you can add a matching cover page, header, and sidebar. Click Insert and then choose the elements you want from the different galleries. Themes and styles also help keep your document coordinated. When you click Design and choose a new Theme, the pictures, charts, and SmartArt graphics change to match your new theme. When you apply styles, your headings change to match the new theme. Save time in Word with new buttons that show up where you need them.\n" + + "To change the way a picture fits in your document, click it and a button for layout options appears next to it. When you work on a table, click where you want to add a row or a column, and then click the plus sign. Reading is easier, too, in the new Reading view. You can collapse parts of the document and focus on the text you want. If you need to stop reading before you reach the end, Word remembers where you left off - even on another device. Video provides a powerful way to help you prove your point. When you click Online Video, you can paste in the embed code for the video you want to add. You can also type a keyword to search online for the video that best fits your document. To make your document look professionally produced, Word provides header, footer, cover page, and text box designs that complement each other. For example, you can add a matching cover page, header, and sidebar.\n" + + "Click Insert and then choose the elements you want from the different galleries. Themes and styles also help keep your document coordinated. When you click Design and choose a new Theme, the pictures, charts, and SmartArt graphics change to match your new theme. When you apply styles, your headings change to match the new theme. Save time in Word with new buttons that show up where you need them. To change the way a picture fits in your document, click it and a button for layout options appears next to it. When you work on a table, click where you want to add a row or a column, and then click the plus sign. Reading is easier, too, in the new Reading view. You can collapse parts of the document and focus on the text you want. If you need to stop reading before you reach the end, Word remembers where you left off - even on another device.\n" + + "Video provides a powerful way to help you prove your point. When you click Online Video, you can paste in the embed code for the video you want to add. You can also type a keyword to search online for the video that best fits your document. To make your document look professionally produced, Word provides header, footer, cover page, and text box designs that complement each other. For example, you can add a matching cover page, header, and sidebar. Click Insert and then choose the elements you want from the different galleries. Themes and styles also help keep your document coordinated. When you click Design and choose a new Theme, the pictures, charts, and SmartArt graphics change to match your new theme. When you apply styles, your headings change to match the new theme. Save time in Word with new buttons that show up where you need them.\n" + + "To change the way a picture fits in your document, click it and a button for layout options appears next to it. When you work on a table, click where you want to add a row or a column, and then click the plus sign. Reading is easier, too, in the new Reading view. You can collapse parts of the document and focus on the text you want. If you need to stop reading before you reach the end, Word remembers where you left off - even on another device. Video provides a powerful way to help you prove your point. When you click Online Video, you can paste in the embed code for the video you want to add. You can also type a keyword to search online for the video that best fits your document. To make your document look professionally produced, Word provides header, footer, cover page, and text box designs that complement each other. For example, you can add a matching cover page, header, and sidebar.\n" + + "Click Insert and then choose the elements you want from the different galleries. Themes and styles also help keep your document coordinated. When you click Design and choose a new Theme, the pictures, charts, and SmartArt graphics change to match your new theme. When you apply styles, your headings change to match the new theme. Save time in Word with new buttons that show up where you need them. To change the way a picture fits in your document, click it and a button for layout options appears next to it. When you work on a table, click where you want to add a row or a column, and then click the plus sign. Reading is easier, too, in the new Reading view. You can collapse parts of the document and focus on the text you want. If you need to stop reading before you reach the end, Word remembers where you left off - even on another device.\n" + + "Video provides a powerful way to help you prove your point. When you click Online Video, you can paste in the embed code for the video you want to add. You can also type a keyword to search online for the video that best fits your document. To make your document look professionally produced, Word provides header, footer, cover page, and text box designs that complement each other. For example, you can add a matching cover page, header, and sidebar. Click Insert and then choose the elements you want from the different galleries. Themes and styles also help keep your document coordinated. When you click Design and choose a new Theme, the pictures, charts, and SmartArt graphics change to match your new theme. When you apply styles, your headings change to match the new theme. Save time in Word with new buttons that show up where you need them.\n"; + + [NUnit.Framework.TestFixtureSetUp] + public static void BeforeClass() { + CreateDestinationFolder(destinationFolder); + } + + /// + /// + [NUnit.Framework.Test] + public virtual void KeepWithNextTest01() { + String outFileName = destinationFolder + "keepWithNextTest01.pdf"; + String cmpFileName = sourceFolder + "cmp_keepWithNextTest01.pdf"; + PdfDocument pdf = new PdfDocument(new PdfWriter(outFileName)); + Document document = new Document(pdf, PageSize.A4); + for (int i = 0; i < 28; i++) { + document.Add(new Paragraph("dummy")); + } + Paragraph title = new Paragraph("THIS IS THE TITLE OF A CHAPTER THAT FITS A PAGE"); + title.SetKeepWithNext(true); + document.Add(title); + for (int i_1 = 0; i_1 < 20; i_1++) { + document.Add(new Paragraph("content of chapter " + i_1)); + } + document.Close(); + NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFileName, cmpFileName, destinationFolder + , "diff")); + } + + /// + /// + [NUnit.Framework.Test] + public virtual void KeepWithNextTest02() { + String outFileName = destinationFolder + "keepWithNextTest02.pdf"; + String cmpFileName = sourceFolder + "cmp_keepWithNextTest02.pdf"; + PdfDocument pdf = new PdfDocument(new PdfWriter(outFileName)); + Document document = new Document(pdf, PageSize.A4); + for (int i = 0; i < 28; i++) { + document.Add(new Paragraph("dummy")); + } + Paragraph title = new Paragraph("THIS IS THE TITLE OF A CHAPTER THAT FITS A PAGE"); + title.SetKeepWithNext(true); + document.Add(title); + document.Add(new Paragraph(LONG_TEXT)); + document.Close(); + NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFileName, cmpFileName, destinationFolder + , "diff")); + } + + /// + /// + [NUnit.Framework.Test] + public virtual void KeepWithNextTest03() { + String outFileName = destinationFolder + "keepWithNextTest03.pdf"; + String cmpFileName = sourceFolder + "cmp_keepWithNextTest03.pdf"; + PdfDocument pdf = new PdfDocument(new PdfWriter(outFileName)); + Document document = new Document(pdf, PageSize.A4); + for (int i = 0; i < 27; i++) { + document.Add(new Paragraph("dummy")); + } + Paragraph title = new Paragraph("THIS IS THE TITLE OF A CHAPTER THAT FITS A PAGE"); + title.SetKeepWithNext(true); + document.Add(title); + document.Add(new Paragraph(LONG_TEXT)); + document.Close(); + NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFileName, cmpFileName, destinationFolder + , "diff")); + } + + /// + /// + [NUnit.Framework.Test] + public virtual void KeepWithNextTest04() { + String outFileName = destinationFolder + "keepWithNextTest04.pdf"; + String cmpFileName = sourceFolder + "cmp_keepWithNextTest04.pdf"; + PdfDocument pdf = new PdfDocument(new PdfWriter(outFileName)); + Document document = new Document(pdf, PageSize.A4); + for (int i = 0; i < 22; i++) { + document.Add(new Paragraph("dummy")); + } + document.SetProperty(Property.FIRST_LINE_INDENT, 20); + Paragraph title = new Paragraph(MIDDLE_TEXT); + title.SetKeepWithNext(true); + document.Add(title); + document.Add(new Paragraph(LONG_TEXT)); + document.Close(); + NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFileName, cmpFileName, destinationFolder + , "diff")); + } + + /// + /// + [NUnit.Framework.Test] + public virtual void KeepWithNextTest05() { + String outFileName = destinationFolder + "keepWithNextTest05.pdf"; + String cmpFileName = sourceFolder + "cmp_keepWithNextTest05.pdf"; + PdfDocument pdf = new PdfDocument(new PdfWriter(outFileName)); + Document document = new Document(pdf, PageSize.A4); + for (int i = 0; i < 22; i++) { + document.Add(new Paragraph("dummy")); + } + document.SetProperty(Property.FIRST_LINE_INDENT, 20); + Paragraph title = new Paragraph(MIDDLE_TEXT); + title.SetKeepTogether(true); + title.SetKeepWithNext(true); + document.Add(title); + document.Add(new Paragraph(LONG_TEXT)); + document.Close(); + NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFileName, cmpFileName, destinationFolder + , "diff")); + } + + /// + /// + [NUnit.Framework.Test] + public virtual void KeepWithNextTest06() { + String outFileName = destinationFolder + "keepWithNextTest06.pdf"; + String cmpFileName = sourceFolder + "cmp_keepWithNextTest06.pdf"; + PdfDocument pdf = new PdfDocument(new PdfWriter(outFileName)); + Document document = new Document(pdf, PageSize.A4); + document.Add(new Paragraph(LONG_TEXT).SetKeepWithNext(true)); + document.Close(); + NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFileName, cmpFileName, destinationFolder + , "diff")); + } + + /// + /// + [NUnit.Framework.Test] + public virtual void KeepWithNextTest07() { + String outFileName = destinationFolder + "keepWithNextTest07.pdf"; + String cmpFileName = sourceFolder + "cmp_keepWithNextTest07.pdf"; + PdfDocument pdf = new PdfDocument(new PdfWriter(outFileName)); + Document document = new Document(pdf, PageSize.A4); + document.SetProperty(Property.FIRST_LINE_INDENT, 20); + document.Add(new Paragraph(LONG_TEXT).SetKeepWithNext(true)); + document.Add(new Paragraph(LONG_TEXT)); + document.Close(); + NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFileName, cmpFileName, destinationFolder + , "diff")); + } + + /// + /// + [NUnit.Framework.Test] + public virtual void KeepWithNextTest08() { + String outFileName = destinationFolder + "keepWithNextTest08.pdf"; + String cmpFileName = sourceFolder + "cmp_keepWithNextTest08.pdf"; + PdfDocument pdf = new PdfDocument(new PdfWriter(outFileName)); + Document document = new Document(pdf, PageSize.A4); + for (int i = 0; i < 25; i++) { + document.Add(new Paragraph("dummy")); + } + document.Add(new Paragraph("Title").SetFont(PdfFontFactory.CreateFont(FontConstants.HELVETICA_BOLD)).SetKeepWithNext + (true)); + List list = new List(ListNumberingType.DECIMAL); + for (int i_1 = 0; i_1 < 10; i_1++) { + list.Add("item"); + } + list.SetKeepTogether(true); + document.Add(list); + document.Close(); + NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFileName, cmpFileName, destinationFolder + , "diff")); + } + + /// + /// + [NUnit.Framework.Test] + public virtual void KeepWithNextTest09() { + String outFileName = destinationFolder + "keepWithNextTest09.pdf"; + String cmpFileName = sourceFolder + "cmp_keepWithNextTest09.pdf"; + PdfDocument pdf = new PdfDocument(new PdfWriter(outFileName)); + Document document = new Document(pdf, PageSize.A4); + for (int i = 0; i < 28; i++) { + document.Add(new Paragraph("dummy")); + } + document.Add(new Paragraph("Title").SetFontSize(20).SetFont(PdfFontFactory.CreateFont(FontConstants.HELVETICA_BOLD + )).SetKeepWithNext(true)); + List list = new List(ListNumberingType.DECIMAL); + for (int i_1 = 0; i_1 < 10; i_1++) { + list.Add("item"); + } + document.Add(list); + document.Close(); + NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFileName, cmpFileName, destinationFolder + , "diff")); + } + + /// + /// + [NUnit.Framework.Test] + public virtual void KeepWithNextTest10() { + String outFileName = destinationFolder + "keepWithNextTest10.pdf"; + String cmpFileName = sourceFolder + "cmp_keepWithNextTest10.pdf"; + PdfDocument pdf = new PdfDocument(new PdfWriter(outFileName)); + Document document = new Document(pdf, PageSize.A4); + for (int i = 0; i < 25; i++) { + document.Add(new Paragraph("dummy")); + } + document.Add(new Paragraph("Title").SetFont(PdfFontFactory.CreateFont(FontConstants.HELVETICA_BOLD)).SetKeepWithNext + (true)); + List list = new List(ListNumberingType.DECIMAL); + for (int i_1 = 0; i_1 < 10; i_1++) { + list.Add("item"); + } + document.Add(list); + document.Close(); + NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFileName, cmpFileName, destinationFolder + , "diff")); + } + } +} diff --git a/itext.tests/itext.layout.tests/itext/layout/LargeElementTest.cs b/itext.tests/itext.layout.tests/itext/layout/LargeElementTest.cs index 117b28225a..7c3ad797eb 100644 --- a/itext.tests/itext.layout.tests/itext/layout/LargeElementTest.cs +++ b/itext.tests/itext.layout.tests/itext/layout/LargeElementTest.cs @@ -1,5 +1,4 @@ using System; -using System.IO; using iText.Kernel.Geom; using iText.Kernel.Pdf; using iText.Kernel.Utils; @@ -25,9 +24,7 @@ public virtual void LargeTableTest01() { String testName = "largeTableTest01.pdf"; String outFileName = destinationFolder + testName; String cmpFileName = sourceFolder + "cmp_" + testName; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); Document doc = new Document(pdfDoc); Table table = new Table(5, true); doc.Add(table); @@ -54,9 +51,7 @@ public virtual void LargeTableTest02() { String testName = "largeTableTest02.pdf"; String outFileName = destinationFolder + testName; String cmpFileName = sourceFolder + "cmp_" + testName; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); Document doc = new Document(pdfDoc); Table table = new Table(5, true).SetMargins(20, 20, 20, 20); doc.Add(table); @@ -79,9 +74,7 @@ public virtual void LargeTableWithHeaderFooterTest01A() { String testName = "largeTableWithHeaderFooterTest01A.pdf"; String outFileName = destinationFolder + testName; String cmpFileName = sourceFolder + "cmp_" + testName; - FileStream fos = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); Document doc = new Document(pdfDoc, PageSize.A4.Rotate()); Table table = new Table(5, true); doc.Add(table); @@ -108,9 +101,7 @@ public virtual void LargeTableWithHeaderFooterTest01B() { String testName = "largeTableWithHeaderFooterTest01B.pdf"; String outFileName = destinationFolder + testName; String cmpFileName = sourceFolder + "cmp_" + testName; - FileStream fos = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); Document doc = new Document(pdfDoc, PageSize.A4.Rotate()); Table table = new Table(5, true); doc.Add(table); @@ -140,9 +131,7 @@ public virtual void LargeTableWithHeaderFooterTest02() { String testName = "largeTableWithHeaderFooterTest02.pdf"; String outFileName = destinationFolder + testName; String cmpFileName = sourceFolder + "cmp_" + testName; - FileStream fos = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); Document doc = new Document(pdfDoc, PageSize.A4.Rotate()); Table table = new Table(5, true); doc.Add(table); @@ -171,9 +160,7 @@ public virtual void LargeTableWithHeaderFooterTest03() { String testName = "largeTableWithHeaderFooterTest03.pdf"; String outFileName = destinationFolder + testName; String cmpFileName = sourceFolder + "cmp_" + testName; - FileStream fos = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); Document doc = new Document(pdfDoc, PageSize.A4.Rotate()); Table table = new Table(5, true); doc.Add(table); @@ -202,9 +189,7 @@ public virtual void LargeTableWithHeaderFooterTest04() { String testName = "largeTableWithHeaderFooterTest04.pdf"; String outFileName = destinationFolder + testName; String cmpFileName = sourceFolder + "cmp_" + testName; - FileStream fos = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(fos); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); Document doc = new Document(pdfDoc, PageSize.A4.Rotate()); Table table = new Table(5, true); doc.Add(table); diff --git a/itext.tests/itext.layout.tests/itext/layout/LineSeparatorTest.cs b/itext.tests/itext.layout.tests/itext/layout/LineSeparatorTest.cs new file mode 100644 index 0000000000..05e5e49766 --- /dev/null +++ b/itext.tests/itext.layout.tests/itext/layout/LineSeparatorTest.cs @@ -0,0 +1,90 @@ +using System; +using iText.Kernel.Colors; +using iText.Kernel.Pdf; +using iText.Kernel.Pdf.Canvas.Draw; +using iText.Kernel.Utils; +using iText.Layout.Element; +using iText.Layout.Properties; +using iText.Test; + +namespace iText.Layout { + public class LineSeparatorTest : ExtendedITextTest { + public static readonly String sourceFolder = NUnit.Framework.TestContext.CurrentContext.TestDirectory + "/../../resources/itext/layout/LineSeparatorTest/"; + + public static readonly String destinationFolder = NUnit.Framework.TestContext.CurrentContext.TestDirectory + + "/test/itext/layout/LineSeparatorTest/"; + + [NUnit.Framework.TestFixtureSetUp] + public static void BeforeClass() { + CreateDestinationFolder(destinationFolder); + } + + /// + /// + [NUnit.Framework.Test] + public virtual void LineSeparatorWidthPercentageTest01() { + String outFileName = destinationFolder + "lineSeparatorWidthPercentageTest01.pdf"; + String cmpFileName = sourceFolder + "cmp_lineSeparatorWidthPercentageTest01.pdf"; + PdfDocument pdf = new PdfDocument(new PdfWriter(outFileName)); + Document document = new Document(pdf); + ILineDrawer line1 = new SolidLine(); + line1.SetColor(Color.RED); + ILineDrawer line2 = new SolidLine(); + document.Add(new LineSeparator(line1).SetWidth(50).SetMarginBottom(10)); + document.Add(new LineSeparator(line2).SetWidthPercent(50)); + document.Close(); + NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFileName, cmpFileName, destinationFolder + , "diff")); + } + + /// + /// + [NUnit.Framework.Test] + public virtual void LineSeparatorBackgroundTest01() { + String outFileName = destinationFolder + "lineSeparatorBackgroundTest01.pdf"; + String cmpFileName = sourceFolder + "cmp_lineSeparatorBackgroundTest01.pdf"; + PdfDocument pdf = new PdfDocument(new PdfWriter(outFileName)); + Document document = new Document(pdf); + Style style = new Style(); + style.SetBackgroundColor(Color.YELLOW); + style.SetMargin(10); + document.Add(new LineSeparator(new SolidLine()).AddStyle(style)); + document.Add(new LineSeparator(new DashedLine()).SetBackgroundColor(Color.RED)); + document.Close(); + NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFileName, cmpFileName, destinationFolder + , "diff")); + } + + /// + /// + [NUnit.Framework.Test] + public virtual void RotatedLineSeparatorTest01() { + String outFileName = destinationFolder + "rotatedLineSeparatorTest01.pdf"; + String cmpFileName = sourceFolder + "cmp_rotatedLineSeparatorTest01.pdf"; + PdfDocument pdf = new PdfDocument(new PdfWriter(outFileName)); + Document document = new Document(pdf); + document.Add(new LineSeparator(new DashedLine()).SetBackgroundColor(Color.RED).SetRotationAngle(Math.PI / + 2)); + document.Close(); + NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFileName, cmpFileName, destinationFolder + , "diff")); + } + + /// + /// + [NUnit.Framework.Test] + public virtual void RotatedLineSeparatorTest02() { + String outFileName = destinationFolder + "rotatedLineSeparatorTest02.pdf"; + String cmpFileName = sourceFolder + "cmp_rotatedLineSeparatorTest02.pdf"; + PdfDocument pdf = new PdfDocument(new PdfWriter(outFileName)); + Document document = new Document(pdf); + document.Add(new Paragraph("Hello")); + document.Add(new LineSeparator(new DashedLine()).SetWidth(100).SetHorizontalAlignment(HorizontalAlignment. + CENTER).SetBackgroundColor(Color.GREEN).SetRotationAngle(Math.PI / 4)); + document.Add(new Paragraph("World")); + document.Close(); + NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFileName, cmpFileName, destinationFolder + , "diff")); + } + } +} diff --git a/itext.tests/itext.layout.tests/itext/layout/LinkTest.cs b/itext.tests/itext.layout.tests/itext/layout/LinkTest.cs index 379d34dcbd..2efaf51e6d 100644 --- a/itext.tests/itext.layout.tests/itext/layout/LinkTest.cs +++ b/itext.tests/itext.layout.tests/itext/layout/LinkTest.cs @@ -1,11 +1,15 @@ using System; using System.IO; +using iText.IO; +using iText.Kernel.Colors; using iText.Kernel.Pdf; using iText.Kernel.Pdf.Action; using iText.Kernel.Pdf.Navigation; using iText.Kernel.Utils; +using iText.Layout.Borders; using iText.Layout.Element; using iText.Test; +using iText.Test.Attributes; namespace iText.Layout { public class LinkTest : ExtendedITextTest { @@ -25,9 +29,7 @@ public static void BeforeClass() { public virtual void LinkTest01() { String outFileName = destinationFolder + "linkTest01.pdf"; String cmpFileName = sourceFolder + "cmp_linkTest01.pdf"; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); Document doc = new Document(pdfDoc); PdfAction action = PdfAction.CreateURI("http://itextpdf.com/", false); Link link = new Link("TestLink", action); @@ -43,9 +45,7 @@ public virtual void LinkTest01() { public virtual void LinkTest02() { String outFileName = destinationFolder + "linkTest02.pdf"; String cmpFileName = sourceFolder + "cmp_linkTest02.pdf"; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); Document doc = new Document(pdfDoc); doc.Add(new AreaBreak()).Add(new AreaBreak()); PdfArray array = new PdfArray(); @@ -62,5 +62,91 @@ public virtual void LinkTest02() { NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFileName, cmpFileName, destinationFolder , "diff")); } + + /// + /// + [NUnit.Framework.Test] + public virtual void BorderedLinkTest() { + String outFileName = destinationFolder + "borderedLinkTest.pdf"; + String cmpFileName = sourceFolder + "cmp_borderedLinkTest.pdf"; + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + Document doc = new Document(pdfDoc); + Link link = new Link("Link with orange border", PdfAction.CreateURI("http://itextpdf.com")); + link.SetBorder(new SolidBorder(Color.ORANGE, 5)); + doc.Add(new Paragraph(link)); + doc.Close(); + NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFileName, cmpFileName, destinationFolder + , "diff")); + } + + /// + /// + /// Stack overflow: Create local link in rotated PdfPCell in iTextSharp + /// + ///

+ /// This is the equivalent Java code for iText 7 of the C# code for iTextSharp 5 + /// in the question. + ///

+ /// + /// + /// Stack overflow: Create local link in rotated PdfPCell in iTextSharp + /// + ///

+ /// This is the equivalent Java code for iText 7 of the C# code for iTextSharp 5 + /// in the question. + ///

+ /// Author: mkl. + ///
+ /// + /// + [NUnit.Framework.Test] + public virtual void TestCreateLocalLinkInRotatedCell() { + String outFileName = destinationFolder + "linkInRotatedCell.pdf"; + String cmpFileName = sourceFolder + "cmp_linkInRotatedCell.pdf"; + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); + Document document = new Document(pdfDocument); + Table table = new Table(2); + Link chunk = new Link("Click here", PdfAction.CreateURI("http://itextpdf.com/")); + table.AddCell(new Cell().Add(new Paragraph().Add(chunk)).SetRotationAngle(Math.PI / 2)); + chunk = new Link("Click here 2", PdfAction.CreateURI("http://itextpdf.com/")); + table.AddCell(new Paragraph().Add(chunk)); + document.Add(table); + document.Close(); + NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFileName, cmpFileName, destinationFolder + , "diff")); + } + + /// + /// + [NUnit.Framework.Test] + public virtual void RotatedLinkAtFixedPosition() { + String outFileName = destinationFolder + "rotatedLinkAtFixedPosition.pdf"; + String cmpFileName = sourceFolder + "cmp_rotatedLinkAtFixedPosition.pdf"; + Document doc = new Document(new PdfDocument(new PdfWriter(outFileName))); + PdfAction action = PdfAction.CreateURI("http://itextpdf.com/", false); + Link link = new Link("TestLink", action); + doc.Add(new Paragraph(link).SetRotationAngle(Math.PI / 4).SetFixedPosition(300, 623, 100)); + doc.Close(); + NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFileName, cmpFileName, destinationFolder + , "diff")); + } + + /// + /// + [LogMessage(LogMessageConstant.ELEMENT_DOES_NOT_FIT_AREA)] + [NUnit.Framework.Test] + public virtual void RotatedLinkInnerRotation() { + String outFileName = destinationFolder + "rotatedLinkInnerRotation.pdf"; + String cmpFileName = sourceFolder + "cmp_rotatedLinkInnerRotation.pdf"; + Document doc = new Document(new PdfDocument(new PdfWriter(outFileName))); + PdfAction action = PdfAction.CreateURI("http://itextpdf.com/", false); + Link link = new Link("TestLink", action); + Paragraph p = new Paragraph(link).SetRotationAngle(Math.PI / 4).SetBackgroundColor(Color.RED); + Div div = new Div().Add(p).SetRotationAngle(Math.PI / 3).SetBackgroundColor(Color.BLUE); + doc.Add(div); + doc.Close(); + NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFileName, cmpFileName, destinationFolder + , "diff")); + } } } diff --git a/itext.tests/itext.layout.tests/itext/layout/ListTest.cs b/itext.tests/itext.layout.tests/itext/layout/ListTest.cs index 87a5e9f3b4..08828bb488 100644 --- a/itext.tests/itext.layout.tests/itext/layout/ListTest.cs +++ b/itext.tests/itext.layout.tests/itext/layout/ListTest.cs @@ -1,14 +1,16 @@ using System; using System.Collections.Generic; -using System.IO; +using iText.IO; using iText.IO.Image; using iText.Kernel.Colors; +using iText.Kernel.Geom; using iText.Kernel.Pdf; using iText.Kernel.Pdf.Xobject; using iText.Kernel.Utils; using iText.Layout.Element; using iText.Layout.Properties; using iText.Test; +using iText.Test.Attributes; namespace iText.Layout { public class ListTest : ExtendedITextTest { @@ -28,7 +30,7 @@ public static void BeforeClass() { public virtual void NestedListTest01() { String outFileName = destinationFolder + "nestedListTest01.pdf"; String cmpFileName = sourceFolder + "cmp_nestedListTest01.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); List romanList2 = new List(ListNumberingType.ROMAN_LOWER).SetSymbolIndent(20).SetMarginLeft(25).Add("One") .Add("Two").Add("Three"); @@ -49,7 +51,7 @@ public virtual void NestedListTest01() { public virtual void ListNumberingTest01() { String outFileName = destinationFolder + "listNumberingTest01.pdf"; String cmpFileName = sourceFolder + "cmp_listNumberingTest01.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); IList lists = new List(); lists.Add(new List(ListNumberingType.DECIMAL)); @@ -72,13 +74,70 @@ public virtual void ListNumberingTest01() { , "diff")); } + /// + /// + [NUnit.Framework.Test] + [LogMessage(LogMessageConstant.ELEMENT_DOES_NOT_FIT_AREA, Count = 8)] + public virtual void AddListOnShortPage1() { + String outFileName = destinationFolder + "addListOnShortPage1.pdf"; + String cmpFileName = sourceFolder + "cmp_addListOnShortPage1.pdf"; + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); + Document doc = new Document(pdfDoc, new PageSize(500, 60)); + ListItem item = new ListItem(); + ListItem nestedItem = new ListItem(); + List list = new List(ListNumberingType.DECIMAL); + List nestedList = new List(ListNumberingType.ENGLISH_UPPER); + List nestedNestedList = new List(ListNumberingType.GREEK_LOWER); + nestedNestedList.Add("Hello"); + nestedNestedList.Add("World"); + nestedItem.Add(nestedNestedList); + nestedList.Add(nestedItem); + nestedList.Add(nestedItem); + item.Add(nestedList); + list.Add(item); + list.Add(item); + doc.Add(list); + doc.Close(); + NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFileName, cmpFileName, destinationFolder + , "diff")); + } + + /// + /// + [NUnit.Framework.Test] + [LogMessage(LogMessageConstant.ELEMENT_DOES_NOT_FIT_AREA, Count = 3)] + public virtual void AddListOnShortPage2() { + String outFileName = destinationFolder + "addListOnShortPage2.pdf"; + String cmpFileName = sourceFolder + "cmp_addListOnShortPage2.pdf"; + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); + Document doc = new Document(pdfDoc, new PageSize(500, 130)); + List list = new List(ListNumberingType.DECIMAL); + ListItem item = new ListItem(); + item.Add(new Paragraph("Red")); + item.Add(new Paragraph("Is")); + item.Add(new Paragraph("The")); + item.Add(new Paragraph("Color")); + item.Add(new Image(ImageDataFactory.Create(sourceFolder + "red.png"))); + List nestedList = new List(ListNumberingType.ENGLISH_UPPER); + nestedList.Add("Hello"); + nestedList.Add("World"); + item.Add(nestedList); + for (int i = 0; i < 3; i++) { + list.Add(item); + } + doc.Add(list); + doc.Close(); + NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFileName, cmpFileName, destinationFolder + , "diff")); + } + /// /// [NUnit.Framework.Test] public virtual void DivInListItemTest01() { String outFileName = destinationFolder + "divInListItemTest01.pdf"; String cmpFileName = sourceFolder + "cmp_divInListItemTest01.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); ListItem item = new ListItem(); item.Add(new Div().Add(new Paragraph("text"))); @@ -94,7 +153,7 @@ public virtual void DivInListItemTest01() { public virtual void ListOverflowTest01() { String outFileName = destinationFolder + "listOverflowTest01.pdf"; String cmpFileName = sourceFolder + "cmp_listOverflowTest01.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); Paragraph p = new Paragraph("Test String"); List list = new List(ListNumberingType.DECIMAL).Add("first string").Add("second string").Add("third string" @@ -114,7 +173,7 @@ public virtual void ListOverflowTest01() { public virtual void ListOverflowTest02() { String outFileName = destinationFolder + "listOverflowTest02.pdf"; String cmpFileName = sourceFolder + "cmp_listOverflowTest02.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); Paragraph p = new Paragraph("Test String"); List list = new List(ListNumberingType.DECIMAL).Add("first string"); @@ -135,7 +194,7 @@ public virtual void ListOverflowTest02() { public virtual void ListOverflowTest03() { String outFileName = destinationFolder + "listOverflowTest03.pdf"; String cmpFileName = sourceFolder + "cmp_listOverflowTest03.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); Paragraph p = new Paragraph("Test String"); List list = new List(ListNumberingType.DECIMAL).SetItemStartIndex(10).Add("first string").Add("second string" @@ -155,7 +214,7 @@ public virtual void ListOverflowTest03() { public virtual void ListEmptyItemTest01() { String outFileName = destinationFolder + "listEmptyItemTest01.pdf"; String cmpFileName = sourceFolder + "cmp_listEmptyItemTest01.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); List list = new List(ListNumberingType.GREEK_LOWER); list.Add(new ListItem()).Add(new ListItem()).Add(new ListItem()).Add("123").Add((ListItem)new ListItem().Add @@ -172,7 +231,7 @@ public virtual void ListEmptyItemTest01() { public virtual void ImageInListTest01() { String outFileName = destinationFolder + "imageInListTest01.pdf"; String cmpFileName = sourceFolder + "cmp_imageInListTest01.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); List list = new List(ListNumberingType.GREEK_LOWER); PdfImageXObject xObject = new PdfImageXObject(ImageDataFactory.Create(sourceFolder + "Desert.jpg")); @@ -191,7 +250,7 @@ public virtual void ImageInListTest01() { public virtual void ListItemAlignmentTest01() { String outFileName = destinationFolder + "listItemAlignmentTest01.pdf"; String cmpFileName = sourceFolder + "cmp_listItemAlignmentTest01.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); List list = new List(ListNumberingType.DECIMAL).SetListSymbolAlignment(ListSymbolAlignment.LEFT); for (int i = 1; i <= 30; i++) { diff --git a/itext.tests/itext.layout.tests/itext/layout/OverflowTest.cs b/itext.tests/itext.layout.tests/itext/layout/OverflowTest.cs index 22a0d1ecce..94ed3b30d1 100644 --- a/itext.tests/itext.layout.tests/itext/layout/OverflowTest.cs +++ b/itext.tests/itext.layout.tests/itext/layout/OverflowTest.cs @@ -1,5 +1,4 @@ using System; -using System.IO; using System.Text; using iText.IO.Font; using iText.Kernel.Colors; @@ -27,7 +26,7 @@ public static void BeforeClass() { public virtual void TextOverflowTest01() { String outFileName = destinationFolder + "textOverflowTest01.pdf"; String cmpFileName = sourceFolder + "cmp_textOverflowTest01.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); StringBuilder text = new StringBuilder(); for (int i = 0; i < 1000; i++) { @@ -46,7 +45,7 @@ public virtual void TextOverflowTest01() { public virtual void TextOverflowTest02() { String outFileName = destinationFolder + "textOverflowTest02.pdf"; String cmpFileName = sourceFolder + "cmp_textOverflowTest02.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); iText.Layout.Element.Text overflowText = new iText.Layout.Element.Text("This is a long-long and large text which will not overflow" ).SetFontSize(19).SetFontColor(Color.RED); @@ -64,7 +63,7 @@ public virtual void TextOverflowTest02() { public virtual void TextOverflowTest03() { String outFileName = destinationFolder + "textOverflowTest03.pdf"; String cmpFileName = sourceFolder + "cmp_textOverflowTest03.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); iText.Layout.Element.Text overflowText = new iText.Layout.Element.Text("This is a long-long and large text which will overflow" ).SetFontSize(25).SetFontColor(Color.RED); @@ -82,7 +81,7 @@ public virtual void TextOverflowTest03() { public virtual void TextOverflowTest04() { String outFileName = destinationFolder + "textOverflowTest04.pdf"; String cmpFileName = sourceFolder + "cmp_textOverflowTest04.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); document.Add(new Paragraph("ThisIsALongTextWithNoSpacesSoSplittingShouldBeForcedInThisCase").SetFontSize(20 )); diff --git a/itext.tests/itext.layout.tests/itext/layout/PositioningTest.cs b/itext.tests/itext.layout.tests/itext/layout/PositioningTest.cs index 5a9ff7a7d9..f5ab7a6e2d 100644 --- a/itext.tests/itext.layout.tests/itext/layout/PositioningTest.cs +++ b/itext.tests/itext.layout.tests/itext/layout/PositioningTest.cs @@ -1,9 +1,10 @@ using System; -using System.IO; +using iText.IO.Image; using iText.Kernel.Colors; using iText.Kernel.Geom; using iText.Kernel.Pdf; using iText.Kernel.Pdf.Canvas; +using iText.Kernel.Pdf.Xobject; using iText.Kernel.Utils; using iText.Layout.Borders; using iText.Layout.Element; @@ -28,7 +29,7 @@ public static void BeforeClass() { public virtual void RelativePositioningTest01() { String outFileName = destinationFolder + "relativePositioningTest01.pdf"; String cmpFileName = sourceFolder + "cmp_relativePositioningTest01.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); Paragraph p = new Paragraph().SetBorder(new SolidBorder(new DeviceGray(0), 5)).SetWidth(300).SetPaddings(20 , 20, 20, 20).Add("Here is a line of text.").Add(new Text("This part is shifted\n up a bit,").SetRelativePosition @@ -46,7 +47,7 @@ public virtual void RelativePositioningTest01() { public virtual void RelativePositioningTest02() { String outFileName = destinationFolder + "relativePositioningTest02.pdf"; String cmpFileName = sourceFolder + "cmp_relativePositioningTest02.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); Paragraph p = new Paragraph().SetBorder(new SolidBorder(new DeviceGray(0), 5)).SetWidth(180).SetPaddings(20 , 20, 20, 20).Add("Here is a line of text.").Add(new Text("This part is shifted\n up a bit,").SetRelativePosition @@ -64,7 +65,7 @@ public virtual void RelativePositioningTest02() { public virtual void FixedPositioningTest01() { String outFileName = destinationFolder + "fixedPositioningTest01.pdf"; String cmpFileName = sourceFolder + "cmp_fixedPositioningTest01.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); List list = new List(ListNumberingType.ROMAN_UPPER).SetFixedPosition(2, 300, 300, 50).SetBackgroundColor(Color .BLUE).SetHeight(100); @@ -81,7 +82,7 @@ public virtual void FixedPositioningTest01() { public virtual void FixedPositioningTest02() { String outFileName = destinationFolder + "fixedPositioningTest02.pdf"; String cmpFileName = sourceFolder + "cmp_fixedPositioningTest02.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); document.GetPdfDocument().AddNewPage(); new PdfCanvas(document.GetPdfDocument().GetPage(1)).SetFillColor(Color.BLACK).Rectangle(300, 300, 100, 100 @@ -100,7 +101,7 @@ public virtual void FixedPositioningTest02() { public virtual void ShowTextAlignedTest01() { String outFileName = destinationFolder + "showTextAlignedTest01.pdf"; String cmpFileName = sourceFolder + "cmp_showTextAlignedTest01.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); pdfDocument.AddNewPage(); PdfCanvas canvas = new PdfCanvas(pdfDocument.GetLastPage()); @@ -165,7 +166,7 @@ public virtual void ShowTextAlignedTest01() { public virtual void ShowTextAlignedTest02() { String outFileName = destinationFolder + "showTextAlignedTest02.pdf"; String cmpFileName = sourceFolder + "cmp_showTextAlignedTest02.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); String watermarkText = "WATERMARK"; Paragraph watermark = new Paragraph(watermarkText); @@ -181,6 +182,26 @@ public virtual void ShowTextAlignedTest02() { , "diff")); } + /// + /// + [NUnit.Framework.Test] + public virtual void ShowTextAlignedTest03() { + String outFileName = destinationFolder + "showTextAlignedTest03.pdf"; + String cmpFileName = sourceFolder + "cmp_showTextAlignedTest03.pdf"; + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); + Document doc = new Document(pdfDoc); + iText.Layout.Element.Image img = new Image(ImageDataFactory.Create(sourceFolder + "bruno.jpg")); + float width = img.GetImageScaledWidth(); + float height = img.GetImageScaledHeight(); + PdfFormXObject template = new PdfFormXObject(new Rectangle(width, height)); + iText.Layout.Canvas canvas = new iText.Layout.Canvas(template, pdfDoc); + canvas.Add(img).ShowTextAligned("HELLO BRUNO", width / 2, height / 2, TextAlignment.CENTER); + doc.Add(new iText.Layout.Element.Image(template)); + doc.Close(); + NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFileName, cmpFileName, destinationFolder + , "diff")); + } + private void DrawCross(PdfCanvas canvas, float x, float y) { DrawLine(canvas, x - 50, y, x + 50, y); DrawLine(canvas, x, y - 50, x, y + 50); diff --git a/itext.tests/itext.layout.tests/itext/layout/PreLayoutTest.cs b/itext.tests/itext.layout.tests/itext/layout/PreLayoutTest.cs index 56e45cd953..37dda4ae54 100644 --- a/itext.tests/itext.layout.tests/itext/layout/PreLayoutTest.cs +++ b/itext.tests/itext.layout.tests/itext/layout/PreLayoutTest.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.IO; using System.Text; using iText.IO.Font; using iText.Kernel.Font; @@ -31,7 +30,7 @@ public static void BeforeClass() { public virtual void PreLayoutTest01() { String outFileName = destinationFolder + "preLayoutTest01.pdf"; String cmpFileName = sourceFolder + "cmp_preLayoutTest01.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument, PageSize.Default, false); IList pageNumberTexts = new List(); IList pageNumberRenderers = new List(); @@ -66,7 +65,7 @@ public virtual void PreLayoutTest01() { public virtual void PreLayoutTest02() { String outFileName = destinationFolder + "preLayoutTest02.pdf"; String cmpFileName = sourceFolder + "cmp_preLayoutTest02.pdf"; - PdfDocument pdfDoc = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDoc, PageSize.Default, false); document.Add(new Paragraph("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")); StringBuilder text = new StringBuilder(); diff --git a/itext.tests/itext.layout.tests/itext/layout/RotationTest.cs b/itext.tests/itext.layout.tests/itext/layout/RotationTest.cs index 80841d26ba..e392638d6c 100644 --- a/itext.tests/itext.layout.tests/itext/layout/RotationTest.cs +++ b/itext.tests/itext.layout.tests/itext/layout/RotationTest.cs @@ -1,5 +1,4 @@ using System; -using System.IO; using iText.IO; using iText.Kernel.Colors; using iText.Kernel.Geom; @@ -46,7 +45,7 @@ public static void BeforeClass() { public virtual void FixedTextRotationTest01() { String outFileName = destinationFolder + "fixedTextRotationTest01.pdf"; String cmpFileName = sourceFolder + cmpPrefix + "fixedTextRotationTest01.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); SolidBorder border = new SolidBorder(0.5f); int x1 = 350; @@ -73,7 +72,7 @@ public virtual void FixedTextRotationTest01() { public virtual void FixedTextRotationTest02() { String outFileName = destinationFolder + "fixedTextRotationTest02.pdf"; String cmpFileName = sourceFolder + cmpPrefix + "fixedTextRotationTest02.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); String longText = "loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo" + "ooooooooooooooooooooooooooooooooooooooooooooooooooooooooong text"; @@ -90,7 +89,7 @@ public virtual void FixedTextRotationTest02() { public virtual void FixedTextRotationTest03() { String outFileName = destinationFolder + "fixedTextRotationTest03.pdf"; String cmpFileName = sourceFolder + cmpPrefix + "fixedTextRotationTest03.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); String simpleText = "text simple text"; float x = 50; @@ -111,7 +110,7 @@ public virtual void FixedTextRotationTest03() { public virtual void FixedTextRotationTest04() { String outFileName = destinationFolder + "fixedTextRotationTest04.pdf"; String cmpFileName = sourceFolder + cmpPrefix + "fixedTextRotationTest04.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); String simpleText = "text simple text"; float x = 50; @@ -128,18 +127,19 @@ public virtual void FixedTextRotationTest04() { /// /// + [LogMessage(LogMessageConstant.ELEMENT_DOES_NOT_FIT_AREA)] [NUnit.Framework.Test] public virtual void StaticTextRotationTest01() { String outFileName = destinationFolder + "staticTextRotationTest01.pdf"; String cmpFileName = sourceFolder + cmpPrefix + "staticTextRotationTest01.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); Paragraph p = new Paragraph(); for (int i = 0; i < 7; ++i) { p.Add(para2Text); } document.Add(p.SetRotationAngle((68 * Math.PI / 180)).SetBackgroundColor(Color.BLUE)); - document.Add(new Paragraph("text line text line text line text line text line text line text line text line text line text line text line text line text line" + document.Add(new Paragraph("text line text line text line text line text line text line text line text line text line text line text line" )); document.Close(); NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFileName, cmpFileName, destinationFolder @@ -148,11 +148,12 @@ public virtual void StaticTextRotationTest01() { /// /// + [LogMessage(LogMessageConstant.ELEMENT_DOES_NOT_FIT_AREA, Count = 2)] [NUnit.Framework.Test] public virtual void StaticTextRotationTest02() { String outFileName = destinationFolder + "staticTextRotationTest02.pdf"; String cmpFileName = sourceFolder + cmpPrefix + "staticTextRotationTest02.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); document.Add(new Paragraph(para1Text)); document.Add(new Paragraph(para2Text).SetRotationAngle((Math.PI / 12))); @@ -170,7 +171,7 @@ public virtual void StaticTextRotationTest02() { public virtual void StaticTextRotationTest03() { String outFileName = destinationFolder + "staticTextRotationTest03.pdf"; String cmpFileName = sourceFolder + cmpPrefix + "staticTextRotationTest03.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); document.Add(new Paragraph(para1Text)); document.Add(new Paragraph(para2Text).SetRotationAngle((Math.PI / 6)).SetBackgroundColor(Color.RED)); @@ -187,7 +188,7 @@ public virtual void StaticTextRotationTest03() { public virtual void StaticTextRotationTest04() { String outFileName = destinationFolder + "staticTextRotationTest04.pdf"; String cmpFileName = sourceFolder + cmpPrefix + "staticTextRotationTest04.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); document.Add(new Paragraph(para1Text)); document.Add(new Paragraph("short text string").SetRotationAngle((Math.PI / 6)).SetBackgroundColor(Color.RED @@ -204,7 +205,7 @@ public virtual void StaticTextRotationTest04() { public virtual void SplitTextRotationTest01() { String outFileName = destinationFolder + "splitTextRotationTest01.pdf"; String cmpFileName = sourceFolder + cmpPrefix + "splitTextRotationTest01.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); document.Add(new Paragraph(para1Text)); document.Add(new Paragraph(para1Text).SetRotationAngle((Math.PI / 4))); @@ -218,11 +219,12 @@ public virtual void SplitTextRotationTest01() { /// /// + [LogMessage(LogMessageConstant.ELEMENT_DOES_NOT_FIT_AREA, Count = 2)] [NUnit.Framework.Test] public virtual void SplitTextRotationTest02() { String outFileName = destinationFolder + "splitTextRotationTest02.pdf"; String cmpFileName = sourceFolder + cmpPrefix + "splitTextRotationTest02.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); document.Add(new Paragraph(para1Text)); document.Add(new Paragraph(para1Text)); @@ -240,12 +242,13 @@ public virtual void SplitTextRotationTest02() { /// /// + [LogMessage(LogMessageConstant.ELEMENT_DOES_NOT_FIT_AREA)] [NUnit.Framework.Test] public virtual void RotationInfiniteLoopTest01() { String fileName = "rotationInfiniteLoopTest01.pdf"; String outFileName = destinationFolder + fileName; String cmpFileName = sourceFolder + cmpPrefix + fileName; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); pdfDocument.SetDefaultPageSize(PageSize.A5.Rotate()); Document document = new Document(pdfDocument); document.Add(new Paragraph(para1Text).SetRotationAngle((Math.PI / 2))); @@ -256,13 +259,13 @@ public virtual void RotationInfiniteLoopTest01() { /// /// - [LogMessage(LogMessageConstant.ELEMENT_DOES_NOT_FIT_AREA, Count = 1)] + [LogMessage(LogMessageConstant.ELEMENT_DOES_NOT_FIT_AREA)] [NUnit.Framework.Test] public virtual void RotationInfiniteLoopTest02() { String fileName = "rotationInfiniteLoopTest02.pdf"; String outFileName = destinationFolder + fileName; String cmpFileName = sourceFolder + cmpPrefix + fileName; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); pdfDocument.SetDefaultPageSize(PageSize.A5.Rotate()); Document document = new Document(pdfDocument); document.Add(new List().Add(para1Text).SetRotationAngle((Math.PI / 2))); @@ -277,9 +280,7 @@ public virtual void RotationInfiniteLoopTest02() { public virtual void TableRotationTest02() { String outFileName = destinationFolder + "tableRotationTest02.pdf"; String cmpFileName = sourceFolder + cmpPrefix + "tableRotationTest02.pdf"; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); Document doc = new Document(pdfDoc); Table table = new Table(new float[] { 50, 50 }).AddCell(new Cell().Add(new Paragraph("cell 1, 1").SetRotationAngle ((Math.PI / 2)))).AddCell(new Cell().Add(new Paragraph("cell 1, 2").SetRotationAngle((Math.PI / 3)))). @@ -291,15 +292,49 @@ public virtual void TableRotationTest02() { , "diff")); } + /// + /// + [LogMessage(LogMessageConstant.ELEMENT_DOES_NOT_FIT_AREA, Count = 2)] + [NUnit.Framework.Test] + public virtual void TableRotationTest03() { + String outFileName = destinationFolder + "tableRotationTest03.pdf"; + String cmpFileName = sourceFolder + cmpPrefix + "tableRotationTest03.pdf"; + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); + Document doc = new Document(pdfDoc); + Table table = new Table(new float[] { 25, 50 }).AddCell(new Cell().Add(new Paragraph("cell 1, 1").SetRotationAngle + ((Math.PI / 2)))).AddCell(new Cell().Add(new Paragraph("cell 1, 2").SetRotationAngle((Math.PI / 3)))). + AddCell(new Cell().Add(new Paragraph("cell 2, 1"))).AddCell(new Cell().Add(new Paragraph("cell 2, 2")) + ).AddCell(new Cell().Add(new Paragraph("cell 3, 1").SetRotationAngle(-(Math.PI / 2)))).AddCell(new Cell + ().Add(new Paragraph("cell 3, 2").SetRotationAngle((Math.PI)))); + doc.Add(table); + doc.Close(); + NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFileName, cmpFileName, destinationFolder + , "diff")); + } + + /// + /// + [NUnit.Framework.Test] + public virtual void CellRotationTest01() { + String outFileName = destinationFolder + "cellRotationTest01.pdf"; + String cmpFileName = sourceFolder + cmpPrefix + "cellRotationTest01.pdf"; + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); + Document doc = new Document(pdfDoc); + Table table = new Table(1).SetWidth(50).AddCell(new Cell().Add(new Paragraph("Hello")).SetRotationAngle(Math + .PI * 70 / 180.0).SetBackgroundColor(Color.GREEN)); + doc.Add(table); + doc.Close(); + NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFileName, cmpFileName, destinationFolder + , "diff")); + } + /// /// [NUnit.Framework.Test] public virtual void DivRotationTest01() { String outFileName = destinationFolder + "divRotationTest01.pdf"; String cmpFileName = sourceFolder + cmpPrefix + "divRotationTest01.pdf"; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); Document doc = new Document(pdfDoc); Div div = new Div().SetBackgroundColor(Color.GREEN); div.Add(new Paragraph(para1Text).SetBackgroundColor(Color.RED)).SetRotationAngle(Math.PI / 4); @@ -314,14 +349,12 @@ public virtual void DivRotationTest01() { /// /// - [LogMessage(LogMessageConstant.ELEMENT_DOES_NOT_FIT_AREA, Count = 1)] + [LogMessage(LogMessageConstant.ELEMENT_DOES_NOT_FIT_AREA, Count = 2)] [NUnit.Framework.Test] public virtual void DivRotationTest02() { String outFileName = destinationFolder + "divRotationTest02.pdf"; String cmpFileName = sourceFolder + cmpPrefix + "divRotationTest02.pdf"; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); Document doc = new Document(pdfDoc); doc.Add(new Paragraph(para1Text)); doc.Add(new Paragraph(para1Text)); @@ -343,9 +376,7 @@ public virtual void DivRotationTest02() { public virtual void ListRotationTest01() { String outFileName = destinationFolder + "listRotationTest01.pdf"; String cmpFileName = sourceFolder + cmpPrefix + "listRotationTest01.pdf"; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); Document doc = new Document(pdfDoc); doc.Add(new Paragraph(para1Text)); List list = new List().SetRotationAngle(3 * Math.PI / 4).SetBackgroundColor(Color.GREEN); @@ -365,9 +396,7 @@ public virtual void ListRotationTest01() { public virtual void ListRotationTest02() { String outFileName = destinationFolder + "listRotationTest02.pdf"; String cmpFileName = sourceFolder + cmpPrefix + "listRotationTest02.pdf"; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); Document doc = new Document(pdfDoc); doc.Add(new Paragraph(para1Text)); doc.Add(new Paragraph(para1Text)); @@ -390,9 +419,7 @@ public virtual void ListRotationTest02() { public virtual void AlignedTextRotationTest01() { String outFileName = destinationFolder + "alignedTextRotationTest01.pdf"; String cmpFileName = sourceFolder + cmpPrefix + "alignedTextRotationTest01.pdf"; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); Document doc = new Document(pdfDoc); doc.Add(new Paragraph(para1Text)); Paragraph p = new Paragraph(); @@ -412,9 +439,7 @@ public virtual void AlignedTextRotationTest01() { public virtual void InnerRotationTest01() { String outFileName = destinationFolder + "innerRotationTest01.pdf"; String cmpFileName = sourceFolder + cmpPrefix + "innerRotationTest01.pdf"; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); Document doc = new Document(pdfDoc); doc.Add(new Div().SetBackgroundColor(Color.GREEN).SetHeight(300).SetWidth(300).Add(new Div().SetBackgroundColor (Color.RED).SetHeight(100).SetWidth(100).SetRotationAngle(Math.PI / 4)).SetRotationAngle(Math.PI / 8)); @@ -425,14 +450,13 @@ public virtual void InnerRotationTest01() { /// /// + [LogMessage(LogMessageConstant.ELEMENT_DOES_NOT_FIT_AREA)] [NUnit.Framework.Test] public virtual void InnerRotationTest02() { String outFileName = destinationFolder + "innerRotationTest02.pdf"; String cmpFileName = sourceFolder + cmpPrefix + "innerRotationTest02.pdf"; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); - PdfDocument pdfDoc = new PdfDocument(writer); - Document doc = new Document(pdfDoc); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); + Document doc = new Document(pdfDoc, new PageSize(6400, 6400)); String longText = para1Text + para2Text + para3Text; String extremeLongText = longText + longText + longText; doc.Add(new Div().SetBackgroundColor(Color.GREEN).SetHeight(300).SetWidth(300).Add(new Div().SetBackgroundColor diff --git a/itext.tests/itext.layout.tests/itext/layout/TableTest.cs b/itext.tests/itext.layout.tests/itext/layout/TableTest.cs index 509a221673..36bcb4e563 100644 --- a/itext.tests/itext.layout.tests/itext/layout/TableTest.cs +++ b/itext.tests/itext.layout.tests/itext/layout/TableTest.cs @@ -1,5 +1,4 @@ using System; -using System.IO; using iText.IO; using iText.IO.Image; using iText.IO.Util; @@ -42,9 +41,7 @@ public virtual void SimpleTableTest01() { String testName = "tableTest01.pdf"; String outFileName = destinationFolder + testName; String cmpFileName = sourceFolder + "cmp_" + testName; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); Document doc = new Document(pdfDoc); Table table = new Table(new float[] { 50, 50 }).AddCell(new Cell().Add(new Paragraph("cell 1, 1"))).AddCell (new Cell().Add(new Paragraph("cell 1, 2"))); @@ -61,9 +58,7 @@ public virtual void SimpleTableTest02() { String testName = "tableTest02.pdf"; String outFileName = destinationFolder + testName; String cmpFileName = sourceFolder + "cmp_" + testName; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); Document doc = new Document(pdfDoc); Table table = new Table(new float[] { 50, 50 }).AddCell(new Cell().Add(new Paragraph("cell 1, 1"))).AddCell (new Cell().Add(new Paragraph("cell 1, 2"))).AddCell(new Cell().Add(new Paragraph("cell 2, 1"))).AddCell @@ -82,9 +77,7 @@ public virtual void SimpleTableTest03() { String testName = "tableTest03.pdf"; String outFileName = destinationFolder + testName; String cmpFileName = sourceFolder + "cmp_" + testName; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); Document doc = new Document(pdfDoc); String textContent1 = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis urna.\n" + "Nunc viverra imperdiet enim. Fusce est. Vivamus a tellus.\n"; @@ -107,9 +100,7 @@ public virtual void SimpleTableTest04() { String testName = "tableTest04.pdf"; String outFileName = destinationFolder + testName; String cmpFileName = sourceFolder + "cmp_" + testName; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); Document doc = new Document(pdfDoc); String textContent = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis urna.\n" + "Nunc viverra imperdiet enim. Fusce est. Vivamus a tellus.\n" + "Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Proin pharetra nonummy pede. Mauris et orci.\n"; @@ -132,9 +123,7 @@ public virtual void SimpleTableTest05() { String testName = "tableTest05.pdf"; String outFileName = destinationFolder + testName; String cmpFileName = sourceFolder + "cmp_" + testName; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); Document doc = new Document(pdfDoc); String textContent = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis urna.\n" + "Nunc viverra imperdiet enim. Fusce est. Vivamus a tellus.\n" + "Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Proin pharetra nonummy pede. Mauris et orci.\n"; @@ -155,9 +144,7 @@ public virtual void SimpleTableTest06() { String testName = "tableTest06.pdf"; String outFileName = destinationFolder + testName; String cmpFileName = sourceFolder + "cmp_" + testName; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); Document doc = new Document(pdfDoc); String textContent = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis urna.\n" + "Nunc viverra imperdiet enim. Fusce est. Vivamus a tellus.\n" + "Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Proin pharetra nonummy pede. Mauris et orci.\n"; @@ -178,9 +165,7 @@ public virtual void SimpleTableTest07() { String testName = "tableTest07.pdf"; String outFileName = destinationFolder + testName; String cmpFileName = sourceFolder + "cmp_" + testName; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); Document doc = new Document(pdfDoc); String textContent = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis urna.\n" + "Nunc viverra imperdiet enim. Fusce est. Vivamus a tellus.\n" + "Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Proin pharetra nonummy pede. Mauris et orci.\n"; @@ -201,9 +186,7 @@ public virtual void SimpleTableTest08() { String testName = "tableTest08.pdf"; String outFileName = destinationFolder + testName; String cmpFileName = sourceFolder + "cmp_" + testName; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); Document doc = new Document(pdfDoc); String textContent = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis urna.\n" + "Nunc viverra imperdiet enim. Fusce est. Vivamus a tellus.\n" + "Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Proin pharetra nonummy pede. Mauris et orci.\n"; @@ -229,9 +212,7 @@ public virtual void SimpleTableTest09() { String testName = "tableTest09.pdf"; String outFileName = destinationFolder + testName; String cmpFileName = sourceFolder + "cmp_" + testName; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); Document doc = new Document(pdfDoc); String textContent = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis urna.\n" + "Nunc viverra imperdiet enim. Fusce est. Vivamus a tellus.\n" + "Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Proin pharetra nonummy pede. Mauris et orci.\n"; @@ -259,9 +240,7 @@ public virtual void SimpleTableTest10() { String testName = "tableTest10.pdf"; String outFileName = destinationFolder + testName; String cmpFileName = sourceFolder + "cmp_" + testName; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); Document doc = new Document(pdfDoc); doc.Add(new Paragraph("Table 1")); Table table = new Table(new float[] { 100, 100 }).AddCell(new Cell().Add(new Paragraph("1, 1"))).AddCell(new @@ -293,9 +272,7 @@ public virtual void SimpleTableTest11() { String testName = "tableTest11.pdf"; String outFileName = destinationFolder + testName; String cmpFileName = sourceFolder + "cmp_" + testName; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); Document doc = new Document(pdfDoc); String shortTextContent = "Nunc viverra imperdiet enim. Fusce est. Vivamus a tellus."; String middleTextContent = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis urna.\n" @@ -325,9 +302,7 @@ public virtual void SimpleTableTest12() { String testName = "tableTest12.pdf"; String outFileName = destinationFolder + testName; String cmpFileName = sourceFolder + "cmp_" + testName; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); Document doc = new Document(pdfDoc); String shortTextContent = "Nunc viverra imperdiet enim. Fusce est. Vivamus a tellus."; String middleTextContent = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis urna.\n" @@ -362,9 +337,7 @@ public virtual void SimpleTableTest13() { String testName = "tableTest13.pdf"; String outFileName = destinationFolder + testName; String cmpFileName = sourceFolder + "cmp_" + testName; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); Document doc = new Document(pdfDoc); String shortTextContent = "Nunc viverra imperdiet enim. Fusce est. Vivamus a tellus."; String middleTextContent = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis urna.\n" @@ -392,9 +365,7 @@ public virtual void SimpleTableTest14() { String testName = "tableTest14.pdf"; String outFileName = destinationFolder + testName; String cmpFileName = sourceFolder + "cmp_" + testName; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); Document doc = new Document(pdfDoc); String textContent = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis urna.\n" + "Nunc viverra imperdiet enim. Fusce est. Vivamus a tellus.\n" + "Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Proin pharetra nonummy pede. Mauris et orci.\n"; @@ -424,9 +395,7 @@ public virtual void SimpleTableTest15() { String testName = "tableTest15.pdf"; String outFileName = destinationFolder + testName; String cmpFileName = sourceFolder + "cmp_" + testName; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); Document doc = new Document(pdfDoc); String textContent = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis urna.\n" + "Nunc viverra imperdiet enim. Fusce est. Vivamus a tellus.\n" + "Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Proin pharetra nonummy pede. Mauris et orci.\n"; @@ -458,9 +427,7 @@ public virtual void SimpleTableTest16() { String testName = "tableTest16.pdf"; String outFileName = destinationFolder + testName; String cmpFileName = sourceFolder + "cmp_" + testName; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); Document doc = new Document(pdfDoc); String textContent = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis urna.\n" + "Nunc viverra imperdiet enim. Fusce est. Vivamus a tellus.\n" + "Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Proin pharetra nonummy pede. Mauris et orci.\n"; @@ -486,9 +453,7 @@ public virtual void SimpleTableTest17() { String testName = "tableTest17.pdf"; String outFileName = destinationFolder + testName; String cmpFileName = sourceFolder + "cmp_" + testName; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); Document doc = new Document(pdfDoc); Table table = new Table(new float[] { 50, 50, 50 }).AddCell(new Cell().Add(new Paragraph("cell 1, 1"))).AddCell (new Cell().Add(new Paragraph("cell 1, 2"))).AddCell(new Cell().Add(new Paragraph("cell 1, 3"))); @@ -513,9 +478,7 @@ public virtual void SimpleTableTest18() { String testName = "tableTest18.pdf"; String outFileName = destinationFolder + testName; String cmpFileName = sourceFolder + "cmp_" + testName; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); Document doc = new Document(pdfDoc); doc.Add(new Paragraph(textContent)); Table table = new Table(new float[] { 50, 50, 50 }).AddCell(new Cell().Add(new Paragraph("cell 1, 1"))).AddCell @@ -541,9 +504,7 @@ public virtual void SimpleTableTest19() { String testName = "tableTest19.pdf"; String outFileName = destinationFolder + testName; String cmpFileName = sourceFolder + "cmp_" + testName; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); Document doc = new Document(pdfDoc); Table table = new Table(new float[] { 130, 130, 260 }).AddCell(new Cell(3, 2).Add(new Paragraph("cell 1:2, 1:3\n" + textContent + textContent))).AddCell(new Cell().Add(new Paragraph("cell 1, 3\n" + textContent))).AddCell @@ -569,9 +530,7 @@ public virtual void SimpleTableTest20() { String testName = "tableTest20.pdf"; String outFileName = destinationFolder + testName; String cmpFileName = sourceFolder + "cmp_" + testName; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); Document doc = new Document(pdfDoc); Table table = new Table(new float[] { 130, 130, 260 }).AddCell(new Cell().Add(new iText.Layout.Element.Image (ImageDataFactory.Create(sourceFolder + "red.png")))).AddCell(new Cell().Add(new Paragraph("cell 4, 2\n" @@ -595,9 +554,7 @@ public virtual void SimpleTableTest21() { String testName = "tableTest21.pdf"; String outFileName = destinationFolder + testName; String cmpFileName = sourceFolder + "cmp_" + testName; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); Document doc = new Document(pdfDoc); String textContent = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis urna.\n" + "Nunc viverra imperdiet enim. Fusce est. Vivamus a tellus.\n" + "Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Proin pharetra nonummy pede. Mauris et orci.\n"; @@ -626,9 +583,7 @@ public virtual void BigRowspanTest01() { String testName = "bigRowspanTest01.pdf"; String outFileName = destinationFolder + testName; String cmpFileName = sourceFolder + "cmp_" + testName; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); Document doc = new Document(pdfDoc); String textContent = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis urna.\n" + "Nunc viverra imperdiet enim. Fusce est. Vivamus a tellus.\n" + "Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Proin pharetra nonummy pede. Mauris et orci.\n"; @@ -654,9 +609,7 @@ public virtual void BigRowspanTest02() { String testName = "bigRowspanTest02.pdf"; String outFileName = destinationFolder + testName; String cmpFileName = sourceFolder + "cmp_" + testName; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); Document doc = new Document(pdfDoc); String textContent = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis urna.\n" + "Nunc viverra imperdiet enim. Fusce est. Vivamus a tellus.\n" + "Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Proin pharetra nonummy pede. Mauris et orci.\n"; @@ -682,9 +635,7 @@ public virtual void BigRowspanTest03() { String testName = "bigRowspanTest03.pdf"; String outFileName = destinationFolder + testName; String cmpFileName = sourceFolder + "cmp_" + testName; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); Document doc = new Document(pdfDoc); String textContent = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis urna.\n" + "Nunc viverra imperdiet enim. Fusce est. Vivamus a tellus.\n" + "Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Proin pharetra nonummy pede. Mauris et orci.\n"; @@ -708,9 +659,7 @@ public virtual void BigRowspanTest04() { String testName = "bigRowspanTest04.pdf"; String outFileName = destinationFolder + testName; String cmpFileName = sourceFolder + "cmp_" + testName; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); Document doc = new Document(pdfDoc); String textContent = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis urna.\n" + "Nunc viverra imperdiet enim. Fusce est. Vivamus a tellus.\n" + "Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Proin pharetra nonummy pede. Mauris et orci.\n"; @@ -736,9 +685,7 @@ public virtual void DifferentPageOrientationTest01() { String testName = "differentPageOrientationTest01.pdf"; String outFileName = destinationFolder + testName; String cmpFileName = sourceFolder + "cmp_" + testName; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); Document doc = new Document(pdfDoc); String textContent1 = "Video provides a powerful way to help you prove your point. When you click Online Video, you can paste in the embed code for the video you want to add. You can also type a keyword to search online for the video that best fits your document."; String textContent2 = "To make your document look professionally produced, Word provides header, footer, cover page, and text box designs that complement each other. For example, you can add a matching cover page, header, and sidebar. Click Insert and then choose the elements you want from the different galleries."; @@ -781,7 +728,7 @@ public virtual void ToLargeElementWithKeepTogetherPropertyInTableTest01() { String testName = "toLargeElementWithKeepTogetherPropertyInTableTest01.pdf"; String outFileName = destinationFolder + testName; String cmpFileName = sourceFolder + "cmp_" + testName; - PdfDocument pdfDoc = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); Document doc = new Document(pdfDoc); Table table = new Table(1); Cell cell = new Cell(); @@ -795,7 +742,7 @@ public virtual void ToLargeElementWithKeepTogetherPropertyInTableTest01() { cell.Add(p); table.AddCell(cell); doc.Add(table); - pdfDoc.Close(); + doc.Close(); NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFileName, cmpFileName, destinationFolder , testName + "_diff")); } @@ -808,8 +755,7 @@ public virtual void ToLargeElementInTableTest01() { String testName = "toLargeElementInTableTest01.pdf"; String outFileName = destinationFolder + testName; String cmpFileName = sourceFolder + "cmp_" + testName; - PdfDocument pdfDoc = new PdfDocument(new PdfWriter(new FileStream(destinationFolder + "toLargeElementInTableTest01.pdf" - , FileMode.Create))); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(destinationFolder + "toLargeElementInTableTest01.pdf")); Document doc = new Document(pdfDoc); Table table = new Table(new float[] { 5 }); Cell cell = new Cell(); @@ -817,7 +763,7 @@ public virtual void ToLargeElementInTableTest01() { cell.Add(p); table.AddCell(cell); doc.Add(table); - pdfDoc.Close(); + doc.Close(); NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFileName, cmpFileName, destinationFolder , testName + "_diff")); } @@ -829,9 +775,7 @@ public virtual void NestedTableSkipHeaderFooterTest() { String testName = "nestedTableSkipHeaderFooter.pdf"; String outFileName = destinationFolder + testName; String cmpFileName = sourceFolder + "cmp_" + testName; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); Document doc = new Document(pdfDoc, PageSize.A4.Rotate()); Table table = new Table(5); table.AddHeaderCell(new Cell(1, 5).Add(new Paragraph("Table XYZ (Continued)"))); @@ -851,26 +795,30 @@ public virtual void NestedTableSkipHeaderFooterTest() { /// /// - [LogMessage(LogMessageConstant.ELEMENT_DOES_NOT_FIT_AREA, Count = 1)] + [LogMessage(LogMessageConstant.ELEMENT_DOES_NOT_FIT_AREA, Count = 9)] [NUnit.Framework.Test] - public virtual void SplitTableOnLowPage() { - String testName = "splitTableOnLowPage.pdf"; + public virtual void SplitTableOnShortPage() { + String testName = "splitTableOnShortPage.pdf"; String outFileName = destinationFolder + testName; String cmpFileName = sourceFolder + "cmp_" + testName; PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); - Document doc = new Document(pdfDoc, new PageSize(300, 120)); + Document doc = new Document(pdfDoc, new PageSize(300, 90)); doc.Add(new Paragraph("Table with setKeepTogether(true):")); - Table table = new Table(2); + Table table = new Table(3); table.SetKeepTogether(true); - table.SetMarginTop(10); Cell cell = new Cell(3, 1); cell.Add("G"); cell.Add("R"); cell.Add("P"); table.AddCell(cell); - table.AddCell("row 1"); - table.AddCell("row 2"); - table.AddCell("row 3"); + table.AddCell("middle row 1"); + cell = new Cell(3, 1); + cell.Add("A"); + cell.Add("B"); + cell.Add("C"); + table.AddCell(cell); + table.AddCell("middle row 2"); + table.AddCell("middle row 3"); doc.Add(table); doc.Add(new AreaBreak()); doc.Add(new Paragraph("Table with setKeepTogether(false):")); @@ -880,5 +828,31 @@ public virtual void SplitTableOnLowPage() { NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFileName, cmpFileName, destinationFolder , testName + "_diff")); } + + /// + /// + [NUnit.Framework.Test] + public virtual void ImageInTableTest_HA() { + String testName = "imageInTableTest_HA.pdf"; + String outFileName = destinationFolder + testName; + String cmpFileName = sourceFolder + "cmp_" + testName; + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); + Document doc = new Document(pdfDoc); + PdfImageXObject xObject = new PdfImageXObject(ImageDataFactory.CreatePng(UrlUtil.ToURL(sourceFolder + "itext.png" + ))); + iText.Layout.Element.Image imageL = new iText.Layout.Element.Image(xObject); + imageL.SetHorizontalAlignment(HorizontalAlignment.LEFT); + iText.Layout.Element.Image imageC = new iText.Layout.Element.Image(xObject); + imageC.SetHorizontalAlignment(HorizontalAlignment.CENTER); + iText.Layout.Element.Image imageR = new iText.Layout.Element.Image(xObject); + imageR.SetHorizontalAlignment(HorizontalAlignment.RIGHT); + doc.Add(new Paragraph("Table")); + Table table = new Table(1).AddCell(new Cell().Add(imageL)).AddCell(new Cell().Add(imageC)).AddCell(new Cell + ().Add(imageR)); + doc.Add(table); + doc.Close(); + NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFileName, cmpFileName, destinationFolder + , testName + "_diff")); + } } } diff --git a/itext.tests/itext.layout.tests/itext/layout/TabsTest.cs b/itext.tests/itext.layout.tests/itext/layout/TabsTest.cs index c547e1c1cb..5d91a66428 100644 --- a/itext.tests/itext.layout.tests/itext/layout/TabsTest.cs +++ b/itext.tests/itext.layout.tests/itext/layout/TabsTest.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.IO; using iText.Kernel.Colors; using iText.Kernel.Geom; using iText.Kernel.Pdf; @@ -48,9 +47,7 @@ public static void BeforeClass() { public virtual void DefaultTabsTest() { String outFileName = destinationFolder + "defaultTabTest.pdf"; String cmpFileName = sourceFolder + "cmp_defaultTabTest.pdf"; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); Document doc = new Document(pdfDoc); Paragraph p = new Paragraph(); AddTabbedTextToParagraph(p, text0, new float[0], null, null, null); @@ -181,9 +178,7 @@ public virtual void SeveralTabsInRowTest() { public virtual void OutOfPageBoundsTest() { String outFileName = destinationFolder + "outOfPageBoundsTest.pdf"; String cmpFileName = sourceFolder + "cmp_outOfPageBoundsTest.pdf"; - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); Document doc = new Document(pdfDoc); //tabstops out of page bounds Paragraph p = new Paragraph(); @@ -231,9 +226,7 @@ public virtual void OutOfPageBoundsTest() { /// private Document InitDocument(String outFileName) { - FileStream file = new FileStream(outFileName, FileMode.Create); - PdfWriter writer = new PdfWriter(file); - PdfDocument pdfDoc = new PdfDocument(writer); + PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName)); pdfDoc.SetDefaultPageSize(PageSize.A4.Rotate()); return new Document(pdfDoc); } diff --git a/itext.tests/itext.layout.tests/itext/layout/TextWritingTest.cs b/itext.tests/itext.layout.tests/itext/layout/TextWritingTest.cs index 2aca074c95..ba91679c0f 100644 --- a/itext.tests/itext.layout.tests/itext/layout/TextWritingTest.cs +++ b/itext.tests/itext.layout.tests/itext/layout/TextWritingTest.cs @@ -1,5 +1,4 @@ using System; -using System.IO; using iText.IO.Font; using iText.Kernel.Colors; using iText.Kernel.Font; @@ -29,7 +28,7 @@ public virtual void TextRiseTest01() { // CountryChunks example String outFileName = destinationFolder + "textRiseTest01.pdf"; String cmpFileName = sourceFolder + "cmp_textRiseTest01.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); PdfFont font = PdfFontFactory.CreateFont(FontConstants.HELVETICA_BOLD); for (int i = 0; i < 10; i++) { @@ -50,7 +49,7 @@ public virtual void TextRiseTest01() { public virtual void TextRenderingModeTest01() { String outFileName = destinationFolder + "textRenderingModeTest01.pdf"; String cmpFileName = sourceFolder + "cmp_textRenderingModeTest01.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); Text text1 = new Text("This is a fill and stroke text").SetTextRenderingMode(PdfCanvasConstants.TextRenderingMode .FILL_STROKE).SetStrokeColor(Color.RED).SetStrokeWidth(0.1f); @@ -73,7 +72,7 @@ public virtual void TextRenderingModeTest01() { public virtual void LeadingTest01() { String outFileName = destinationFolder + "leadingTest01.pdf"; String cmpFileName = sourceFolder + "cmp_leadingTest01.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); Paragraph p1 = new Paragraph("first, leading of 150").SetFixedLeading(150); document.Add(p1); @@ -93,7 +92,7 @@ public virtual void LeadingTest01() { public virtual void FirstLineIndentTest01() { String outFileName = destinationFolder + "firstLineIndentTest01.pdf"; String cmpFileName = sourceFolder + "cmp_firstLineIndentTest01.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); document.SetProperty(Property.FIRST_LINE_INDENT, 25); document.Add(new Paragraph("Portable Document Format (PDF) is a file format used to present documents in a manner " @@ -129,7 +128,7 @@ public virtual void FirstLineIndentTest01() { public virtual void CharSpacingTest01() { String outFileName = destinationFolder + "charSpacingTest01.pdf"; String cmpFileName = sourceFolder + "cmp_charSpacingTest01.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); PdfFont font = PdfFontFactory.CreateFont(FontConstants.HELVETICA); Paragraph p = new Paragraph().SetFont(font); @@ -152,7 +151,7 @@ public virtual void CharSpacingTest01() { public virtual void WordSpacingTest01() { String outFileName = destinationFolder + "wordSpacingTest01.pdf"; String cmpFileName = sourceFolder + "cmp_wordSpacingTest01.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); PdfFont font = PdfFontFactory.CreateFont(FontConstants.HELVETICA); Paragraph p = new Paragraph().SetFont(font); @@ -176,7 +175,7 @@ public virtual void WordSpacingTest01() { public virtual void FontStyleSimulationTest01() { String outFileName = destinationFolder + "fontStyleSimulationTest01.pdf"; String cmpFileName = sourceFolder + "cmp_fontStyleSimulationTest01.pdf"; - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(outFileName, FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName)); Document document = new Document(pdfDocument); document.Add(new Paragraph("I'm underlined").SetUnderline()); document.Add(new Paragraph("I'm strikethrough").SetLineThrough()); diff --git a/itext.tests/itext.layout.tests/itext/layout/XMPWriterTest.cs b/itext.tests/itext.layout.tests/itext/layout/XMPWriterTest.cs index 59ce1c9369..61a61ed06d 100644 --- a/itext.tests/itext.layout.tests/itext/layout/XMPWriterTest.cs +++ b/itext.tests/itext.layout.tests/itext/layout/XMPWriterTest.cs @@ -1,5 +1,4 @@ using System; -using System.IO; using iText.IO.Source; using iText.Kernel.Pdf; using iText.Kernel.Utils; @@ -26,8 +25,7 @@ public static void BeforeClass() { public virtual void CreatePdfTest() { String fileName = "xmp_metadata.pdf"; // step 1 - PdfDocument pdfDocument = new PdfDocument(new PdfWriter(new FileStream(destinationFolder + "xmp_metadata.pdf" - , FileMode.Create))); + PdfDocument pdfDocument = new PdfDocument(new PdfWriter(destinationFolder + "xmp_metadata.pdf")); Document document = new Document(pdfDocument); // step 2 ByteArrayOutputStream os = new ByteArrayOutputStream(); diff --git a/itext.tests/itext.layout.tests/itext/layout/properties/PropertyTest.cs b/itext.tests/itext.layout.tests/itext/layout/properties/PropertyTest.cs index fcb35b033b..f16ae90810 100644 --- a/itext.tests/itext.layout.tests/itext/layout/properties/PropertyTest.cs +++ b/itext.tests/itext.layout.tests/itext/layout/properties/PropertyTest.cs @@ -15,7 +15,7 @@ public virtual void PropertyUniquenessTest() { int value = (int)field.GetValue(null); maxFieldValue = Math.Max(maxFieldValue, value); if (fieldValues.Contains(value)) { - NUnit.Framework.Assert.Fail("Multiple fields with same value"); + NUnit.Framework.Assert.Fail(String.Format("Multiple fields with same value: {0}", value)); } fieldValues.Add(value); } diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/AlignmentTest/cmp_justifyAlignmentTest03.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/AlignmentTest/cmp_justifyAlignmentTest03.pdf index ed37b22f45..81a82ff8ea 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/AlignmentTest/cmp_justifyAlignmentTest03.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/AlignmentTest/cmp_justifyAlignmentTest03.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/AutoTaggingTest/cmp_artifactTest01.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/AutoTaggingTest/cmp_artifactTest01.pdf index 0b4f4d4e34..031545a7b0 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/AutoTaggingTest/cmp_artifactTest01.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/AutoTaggingTest/cmp_artifactTest01.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/AutoTaggingTest/cmp_artifactTest02.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/AutoTaggingTest/cmp_artifactTest02.pdf index b8a41d8ab8..611f937a75 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/AutoTaggingTest/cmp_artifactTest02.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/AutoTaggingTest/cmp_artifactTest02.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/AutoTaggingTest/cmp_flushingTest02.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/AutoTaggingTest/cmp_flushingTest02.pdf index 49b4b8afc0..d6c39faca1 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/AutoTaggingTest/cmp_flushingTest02.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/AutoTaggingTest/cmp_flushingTest02.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/AutoTaggingTest/cmp_flushingTest03.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/AutoTaggingTest/cmp_flushingTest03.pdf index df19027f09..04962da55b 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/AutoTaggingTest/cmp_flushingTest03.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/AutoTaggingTest/cmp_flushingTest03.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/AutoTaggingTest/cmp_tableTest01.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/AutoTaggingTest/cmp_tableTest01.pdf index b113f341c0..5ffc630086 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/AutoTaggingTest/cmp_tableTest01.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/AutoTaggingTest/cmp_tableTest01.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/AutoTaggingTest/cmp_tableTest02.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/AutoTaggingTest/cmp_tableTest02.pdf index 659ee68753..b1364e05ce 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/AutoTaggingTest/cmp_tableTest02.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/AutoTaggingTest/cmp_tableTest02.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/AutoTaggingTest/cmp_tableTest03.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/AutoTaggingTest/cmp_tableTest03.pdf index 7c892ab20f..1f66fe1a45 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/AutoTaggingTest/cmp_tableTest03.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/AutoTaggingTest/cmp_tableTest03.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/AutoTaggingTest/cmp_tableTest04.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/AutoTaggingTest/cmp_tableTest04.pdf index f0193af157..b7054d706f 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/AutoTaggingTest/cmp_tableTest04.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/AutoTaggingTest/cmp_tableTest04.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/AutoTaggingTest/cmp_tableTest05.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/AutoTaggingTest/cmp_tableTest05.pdf index 51ce12e0b7..d79e13da4c 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/AutoTaggingTest/cmp_tableTest05.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/AutoTaggingTest/cmp_tableTest05.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/AutoTaggingTest/cmp_tableTest06.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/AutoTaggingTest/cmp_tableTest06.pdf index 795f1ad061..0d9d43ad3a 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/AutoTaggingTest/cmp_tableTest06.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/AutoTaggingTest/cmp_tableTest06.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/BackgroundColorTest/cmp_simpleBackgroundColorTest.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/BackgroundColorTest/cmp_simpleBackgroundColorTest.pdf new file mode 100644 index 0000000000..dec9202ab9 Binary files /dev/null and b/itext.tests/itext.layout.tests/resources/itext/layout/BackgroundColorTest/cmp_simpleBackgroundColorTest.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/BorderTest/cmp_forcedPlacementTest01.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/BorderTest/cmp_forcedPlacementTest01.pdf new file mode 100644 index 0000000000..cc98f04423 Binary files /dev/null and b/itext.tests/itext.layout.tests/resources/itext/layout/BorderTest/cmp_forcedPlacementTest01.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/BorderTest/cmp_infiniteLoopTest01.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/BorderTest/cmp_infiniteLoopTest01.pdf new file mode 100644 index 0000000000..c705163d76 Binary files /dev/null and b/itext.tests/itext.layout.tests/resources/itext/layout/BorderTest/cmp_infiniteLoopTest01.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/BorderTest/cmp_noHorizontalBorderTest.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/BorderTest/cmp_noHorizontalBorderTest.pdf new file mode 100644 index 0000000000..6f6179e810 Binary files /dev/null and b/itext.tests/itext.layout.tests/resources/itext/layout/BorderTest/cmp_noHorizontalBorderTest.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/BorderTest/cmp_noVerticalBorderTest.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/BorderTest/cmp_noVerticalBorderTest.pdf new file mode 100644 index 0000000000..34954571a9 Binary files /dev/null and b/itext.tests/itext.layout.tests/resources/itext/layout/BorderTest/cmp_noVerticalBorderTest.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/BorderTest/cmp_wideBorderTest01.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/BorderTest/cmp_wideBorderTest01.pdf new file mode 100644 index 0000000000..65f53da0e4 Binary files /dev/null and b/itext.tests/itext.layout.tests/resources/itext/layout/BorderTest/cmp_wideBorderTest01.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/DefaultLayoutTest/cmp_addParagraphOnShortPage1.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/DefaultLayoutTest/cmp_addParagraphOnShortPage1.pdf new file mode 100644 index 0000000000..d31b616993 Binary files /dev/null and b/itext.tests/itext.layout.tests/resources/itext/layout/DefaultLayoutTest/cmp_addParagraphOnShortPage1.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/DefaultLayoutTest/cmp_addParagraphOnShortPage2.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/DefaultLayoutTest/cmp_addParagraphOnShortPage2.pdf new file mode 100644 index 0000000000..1409191cad Binary files /dev/null and b/itext.tests/itext.layout.tests/resources/itext/layout/DefaultLayoutTest/cmp_addParagraphOnShortPage2.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/ImageTest/cmp_flushOnDrawCheckCircularReferencesTest.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/ImageTest/cmp_flushOnDrawCheckCircularReferencesTest.pdf index 8414c2a1ed..894b3deae5 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/ImageTest/cmp_flushOnDrawCheckCircularReferencesTest.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/ImageTest/cmp_flushOnDrawCheckCircularReferencesTest.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/ImageTest/cmp_flushOnDrawTest.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/ImageTest/cmp_flushOnDrawTest.pdf index b81f6efb5e..b500cbab11 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/ImageTest/cmp_flushOnDrawTest.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/ImageTest/cmp_flushOnDrawTest.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/ImageTest/cmp_imageTest09.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/ImageTest/cmp_imageTest09.pdf new file mode 100644 index 0000000000..7ac0004388 Binary files /dev/null and b/itext.tests/itext.layout.tests/resources/itext/layout/ImageTest/cmp_imageTest09.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/ImageTest/cmp_imageTest10.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/ImageTest/cmp_imageTest10.pdf new file mode 100644 index 0000000000..29f5cea933 Binary files /dev/null and b/itext.tests/itext.layout.tests/resources/itext/layout/ImageTest/cmp_imageTest10.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/ImageTest/cmp_imageTest11.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/ImageTest/cmp_imageTest11.pdf new file mode 100644 index 0000000000..595a4c7022 Binary files /dev/null and b/itext.tests/itext.layout.tests/resources/itext/layout/ImageTest/cmp_imageTest11.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/ImageTest/cmp_imageTest12.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/ImageTest/cmp_imageTest12.pdf new file mode 100644 index 0000000000..4095f15d80 Binary files /dev/null and b/itext.tests/itext.layout.tests/resources/itext/layout/ImageTest/cmp_imageTest12.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/ImageTest/cmp_imageTest13.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/ImageTest/cmp_imageTest13.pdf new file mode 100644 index 0000000000..97258e5eff Binary files /dev/null and b/itext.tests/itext.layout.tests/resources/itext/layout/ImageTest/cmp_imageTest13.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/ImageTest/cmp_imageTest14.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/ImageTest/cmp_imageTest14.pdf new file mode 100644 index 0000000000..171f5523f9 Binary files /dev/null and b/itext.tests/itext.layout.tests/resources/itext/layout/ImageTest/cmp_imageTest14.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/KeepWithNextTest/cmp_keepWithNextTest01.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/KeepWithNextTest/cmp_keepWithNextTest01.pdf new file mode 100644 index 0000000000..80ae14e8b6 Binary files /dev/null and b/itext.tests/itext.layout.tests/resources/itext/layout/KeepWithNextTest/cmp_keepWithNextTest01.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/KeepWithNextTest/cmp_keepWithNextTest02.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/KeepWithNextTest/cmp_keepWithNextTest02.pdf new file mode 100644 index 0000000000..6bda8d6615 Binary files /dev/null and b/itext.tests/itext.layout.tests/resources/itext/layout/KeepWithNextTest/cmp_keepWithNextTest02.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/KeepWithNextTest/cmp_keepWithNextTest03.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/KeepWithNextTest/cmp_keepWithNextTest03.pdf new file mode 100644 index 0000000000..2f4c7e36e0 Binary files /dev/null and b/itext.tests/itext.layout.tests/resources/itext/layout/KeepWithNextTest/cmp_keepWithNextTest03.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/KeepWithNextTest/cmp_keepWithNextTest04.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/KeepWithNextTest/cmp_keepWithNextTest04.pdf new file mode 100644 index 0000000000..c3ad295bf1 Binary files /dev/null and b/itext.tests/itext.layout.tests/resources/itext/layout/KeepWithNextTest/cmp_keepWithNextTest04.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/KeepWithNextTest/cmp_keepWithNextTest05.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/KeepWithNextTest/cmp_keepWithNextTest05.pdf new file mode 100644 index 0000000000..239bc185ec Binary files /dev/null and b/itext.tests/itext.layout.tests/resources/itext/layout/KeepWithNextTest/cmp_keepWithNextTest05.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/KeepWithNextTest/cmp_keepWithNextTest06.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/KeepWithNextTest/cmp_keepWithNextTest06.pdf new file mode 100644 index 0000000000..14b330f5f5 Binary files /dev/null and b/itext.tests/itext.layout.tests/resources/itext/layout/KeepWithNextTest/cmp_keepWithNextTest06.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/KeepWithNextTest/cmp_keepWithNextTest07.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/KeepWithNextTest/cmp_keepWithNextTest07.pdf new file mode 100644 index 0000000000..03ccf3cac4 Binary files /dev/null and b/itext.tests/itext.layout.tests/resources/itext/layout/KeepWithNextTest/cmp_keepWithNextTest07.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/KeepWithNextTest/cmp_keepWithNextTest08.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/KeepWithNextTest/cmp_keepWithNextTest08.pdf new file mode 100644 index 0000000000..f86bb77865 Binary files /dev/null and b/itext.tests/itext.layout.tests/resources/itext/layout/KeepWithNextTest/cmp_keepWithNextTest08.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/KeepWithNextTest/cmp_keepWithNextTest09.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/KeepWithNextTest/cmp_keepWithNextTest09.pdf new file mode 100644 index 0000000000..d9401d1570 Binary files /dev/null and b/itext.tests/itext.layout.tests/resources/itext/layout/KeepWithNextTest/cmp_keepWithNextTest09.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/KeepWithNextTest/cmp_keepWithNextTest10.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/KeepWithNextTest/cmp_keepWithNextTest10.pdf new file mode 100644 index 0000000000..ca52ba1788 Binary files /dev/null and b/itext.tests/itext.layout.tests/resources/itext/layout/KeepWithNextTest/cmp_keepWithNextTest10.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/LargeElementTest/cmp_largeTableTest01.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/LargeElementTest/cmp_largeTableTest01.pdf index 0bfc7c7cab..f1664a0ef4 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/LargeElementTest/cmp_largeTableTest01.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/LargeElementTest/cmp_largeTableTest01.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/LargeElementTest/cmp_largeTableTest02.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/LargeElementTest/cmp_largeTableTest02.pdf index 0a5d37bfb4..1465d94ebe 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/LargeElementTest/cmp_largeTableTest02.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/LargeElementTest/cmp_largeTableTest02.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/LargeElementTest/cmp_largeTableWithHeaderFooterTest01A.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/LargeElementTest/cmp_largeTableWithHeaderFooterTest01A.pdf index c7888ab5e4..cad2abf39c 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/LargeElementTest/cmp_largeTableWithHeaderFooterTest01A.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/LargeElementTest/cmp_largeTableWithHeaderFooterTest01A.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/LargeElementTest/cmp_largeTableWithHeaderFooterTest01B.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/LargeElementTest/cmp_largeTableWithHeaderFooterTest01B.pdf index 2501c3e1fe..a3fac2052e 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/LargeElementTest/cmp_largeTableWithHeaderFooterTest01B.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/LargeElementTest/cmp_largeTableWithHeaderFooterTest01B.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/LargeElementTest/cmp_largeTableWithHeaderFooterTest02.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/LargeElementTest/cmp_largeTableWithHeaderFooterTest02.pdf index 58450066d7..9a76fcd701 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/LargeElementTest/cmp_largeTableWithHeaderFooterTest02.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/LargeElementTest/cmp_largeTableWithHeaderFooterTest02.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/LargeElementTest/cmp_largeTableWithHeaderFooterTest03.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/LargeElementTest/cmp_largeTableWithHeaderFooterTest03.pdf index d10473f025..fcc61e987c 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/LargeElementTest/cmp_largeTableWithHeaderFooterTest03.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/LargeElementTest/cmp_largeTableWithHeaderFooterTest03.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/LargeElementTest/cmp_largeTableWithHeaderFooterTest04.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/LargeElementTest/cmp_largeTableWithHeaderFooterTest04.pdf index b7f3abb1ef..e559483f70 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/LargeElementTest/cmp_largeTableWithHeaderFooterTest04.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/LargeElementTest/cmp_largeTableWithHeaderFooterTest04.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/LineSeparatorTest/cmp_lineSeparatorBackgroundTest01.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/LineSeparatorTest/cmp_lineSeparatorBackgroundTest01.pdf new file mode 100644 index 0000000000..21f178625b Binary files /dev/null and b/itext.tests/itext.layout.tests/resources/itext/layout/LineSeparatorTest/cmp_lineSeparatorBackgroundTest01.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/LineSeparatorTest/cmp_lineSeparatorWidthPercentageTest01.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/LineSeparatorTest/cmp_lineSeparatorWidthPercentageTest01.pdf new file mode 100644 index 0000000000..d28302cd31 Binary files /dev/null and b/itext.tests/itext.layout.tests/resources/itext/layout/LineSeparatorTest/cmp_lineSeparatorWidthPercentageTest01.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/LineSeparatorTest/cmp_rotatedLineSeparatorTest01.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/LineSeparatorTest/cmp_rotatedLineSeparatorTest01.pdf new file mode 100644 index 0000000000..eb0f786c6c Binary files /dev/null and b/itext.tests/itext.layout.tests/resources/itext/layout/LineSeparatorTest/cmp_rotatedLineSeparatorTest01.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/LineSeparatorTest/cmp_rotatedLineSeparatorTest02.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/LineSeparatorTest/cmp_rotatedLineSeparatorTest02.pdf new file mode 100644 index 0000000000..f9a617f869 Binary files /dev/null and b/itext.tests/itext.layout.tests/resources/itext/layout/LineSeparatorTest/cmp_rotatedLineSeparatorTest02.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/LinkTest/cmp_borderedLinkTest.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/LinkTest/cmp_borderedLinkTest.pdf new file mode 100644 index 0000000000..e0f1b4abfb Binary files /dev/null and b/itext.tests/itext.layout.tests/resources/itext/layout/LinkTest/cmp_borderedLinkTest.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/LinkTest/cmp_linkInRotatedCell.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/LinkTest/cmp_linkInRotatedCell.pdf new file mode 100644 index 0000000000..2b190f55c4 Binary files /dev/null and b/itext.tests/itext.layout.tests/resources/itext/layout/LinkTest/cmp_linkInRotatedCell.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/LinkTest/cmp_linkTest01.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/LinkTest/cmp_linkTest01.pdf index 28801a27ea..087aa125ce 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/LinkTest/cmp_linkTest01.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/LinkTest/cmp_linkTest01.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/LinkTest/cmp_linkTest02.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/LinkTest/cmp_linkTest02.pdf index 886b224ed2..4af571e4f4 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/LinkTest/cmp_linkTest02.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/LinkTest/cmp_linkTest02.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/LinkTest/cmp_rotatedLinkAtFixedPosition.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/LinkTest/cmp_rotatedLinkAtFixedPosition.pdf new file mode 100644 index 0000000000..7a0a6ae31f Binary files /dev/null and b/itext.tests/itext.layout.tests/resources/itext/layout/LinkTest/cmp_rotatedLinkAtFixedPosition.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/LinkTest/cmp_rotatedLinkInnerRotation.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/LinkTest/cmp_rotatedLinkInnerRotation.pdf new file mode 100644 index 0000000000..d0d735eda0 Binary files /dev/null and b/itext.tests/itext.layout.tests/resources/itext/layout/LinkTest/cmp_rotatedLinkInnerRotation.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/ListTest/cmp_addListOnShortPage1.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/ListTest/cmp_addListOnShortPage1.pdf new file mode 100644 index 0000000000..f879df11cb Binary files /dev/null and b/itext.tests/itext.layout.tests/resources/itext/layout/ListTest/cmp_addListOnShortPage1.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/ListTest/cmp_addListOnShortPage2.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/ListTest/cmp_addListOnShortPage2.pdf new file mode 100644 index 0000000000..7496c68373 Binary files /dev/null and b/itext.tests/itext.layout.tests/resources/itext/layout/ListTest/cmp_addListOnShortPage2.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/ListTest/red.png b/itext.tests/itext.layout.tests/resources/itext/layout/ListTest/red.png new file mode 100644 index 0000000000..797bcb18f3 Binary files /dev/null and b/itext.tests/itext.layout.tests/resources/itext/layout/ListTest/red.png differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/PositioningTest/bruno.jpg b/itext.tests/itext.layout.tests/resources/itext/layout/PositioningTest/bruno.jpg new file mode 100644 index 0000000000..67f19cc50b Binary files /dev/null and b/itext.tests/itext.layout.tests/resources/itext/layout/PositioningTest/bruno.jpg differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/PositioningTest/cmp_fixedPositioningTest01.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/PositioningTest/cmp_fixedPositioningTest01.pdf index 3596610400..b65c93d8d1 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/PositioningTest/cmp_fixedPositioningTest01.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/PositioningTest/cmp_fixedPositioningTest01.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/PositioningTest/cmp_showTextAlignedTest01.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/PositioningTest/cmp_showTextAlignedTest01.pdf index 9354e74f86..be7eedea9b 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/PositioningTest/cmp_showTextAlignedTest01.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/PositioningTest/cmp_showTextAlignedTest01.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/PositioningTest/cmp_showTextAlignedTest02.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/PositioningTest/cmp_showTextAlignedTest02.pdf index 481fee3ac7..7e80b4eb96 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/PositioningTest/cmp_showTextAlignedTest02.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/PositioningTest/cmp_showTextAlignedTest02.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/PositioningTest/cmp_showTextAlignedTest03.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/PositioningTest/cmp_showTextAlignedTest03.pdf new file mode 100644 index 0000000000..5f88546192 Binary files /dev/null and b/itext.tests/itext.layout.tests/resources/itext/layout/PositioningTest/cmp_showTextAlignedTest03.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_alignedTextRotationTest01.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_alignedTextRotationTest01.pdf index 847f967d60..db69eb7c13 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_alignedTextRotationTest01.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_alignedTextRotationTest01.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_cellRotationTest01.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_cellRotationTest01.pdf new file mode 100644 index 0000000000..b36868ced1 Binary files /dev/null and b/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_cellRotationTest01.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_divRotationTest01.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_divRotationTest01.pdf index 7a4d573953..9e4accb006 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_divRotationTest01.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_divRotationTest01.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_divRotationTest02.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_divRotationTest02.pdf index cba2db2a86..fcbc6e92e7 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_divRotationTest02.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_divRotationTest02.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_fixedTextRotationTest01.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_fixedTextRotationTest01.pdf index b4243d82bb..06ff3e1da8 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_fixedTextRotationTest01.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_fixedTextRotationTest01.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_fixedTextRotationTest02.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_fixedTextRotationTest02.pdf index 41430d8312..cf3d0de709 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_fixedTextRotationTest02.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_fixedTextRotationTest02.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_fixedTextRotationTest03.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_fixedTextRotationTest03.pdf index 54e531b646..84cae572e6 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_fixedTextRotationTest03.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_fixedTextRotationTest03.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_fixedTextRotationTest04.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_fixedTextRotationTest04.pdf index 2ac0c678a9..8266155e5f 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_fixedTextRotationTest04.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_fixedTextRotationTest04.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_innerRotationTest01.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_innerRotationTest01.pdf index 8ff82eb537..db22b44381 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_innerRotationTest01.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_innerRotationTest01.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_innerRotationTest02.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_innerRotationTest02.pdf index 1a3c10c4a1..d1df9fcd7a 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_innerRotationTest02.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_innerRotationTest02.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_listRotationTest01.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_listRotationTest01.pdf index 9e906c9fa4..97a29020d0 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_listRotationTest01.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_listRotationTest01.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_listRotationTest02.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_listRotationTest02.pdf index 96eb9ac053..d816938deb 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_listRotationTest02.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_listRotationTest02.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_rotationInfiniteLoopTest01.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_rotationInfiniteLoopTest01.pdf index cecd2e5fb1..b562d8145e 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_rotationInfiniteLoopTest01.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_rotationInfiniteLoopTest01.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_rotationInfiniteLoopTest02.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_rotationInfiniteLoopTest02.pdf index 8e0a09872a..8765fbc631 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_rotationInfiniteLoopTest02.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_rotationInfiniteLoopTest02.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_splitTextRotationTest01.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_splitTextRotationTest01.pdf index 8d7cc54d4d..53b893855c 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_splitTextRotationTest01.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_splitTextRotationTest01.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_splitTextRotationTest02.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_splitTextRotationTest02.pdf index 74077af1ce..edbb8cca18 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_splitTextRotationTest02.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_splitTextRotationTest02.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_staticTextRotationTest01.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_staticTextRotationTest01.pdf index 776173656e..dbc93abefc 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_staticTextRotationTest01.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_staticTextRotationTest01.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_staticTextRotationTest02.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_staticTextRotationTest02.pdf index 50eccfe136..caf547729e 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_staticTextRotationTest02.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_staticTextRotationTest02.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_staticTextRotationTest03.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_staticTextRotationTest03.pdf index 351da2d925..053a11a50e 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_staticTextRotationTest03.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_staticTextRotationTest03.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_staticTextRotationTest04.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_staticTextRotationTest04.pdf index 0199fc03d8..cbb9037741 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_staticTextRotationTest04.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_staticTextRotationTest04.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_tableRotationTest02.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_tableRotationTest02.pdf index b4d463c073..99b139c537 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_tableRotationTest02.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_tableRotationTest02.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_tableRotationTest03.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_tableRotationTest03.pdf new file mode 100644 index 0000000000..194d54b0f8 Binary files /dev/null and b/itext.tests/itext.layout.tests/resources/itext/layout/RotationTest/cmp_tableRotationTest03.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/TabTest/cmp_anchorTabStopsTest.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/TabTest/cmp_anchorTabStopsTest.pdf index 884de289bd..91781d2e48 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/TabTest/cmp_anchorTabStopsTest.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/TabTest/cmp_anchorTabStopsTest.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/TabTest/cmp_outOfPageBoundsTest.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/TabTest/cmp_outOfPageBoundsTest.pdf index ec276f4ab6..7c8a1d3609 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/TabTest/cmp_outOfPageBoundsTest.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/TabTest/cmp_outOfPageBoundsTest.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/TabTest/cmp_severalTabsInRowTest.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/TabTest/cmp_severalTabsInRowTest.pdf index 4c1650e09c..62a8c60dd5 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/TabTest/cmp_severalTabsInRowTest.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/TabTest/cmp_severalTabsInRowTest.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_bigRowspanTest01.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_bigRowspanTest01.pdf index 539ea34ec5..f891fcacbc 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_bigRowspanTest01.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_bigRowspanTest01.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_bigRowspanTest02.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_bigRowspanTest02.pdf index 84c4fbb35c..0721c7f0e5 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_bigRowspanTest02.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_bigRowspanTest02.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_bigRowspanTest03.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_bigRowspanTest03.pdf index 35d2c52fec..62a4e7ae3a 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_bigRowspanTest03.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_bigRowspanTest03.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_bigRowspanTest04.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_bigRowspanTest04.pdf index 1f432764a6..fa8972d975 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_bigRowspanTest04.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_bigRowspanTest04.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_differentPageOrientationTest01.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_differentPageOrientationTest01.pdf index 36756682a1..5a9ac8c789 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_differentPageOrientationTest01.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_differentPageOrientationTest01.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_imageInTableTest_HA.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_imageInTableTest_HA.pdf new file mode 100644 index 0000000000..3a8bf442c2 Binary files /dev/null and b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_imageInTableTest_HA.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_nestedTableSkipHeaderFooter.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_nestedTableSkipHeaderFooter.pdf index b8d1d5b435..e5dc81c5ca 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_nestedTableSkipHeaderFooter.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_nestedTableSkipHeaderFooter.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_splitTableOnShortPage.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_splitTableOnShortPage.pdf new file mode 100644 index 0000000000..25233f8495 Binary files /dev/null and b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_splitTableOnShortPage.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest01.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest01.pdf index ef2fb7b8c8..0fb837f7ba 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest01.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest01.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest02.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest02.pdf index 44a95dffef..2fb1a571cf 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest02.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest02.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest03.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest03.pdf index 5fd40553d3..ec02a6de47 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest03.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest03.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest04.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest04.pdf index d1f549f816..cc3b875c0f 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest04.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest04.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest05.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest05.pdf index d2e3a20d0c..14c604b1d0 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest05.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest05.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest06.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest06.pdf index c976ccfe12..e56fa60a7e 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest06.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest06.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest07.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest07.pdf index ee75fc19e0..70a8768f3a 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest07.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest07.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest08.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest08.pdf index c0385355bf..6736cb87b0 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest08.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest08.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest09.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest09.pdf index 80d3a0ca81..262bc799d3 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest09.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest09.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest10.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest10.pdf index bf7b30b027..aab11d05b9 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest10.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest10.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest11.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest11.pdf index 16d485ff8c..af1956381a 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest11.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest11.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest12.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest12.pdf index d2cbb39a78..6296bb6edf 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest12.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest12.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest13.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest13.pdf index 5ec17580c8..43e78811a4 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest13.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest13.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest14.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest14.pdf index 24c1d6e82c..fcdd28fdfe 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest14.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest14.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest15.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest15.pdf index 9ee54cb058..6aa05dab65 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest15.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest15.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest16.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest16.pdf index 8a1e392d97..2c497d574f 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest16.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest16.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest17.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest17.pdf index 37d2e7e1fd..b4aaf1a21a 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest17.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest17.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest18.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest18.pdf index 33a4ff4e25..c79a56c025 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest18.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest18.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest19.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest19.pdf index 97613023e3..fcf0f062a2 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest19.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest19.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest20.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest20.pdf index 851ce18440..c1dd4fdff5 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest20.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest20.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest21.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest21.pdf index 134363bb28..d63ea5040d 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest21.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_tableTest21.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_toLargeElementInTableTest01.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_toLargeElementInTableTest01.pdf index ba6c0508e1..c4bb48637b 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_toLargeElementInTableTest01.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_toLargeElementInTableTest01.pdf differ diff --git a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_toLargeElementWithKeepTogetherPropertyInTableTest01.pdf b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_toLargeElementWithKeepTogetherPropertyInTableTest01.pdf index dd51d59629..0688bb85f2 100644 Binary files a/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_toLargeElementWithKeepTogetherPropertyInTableTest01.pdf and b/itext.tests/itext.layout.tests/resources/itext/layout/TableTest/cmp_toLargeElementWithKeepTogetherPropertyInTableTest01.pdf differ diff --git a/itext.tests/itext.pdfa.tests/Properties/AssemblyInfo.cs b/itext.tests/itext.pdfa.tests/Properties/AssemblyInfo.cs index c1072681f5..ed959c8e36 100644 --- a/itext.tests/itext.pdfa.tests/Properties/AssemblyInfo.cs +++ b/itext.tests/itext.pdfa.tests/Properties/AssemblyInfo.cs @@ -15,5 +15,7 @@ [assembly: Guid("b7c0e021-71ac-4c97-9a51-8356f1bd53c7")] -[assembly: AssemblyVersion("7.0.0.0")] -[assembly: AssemblyFileVersion("7.0.0.0")] +[assembly: AssemblyVersion("7.0.1.0")] +[assembly: AssemblyFileVersion("7.0.1.0")] + +[assembly: NUnit.Framework.Timeout(300000)] diff --git a/itext.tests/itext.pdfa.tests/itext.pdfa.tests.csproj b/itext.tests/itext.pdfa.tests/itext.pdfa.tests.csproj index b10eee0524..7976396785 100644 --- a/itext.tests/itext.pdfa.tests/itext.pdfa.tests.csproj +++ b/itext.tests/itext.pdfa.tests/itext.pdfa.tests.csproj @@ -35,7 +35,7 @@ - ..\..\packages\NUnit.3.2.1\lib\net40\nunit.framework.dll + $(SolutionDir)\packages\NUnit.3.2.1\lib\net40\nunit.framework.dll
diff --git a/itext.tests/itext.pdfa.tests/itext/pdfa/PdfA1AnnotationCheckTest.cs b/itext.tests/itext.pdfa.tests/itext/pdfa/PdfA1AnnotationCheckTest.cs index 8a64dcbe8c..e0c8a313f5 100644 --- a/itext.tests/itext.pdfa.tests/itext/pdfa/PdfA1AnnotationCheckTest.cs +++ b/itext.tests/itext.pdfa.tests/itext/pdfa/PdfA1AnnotationCheckTest.cs @@ -115,7 +115,7 @@ public virtual void AnnotationCheckTest05() { Rectangle rect = new Rectangle(100, 100, 100, 100); PdfAnnotation annot = new PdfWidgetAnnotation(rect); annot.SetFlag(PdfAnnotation.PRINT); - PdfStream s = new PdfStream("Hello World".GetBytes()); + PdfStream s = new PdfStream("Hello World".GetBytes(iText.IO.Util.EncodingUtil.ISO_8859_1)); annot.SetDownAppearance(new PdfDictionary()); annot.SetNormalAppearance(s); page.AddAnnotation(annot); diff --git a/itext.tests/itext.pdfa.tests/itext/pdfa/PdfAFontTest.cs b/itext.tests/itext.pdfa.tests/itext/pdfa/PdfAFontTest.cs index a85d30e315..91cf9ffac2 100644 --- a/itext.tests/itext.pdfa.tests/itext/pdfa/PdfAFontTest.cs +++ b/itext.tests/itext.pdfa.tests/itext/pdfa/PdfAFontTest.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using iText.IO.Font; using iText.Kernel.Colors; using iText.Kernel.Font; using iText.Kernel.Pdf; @@ -226,6 +227,83 @@ public virtual void CidFontCheckTest3() { CompareResult(outPdf, cmpPdf); } + /// + /// + /// + [NUnit.Framework.Test] + public virtual void SymbolicTtfCharEncodingsPdfA1Test01() { + // encoding must not be specified + CreateDocumentWithFont("symbolicTtfCharEncodingsPdfA1Test01.pdf", "Symbols1.ttf", "", PdfAConformanceLevel + .PDF_A_1B); + } + + /// + /// + /// + [NUnit.Framework.Test] + public virtual void SymbolicTtfCharEncodingsPdfA1Test02() { + // if you specify encoding, symbolic font is treated as non-symbolic + CreateDocumentWithFont("symbolicTtfCharEncodingsPdfA1Test02.pdf", "Symbols1.ttf", PdfEncodings.MACROMAN, PdfAConformanceLevel + .PDF_A_1B); + } + + /// + /// + /// + [NUnit.Framework.Test] + public virtual void SymbolicTtfCharEncodingsPdfA1Test03() { + NUnit.Framework.Assert.That(() => { + // if you specify encoding, symbolic font is treated as non-symbolic + CreateDocumentWithFont("symbolicTtfCharEncodingsPdfA1Test03.pdf", "Symbols1.ttf", "ISO-8859-1", PdfAConformanceLevel + .PDF_A_1B); + } + , NUnit.Framework.Throws.TypeOf().With.Message.EqualTo(PdfAConformanceException.AllNonSymbolicTrueTypeFontShallSpecifyMacRomanOrWinAnsiEncodingAsTheEncodingEntry)); +; + } + + /// + /// + /// + [NUnit.Framework.Test] + public virtual void NonSymbolicTtfCharEncodingsPdfA1Test01() { + // encoding must be either winansi or macroman, by default winansi is used + CreateDocumentWithFont("nonSymbolicTtfCharEncodingsPdfA1Test01.pdf", "FreeSans.ttf", PdfEncodings.WINANSI, + PdfAConformanceLevel.PDF_A_1B); + } + + /// + /// + /// + [NUnit.Framework.Test] + public virtual void NonSymbolicTtfCharEncodingsPdfA1Test02() { + NUnit.Framework.Assert.That(() => { + // encoding must be either winansi or macroman, by default winansi is used + CreateDocumentWithFont("nonSymbolicTtfCharEncodingsPdfA1Test02.pdf", "FreeSans.ttf", "ISO-8859-1", PdfAConformanceLevel + .PDF_A_2B); + } + , NUnit.Framework.Throws.TypeOf().With.Message.EqualTo(PdfAConformanceException.AllNonSymbolicTrueTypeFontShallSpecifyMacRomanEncodingOrWinAnsiEncoding)); +; + } + + /// + /// + private void CreateDocumentWithFont(String outFileName, String fontFileName, String encoding, PdfAConformanceLevel + conformanceLevel) { + String outPdf = outputDir + outFileName; + String cmpPdf = sourceFolder + "cmp/PdfAFontTest/cmp_" + outFileName; + PdfWriter writer = new PdfWriter(outPdf); + Stream @is = new FileStream(sourceFolder + "sRGB Color Space Profile.icm", FileMode.Open, FileAccess.Read); + PdfDocument doc = new PdfADocument(writer, conformanceLevel, new PdfOutputIntent("Custom", "", "http://www.color.org" + , "sRGB IEC61966-2.1", @is)); + PdfPage page = doc.AddNewPage(); + PdfFont font = PdfFontFactory.CreateFont(sourceFolder + fontFileName, encoding, true); + PdfCanvas canvas = new PdfCanvas(page); + canvas.SaveState().BeginText().MoveText(36, 700).SetFontAndSize(font, 12).ShowText("Hello World").EndText( + ).RestoreState(); + doc.Close(); + CompareResult(outPdf, cmpPdf); + } + /// /// private void CompareResult(String outPdf, String cmpPdf) { diff --git a/itext.tests/itext.pdfa.tests/resources/itext/pdfa/Symbols1.ttf b/itext.tests/itext.pdfa.tests/resources/itext/pdfa/Symbols1.ttf new file mode 100644 index 0000000000..5b4f4c79f4 Binary files /dev/null and b/itext.tests/itext.pdfa.tests/resources/itext/pdfa/Symbols1.ttf differ diff --git a/itext.tests/itext.pdfa.tests/resources/itext/pdfa/cmp/PdfA2ActionCheckTest/cmp_pdfA2b_actionCheck15.pdf b/itext.tests/itext.pdfa.tests/resources/itext/pdfa/cmp/PdfA2ActionCheckTest/cmp_pdfA2b_actionCheck15.pdf index e02cde9cc1..023485c666 100644 Binary files a/itext.tests/itext.pdfa.tests/resources/itext/pdfa/cmp/PdfA2ActionCheckTest/cmp_pdfA2b_actionCheck15.pdf and b/itext.tests/itext.pdfa.tests/resources/itext/pdfa/cmp/PdfA2ActionCheckTest/cmp_pdfA2b_actionCheck15.pdf differ diff --git a/itext.tests/itext.pdfa.tests/resources/itext/pdfa/cmp/PdfAFontTest/cmp_nonSymbolicTtfCharEncodingsPdfA1Test01.pdf b/itext.tests/itext.pdfa.tests/resources/itext/pdfa/cmp/PdfAFontTest/cmp_nonSymbolicTtfCharEncodingsPdfA1Test01.pdf new file mode 100644 index 0000000000..da68b9da76 Binary files /dev/null and b/itext.tests/itext.pdfa.tests/resources/itext/pdfa/cmp/PdfAFontTest/cmp_nonSymbolicTtfCharEncodingsPdfA1Test01.pdf differ diff --git a/itext.tests/itext.pdfa.tests/resources/itext/pdfa/cmp/PdfAFontTest/cmp_symbolicTtfCharEncodingsPdfA1Test01.pdf b/itext.tests/itext.pdfa.tests/resources/itext/pdfa/cmp/PdfAFontTest/cmp_symbolicTtfCharEncodingsPdfA1Test01.pdf new file mode 100644 index 0000000000..1b2caf0db3 Binary files /dev/null and b/itext.tests/itext.pdfa.tests/resources/itext/pdfa/cmp/PdfAFontTest/cmp_symbolicTtfCharEncodingsPdfA1Test01.pdf differ diff --git a/itext.tests/itext.pdfa.tests/resources/itext/pdfa/cmp/PdfAFontTest/cmp_symbolicTtfCharEncodingsPdfA1Test02.pdf b/itext.tests/itext.pdfa.tests/resources/itext/pdfa/cmp/PdfAFontTest/cmp_symbolicTtfCharEncodingsPdfA1Test02.pdf new file mode 100644 index 0000000000..c21e229fad Binary files /dev/null and b/itext.tests/itext.pdfa.tests/resources/itext/pdfa/cmp/PdfAFontTest/cmp_symbolicTtfCharEncodingsPdfA1Test02.pdf differ diff --git a/itext.tests/itext.sign.tests/Properties/AssemblyInfo.cs b/itext.tests/itext.sign.tests/Properties/AssemblyInfo.cs index ffc8e54692..eb2a5f0392 100644 --- a/itext.tests/itext.sign.tests/Properties/AssemblyInfo.cs +++ b/itext.tests/itext.sign.tests/Properties/AssemblyInfo.cs @@ -15,5 +15,7 @@ [assembly: Guid("be15bdf3-b184-4e2f-8459-ebee3160e19d")] -[assembly: AssemblyVersion("7.0.0.0")] -[assembly: AssemblyFileVersion("7.0.0.0")] +[assembly: AssemblyVersion("7.0.1.0")] +[assembly: AssemblyFileVersion("7.0.1.0")] + +[assembly: NUnit.Framework.Timeout(300000)] diff --git a/itext.tests/itext.sign.tests/itext.sign.tests.csproj b/itext.tests/itext.sign.tests/itext.sign.tests.csproj index 6d084498be..6431b7517a 100644 --- a/itext.tests/itext.sign.tests/itext.sign.tests.csproj +++ b/itext.tests/itext.sign.tests/itext.sign.tests.csproj @@ -35,7 +35,7 @@ - ..\..\packages\NUnit.3.2.1\lib\net40\nunit.framework.dll + $(SolutionDir)\packages\NUnit.3.2.1\lib\net40\nunit.framework.dll diff --git a/itext.tests/itext.sign.tests/itext/signatures/SigningTest.cs b/itext.tests/itext.sign.tests/itext/signatures/SigningTest.cs index ee93d47ac7..52ebb20d92 100644 --- a/itext.tests/itext.sign.tests/itext/signatures/SigningTest.cs +++ b/itext.tests/itext.sign.tests/itext/signatures/SigningTest.cs @@ -93,7 +93,7 @@ public virtual void SigningIntoExistingFieldTest01() .CADES, "Test 1", "TestCity", null, false); NUnit.Framework.Assert.IsNull(new CompareTool().CompareVisually(dest, sourceFolder + "cmp_" + fileName, destinationFolder, "diff_", - new Dictionary>{ {1 , IO.Util.JavaUtil.ArraysAsList(new Rectangle(67, 725, 155, 15))}})); + new Dictionary>{ {1 , IO.Util.JavaUtil.ArraysAsList(new Rectangle(67, 725, 160, 15))}})); } /// @@ -111,7 +111,7 @@ public virtual void SigningIntoExistingFieldTest02() .CADES, "Test 1", "TestCity", null, false); NUnit.Framework.Assert.IsNull(new CompareTool().CompareVisually(dest, sourceFolder + "cmp_" + fileName, destinationFolder, "diff_", - new Dictionary> { { 1, IO.Util.JavaUtil.ArraysAsList(new Rectangle(67, 725, 155, 15)) } })); + new Dictionary> { { 1, IO.Util.JavaUtil.ArraysAsList(new Rectangle(67, 725, 160, 15)) } })); } /// diff --git a/itext/itext.barcodes/Properties/AssemblyInfo.cs b/itext/itext.barcodes/Properties/AssemblyInfo.cs index 776376d03b..decd87162c 100644 --- a/itext/itext.barcodes/Properties/AssemblyInfo.cs +++ b/itext/itext.barcodes/Properties/AssemblyInfo.cs @@ -21,5 +21,5 @@ [assembly: Guid("8694665a-5749-40c6-9e9c-53c686a77ad1")] -[assembly: AssemblyVersion("7.0.0.0")] -[assembly: AssemblyFileVersion("7.0.0.0")] +[assembly: AssemblyVersion("7.0.1.0")] +[assembly: AssemblyFileVersion("7.0.1.0")] diff --git a/itext/itext.barcodes/itext/barcodes/BarcodeCodabar.cs b/itext/itext.barcodes/itext/barcodes/BarcodeCodabar.cs index 3bca10e667..7a736a7487 100644 --- a/itext/itext.barcodes/itext/barcodes/BarcodeCodabar.cs +++ b/itext/itext.barcodes/itext/barcodes/BarcodeCodabar.cs @@ -114,7 +114,7 @@ public static byte[] GetBarsCodabar(String text) { text = text.ToUpper(System.Globalization.CultureInfo.InvariantCulture); int len = text.Length; if (len < 2) { - throw new ArgumentException(PdfException.CodabarMustHaveAtLeastAStartAndStopCharacter); + throw new ArgumentException(PdfException.CodabarMustHaveAtLeastStartAndStopCharacter); } if (CHARS.IndexOf(text[0]) < START_STOP_IDX || CHARS.IndexOf(text[len - 1]) < START_STOP_IDX) { throw new ArgumentException(PdfException.CodabarMustHaveOneAbcdAsStartStopCharacter); @@ -123,10 +123,10 @@ public static byte[] GetBarsCodabar(String text) { for (int k = 0; k < len; ++k) { int idx = CHARS.IndexOf(text[k]); if (idx >= START_STOP_IDX && k > 0 && k < len - 1) { - throw new ArgumentException(PdfException.CodabarStartStopCharacterAreOnlyExtremes); + throw new ArgumentException(PdfException.InCodabarStartStopCharactersAreOnlyAllowedAtTheExtremes); } if (idx < 0) { - throw new ArgumentException(PdfException.CodabarCharacterOneIsIllegal); + throw new ArgumentException(PdfException.IllegalCharacterInCodabarBarcode); } System.Array.Copy(BARS[idx], 0, bars, k * 8, 7); } diff --git a/itext/itext.barcodes/itext/barcodes/qrcode/EncodeHintType.cs b/itext/itext.barcodes/itext/barcodes/qrcode/EncodeHintType.cs index 1341838ab4..8933a83537 100644 --- a/itext/itext.barcodes/itext/barcodes/qrcode/EncodeHintType.cs +++ b/itext/itext.barcodes/itext/barcodes/qrcode/EncodeHintType.cs @@ -53,6 +53,10 @@ public sealed class EncodeHintType { public static readonly iText.Barcodes.Qrcode.EncodeHintType CHARACTER_SET = new iText.Barcodes.Qrcode.EncodeHintType (); + /// Specifies the minimal version level to use, for example in QR Codes (type Integer). + public static readonly iText.Barcodes.Qrcode.EncodeHintType MIN_VERSION_NR = new iText.Barcodes.Qrcode.EncodeHintType + (); + private EncodeHintType() { } } diff --git a/itext/itext.barcodes/itext/barcodes/qrcode/Encoder.cs b/itext/itext.barcodes/itext/barcodes/qrcode/Encoder.cs index 4091cd6af3..1109c39040 100644 --- a/itext/itext.barcodes/itext/barcodes/qrcode/Encoder.cs +++ b/itext/itext.barcodes/itext/barcodes/qrcode/Encoder.cs @@ -99,6 +99,15 @@ public static void Encode(String content, ErrorCorrectionLevel ecLevel, IDiction if (encoding == null) { encoding = DEFAULT_BYTE_MODE_ENCODING; } + int desiredMinVersion = (hints == null || hints.Get(EncodeHintType.MIN_VERSION_NR) == null) ? 1 : (int)hints + .Get(EncodeHintType.MIN_VERSION_NR); + //Check if desired level is within bounds of [1,40] + if (desiredMinVersion < 1) { + desiredMinVersion = 1; + } + if (desiredMinVersion > 40) { + desiredMinVersion = 40; + } // Step 1: Choose the mode (encoding). Mode mode = ChooseMode(content, encoding); // Step 2: Append "bytes" into "dataBits" in appropriate encoding. @@ -106,7 +115,7 @@ public static void Encode(String content, ErrorCorrectionLevel ecLevel, IDiction AppendBytes(content, mode, dataBits, encoding); // Step 3: Initialize QR code that can contain "dataBits". int numInputBytes = dataBits.SizeInBytes(); - InitQRCode(numInputBytes, ecLevel, mode, qrCode); + InitQRCode(numInputBytes, ecLevel, desiredMinVersion, mode, qrCode); // Step 4: Build another bit vector that contains header and data. BitVector headerAndDataBits = new BitVector(); // Step 4.5: Append ECI message if applicable @@ -238,11 +247,12 @@ private static int ChooseMaskPattern(BitVector bits, ErrorCorrectionLevel ecLeve /// modify "qrCode". /// /// - private static void InitQRCode(int numInputBytes, ErrorCorrectionLevel ecLevel, Mode mode, QRCode qrCode) { + private static void InitQRCode(int numInputBytes, ErrorCorrectionLevel ecLevel, int desiredMinVersion, Mode + mode, QRCode qrCode) { qrCode.SetECLevel(ecLevel); qrCode.SetMode(mode); // In the following comments, we use numbers of Version 7-H. - for (int versionNum = 1; versionNum <= 40; versionNum++) { + for (int versionNum = desiredMinVersion; versionNum <= 40; versionNum++) { Version version = Version.GetVersionForNumber(versionNum); // numBytes = 196 int numBytes = version.GetTotalCodewords(); diff --git a/itext/itext.font-asian/Properties/AssemblyInfo.cs b/itext/itext.font-asian/Properties/AssemblyInfo.cs index 4e62608a76..e314ade3ee 100644 --- a/itext/itext.font-asian/Properties/AssemblyInfo.cs +++ b/itext/itext.font-asian/Properties/AssemblyInfo.cs @@ -15,5 +15,5 @@ [assembly: Guid("0f10190c-7611-4378-a157-03bf2ed78e30")] -[assembly: AssemblyVersion("7.0.0.0")] -[assembly: AssemblyFileVersion("7.0.0.0")] +[assembly: AssemblyVersion("7.0.1.0")] +[assembly: AssemblyFileVersion("7.0.1.0")] diff --git a/itext/itext.forms/Properties/AssemblyInfo.cs b/itext/itext.forms/Properties/AssemblyInfo.cs index 8097d8f4aa..41c0f2cf6e 100644 --- a/itext/itext.forms/Properties/AssemblyInfo.cs +++ b/itext/itext.forms/Properties/AssemblyInfo.cs @@ -20,5 +20,5 @@ [assembly: Guid("2257d7e6-2873-4cfb-ac3c-b24765a4b3b1")] -[assembly: AssemblyVersion("7.0.0.0")] -[assembly: AssemblyFileVersion("7.0.0.0")] +[assembly: AssemblyVersion("7.0.1.0")] +[assembly: AssemblyFileVersion("7.0.1.0")] diff --git a/itext/itext.forms/itext.forms.csproj b/itext/itext.forms/itext.forms.csproj index fd32bbf386..d159beac66 100644 --- a/itext/itext.forms/itext.forms.csproj +++ b/itext/itext.forms/itext.forms.csproj @@ -31,6 +31,7 @@ TRACE prompt 4 + false bin\Release\itext.forms.xml diff --git a/itext/itext.forms/itext/forms/FormsExtensions.cs b/itext/itext.forms/itext/forms/FormsExtensions.cs index 8abbd1c241..cbb7c57d63 100644 --- a/itext/itext.forms/itext/forms/FormsExtensions.cs +++ b/itext/itext.forms/itext/forms/FormsExtensions.cs @@ -46,6 +46,7 @@ source product. using System.Linq; using System.Collections.Generic; using System.IO; +using System.Text; namespace iText.Forms { internal static class FormsExtensions { @@ -69,8 +70,24 @@ public static byte[] GetBytes(this String str) { return System.Text.Encoding.UTF8.GetBytes(str); } + public static byte[] GetBytes(this String str, Encoding encoding) { + return encoding.GetBytes(str); + } + public static T[] ToArray(this ICollection col, T[] toArray) { - T[] r = col.ToArray(); + T[] r; + int colSize = col.Count; + if (colSize <= toArray.Length) { + col.CopyTo(toArray, 0); + if (colSize != toArray.Length) { + toArray[colSize] = default(T); + } + r = toArray; + } else { + r = new T[colSize]; + col.CopyTo(r, 0); + } + return r; } diff --git a/itext/itext.forms/itext/forms/PdfAcroForm.cs b/itext/itext.forms/itext/forms/PdfAcroForm.cs index 3edd8b6d16..4f5777c380 100644 --- a/itext/itext.forms/itext/forms/PdfAcroForm.cs +++ b/itext/itext.forms/itext/forms/PdfAcroForm.cs @@ -61,6 +61,7 @@ public class PdfAcroForm : PdfObjectWrapper { /// To be used with /// /// . + ///

///

/// If set, the document contains at least one signature field. This flag /// allows a conforming reader to enable user interface items (such as menu @@ -75,6 +76,7 @@ public class PdfAcroForm : PdfObjectWrapper { /// To be used with /// /// . + ///

///

/// If set, the document contains signatures that may be invalidated if the /// file is saved (written) in a way that alters its previous contents, as @@ -235,6 +237,9 @@ public virtual void AddField(PdfFormField field, PdfPage page) { } GetFields().Add(fieldDic); fields[field.GetFieldName().ToUnicodeString()] = field; + if (field.GetKids() != null) { + IterateFields(field.GetKids(), fields); + } if (field.GetFormType() != null && (field.GetFormType().Equals(PdfName.Tx) || field.GetFormType().Equals(PdfName .Ch))) { IList resources = GetResources(field.GetPdfObject()); @@ -309,6 +314,7 @@ public virtual IDictionary GetFormFields() { /// Sets the NeedAppearances boolean property on the AcroForm. /// /// Sets the NeedAppearances boolean property on the AcroForm. + ///

///

/// NeedAppearances is a flag specifying whether to construct appearance /// streams and appearance dictionaries for all widget annotations in the @@ -325,6 +331,7 @@ public virtual iText.Forms.PdfAcroForm SetNeedAppearances(bool needAppearances) /// Gets the NeedAppearances boolean property on the AcroForm. /// /// Gets the NeedAppearances boolean property on the AcroForm. + ///

///

/// NeedAppearances is a flag specifying whether to construct appearance /// streams and appearance dictionaries for all widget annotations in the @@ -344,6 +351,7 @@ public virtual PdfBoolean GetNeedAppearances() { /// Sets the SigFlags integer property on the AcroForm. /// /// Sets the SigFlags integer property on the AcroForm. + ///

///

/// SigFlags is a set of flags specifying various document-level /// characteristics related to signature fields. @@ -367,6 +375,7 @@ public virtual iText.Forms.PdfAcroForm SetSignatureFlags(int sigFlags) { /// /// Changes the SigFlags integer property on the AcroForm. /// This method allows only to add flags, not to remove them. + ///

///

/// SigFlags is a set of flags specifying various document-level /// characteristics related to signature fields. @@ -391,6 +400,7 @@ public virtual iText.Forms.PdfAcroForm SetSignatureFlag(int sigFlag) { /// Gets the SigFlags integer property on the AcroForm. /// /// Gets the SigFlags integer property on the AcroForm. + ///

///

/// SigFlags is a set of flags specifying various document-level /// characteristics related to signature fields @@ -411,6 +421,7 @@ public virtual int GetSignatureFlags() { /// Sets the CO array property on the AcroForm. /// /// Sets the CO array property on the AcroForm. + ///

///

/// CO, Calculation Order, is an array of indirect references to /// field dictionaries with calculation actions, defining the calculation @@ -428,6 +439,7 @@ public virtual iText.Forms.PdfAcroForm SetCalculationOrder(PdfArray calculationO /// Gets the CO array property on the AcroForm. /// /// Gets the CO array property on the AcroForm. + ///

///

/// CO, Calculation Order, is an array of indirect references to /// field dictionaries with calculation actions, defining the calculation @@ -444,6 +456,7 @@ public virtual PdfArray GetCalculationOrder() { /// Sets the DR dictionary property on the AcroForm. /// /// Sets the DR dictionary property on the AcroForm. + ///

///

/// DR is a resource dictionary containing default resources /// (such as fonts, patterns, or colour spaces) that shall be used by form @@ -462,6 +475,7 @@ public virtual iText.Forms.PdfAcroForm SetDefaultResources(PdfDictionary default /// Gets the DR dictionary property on the AcroForm. /// /// Gets the DR dictionary property on the AcroForm. + ///

///

/// DR is a resource dictionary containing default resources /// (such as fonts, patterns, or colour spaces) that shall be used by form @@ -479,6 +493,7 @@ public virtual PdfDictionary GetDefaultResources() { /// Sets the DA String property on the AcroForm. /// /// Sets the DA String property on the AcroForm. + ///

/// This method sets a default (fallback value) for the DA /// attribute of variable text /// form field @@ -486,7 +501,7 @@ public virtual PdfDictionary GetDefaultResources() { /// /// a String containing a sequence of valid PDF syntax /// current AcroForm - /// + /// public virtual iText.Forms.PdfAcroForm SetDefaultAppearance(String appearance) { return Put(PdfName.DA, new PdfString(appearance)); } @@ -494,6 +509,7 @@ public virtual iText.Forms.PdfAcroForm SetDefaultAppearance(String appearance) { ///

Gets the DA String property on the AcroForm. /// /// Gets the DA String property on the AcroForm. + ///

/// This method returns the default (fallback value) for the DA /// attribute of variable text /// form field @@ -507,6 +523,7 @@ public virtual PdfString GetDefaultAppearance() { ///

Sets the Q integer property on the AcroForm. /// /// Sets the Q integer property on the AcroForm. + ///

/// This method sets a default (fallback value) for the Q /// attribute of variable text /// form field @@ -514,7 +531,7 @@ public virtual PdfString GetDefaultAppearance() { /// /// an integer representing a justification value /// current AcroForm - /// + /// public virtual iText.Forms.PdfAcroForm SetDefaultJustification(int justification) { return Put(PdfName.Q, new PdfNumber(justification)); } @@ -522,13 +539,14 @@ public virtual iText.Forms.PdfAcroForm SetDefaultJustification(int justification ///

Gets the Q integer property on the AcroForm. /// /// Gets the Q integer property on the AcroForm. + ///

/// This method gets the default (fallback value) for the Q /// attribute of variable text /// form field /// s. /// /// an integer representing a justification value - /// + /// public virtual PdfNumber GetDefaultJustification() { return GetPdfObject().GetAsNumber(PdfName.Q); } @@ -536,6 +554,7 @@ public virtual PdfNumber GetDefaultJustification() { ///

Sets the XFA property on the AcroForm. /// /// Sets the XFA property on the AcroForm. + ///

/// XFA can either be a /// /// or a @@ -552,6 +571,7 @@ public virtual iText.Forms.PdfAcroForm SetXFAResource(PdfStream xfaResource) { ///

Sets the XFA property on the AcroForm. /// /// Sets the XFA property on the AcroForm. + ///

/// XFA can either be a /// /// or a @@ -621,9 +641,11 @@ public virtual bool IsGenerateAppearance() { /// form field /// s /// that don't have one. + ///

/// Not generating appearances will speed up form flattening but the results /// can be unexpected in Acrobat. Don't use it unless your environment is /// well controlled. The default is true. + ///

/// If generateAppearance is set to true, then /// NeedAppearances is set to false. This does not /// apply vice versa. @@ -710,7 +732,8 @@ public virtual void FlattenFields() { } } } - if (xObject != null) { + // Subtype is required key, if there is no Subtype it is invalid XObject. DEVSIX-725 + if (xObject != null && xObject.GetPdfObject().Get(PdfName.Subtype) != null) { Rectangle box = fieldObject.GetAsRectangle(PdfName.Rect); if (page.IsFlushed()) { throw new PdfException(PdfException.PageWasAlreadyFlushedUseAddFieldAppearanceToPageMethodBeforePageFlushing @@ -730,7 +753,7 @@ public virtual void FlattenFields() { canvas.OpenTag(tagRef); } canvas.AddXObject(xObject, box.GetX(), box.GetY()); - if (document.IsTagged()) { + if (tagPointer != null) { canvas.CloseTag(); } } @@ -894,8 +917,8 @@ protected override bool IsWrappedObjectMustBeIndirect() { return false; } - private IDictionary IterateFields(PdfArray array) { - IDictionary fields = new LinkedDictionary(); + private IDictionary IterateFields(PdfArray array, IDictionary + fields) { int index = 1; foreach (PdfObject field in array) { PdfFormField formField = PdfFormField.MakeFormField(field, document); @@ -917,12 +940,16 @@ private IDictionary IterateFields(PdfArray array) { } fields[name] = formField; if (formField.GetKids() != null) { - fields.AddAll(IterateFields(formField.GetKids())); + IterateFields(formField.GetKids(), fields); } } return fields; } + private IDictionary IterateFields(PdfArray array) { + return IterateFields(array, new LinkedDictionary()); + } + private PdfDictionary ProcessKids(PdfArray kids, PdfDictionary parent, PdfPage page) { if (kids.Size() == 1) { PdfDictionary kidDict = (PdfDictionary)kids.Get(0); @@ -1140,14 +1167,7 @@ private ICollection PrepareFieldsForFlattening(PdfFormField field) PdfArray kids = field.GetKids(); if (kids != null) { foreach (PdfObject kid in kids) { - PdfDictionary fieldDict; - if (kid.IsIndirectReference()) { - fieldDict = (PdfDictionary)((PdfIndirectReference)kid).GetRefersTo(); - } - else { - fieldDict = (PdfDictionary)kid; - } - PdfFormField kidField = new PdfFormField(fieldDict); + PdfFormField kidField = new PdfFormField((PdfDictionary)kid); preparedFields.Add(kidField); if (kidField.GetKids() != null) { preparedFields.AddAll(PrepareFieldsForFlattening(kidField)); diff --git a/itext/itext.forms/itext/forms/PdfPageFormCopier.cs b/itext/itext.forms/itext/forms/PdfPageFormCopier.cs index 819009b4ea..a87e4f7953 100644 --- a/itext/itext.forms/itext/forms/PdfPageFormCopier.cs +++ b/itext/itext.forms/itext/forms/PdfPageFormCopier.cs @@ -54,6 +54,14 @@ namespace iText.Forms { /// A sample implementation of the {#link IPdfPageExtraCopier} interface which /// copies only AcroForm fields to a new page. /// + /// + /// A sample implementation of the {#link IPdfPageExtraCopier} interface which + /// copies only AcroForm fields to a new page. + ///

+ /// NOTE: While it's absolutely not necessary to use the same PdfPageFormCopier instance for copying operations, + /// it is still worth to know that PdfPageFormCopier uses some caching logic which can potentially improve performance + /// in case of the reusing of the same instance. + ///
public class PdfPageFormCopier : IPdfPageExtraCopier { internal PdfAcroForm formFrom; @@ -63,6 +71,8 @@ public class PdfPageFormCopier : IPdfPageExtraCopier { internal PdfDocument documentTo; + internal ILogger logger = LoggerFactory.GetLogger(typeof(PdfPageFormCopier)); + public virtual void Copy(PdfPage fromPage, PdfPage toPage) { if (documentFrom != fromPage.GetDocument()) { documentFrom = fromPage.GetDocument(); @@ -71,16 +81,15 @@ public virtual void Copy(PdfPage fromPage, PdfPage toPage) { if (documentTo != toPage.GetDocument()) { documentTo = toPage.GetDocument(); formTo = PdfAcroForm.GetAcroForm(documentTo, true); - if (formFrom != null) { - //duplicate AcroForm dictionary - IList excludedKeys = new List(); - excludedKeys.Add(PdfName.Fields); - excludedKeys.Add(PdfName.DR); - PdfDictionary dict = formFrom.GetPdfObject().CopyTo(documentTo, excludedKeys, false); - formTo.GetPdfObject().MergeDifferent(dict); - } } - IList usedParents = new List(); + if (formFrom != null) { + //duplicate AcroForm dictionary + IList excludedKeys = new List(); + excludedKeys.Add(PdfName.Fields); + excludedKeys.Add(PdfName.DR); + PdfDictionary dict = formFrom.GetPdfObject().CopyTo(documentTo, excludedKeys, false); + formTo.GetPdfObject().MergeDifferent(dict); + } if (formFrom != null) { IDictionary fieldsFrom = formFrom.GetFormFields(); if (fieldsFrom.Count > 0) { @@ -90,19 +99,44 @@ public virtual void Copy(PdfPage fromPage, PdfPage toPage) { if (annot.GetSubtype().Equals(PdfName.Widget)) { PdfDictionary parent = annot.GetPdfObject().GetAsDictionary(PdfName.Parent); if (parent != null) { - PdfString parentName = parent.GetAsString(PdfName.T); + PdfFormField parentField = GetParentField(parent, documentTo); + PdfString parentName = parentField.GetFieldName(); if (parentName == null) { continue; } - if (!usedParents.Contains(parent)) { - PdfFormField field = PdfFormField.MakeFormField(parent, toPage.GetDocument()); - field.GetKids().Clear(); + if (!fieldsTo.ContainsKey(parentName.ToUnicodeString())) { + PdfFormField field = CreateParentFieldCopy(annot.GetPdfObject(), documentTo); + PdfArray kids = field.GetKids(); + field.GetPdfObject().Remove(PdfName.Kids); formTo.AddField(field, toPage); - usedParents.Add(parent); - field.AddKid((PdfWidgetAnnotation)annot); + field.GetPdfObject().Put(PdfName.Kids, kids); } else { - parent.GetAsArray(PdfName.Kids).Add(annot.GetPdfObject()); + PdfFormField field = PdfFormField.MakeFormField(annot.GetPdfObject(), documentTo); + PdfString fieldName = field.GetFieldName(); + if (fieldName != null) { + PdfFormField existingField = fieldsTo.Get(fieldName.ToUnicodeString()); + if (existingField != null) { + PdfFormField clonedField = PdfFormField.MakeFormField(field.GetPdfObject().Clone().MakeIndirect(documentTo + ), documentTo); + toPage.GetPdfObject().GetAsArray(PdfName.Annots).Add(clonedField.GetPdfObject()); + toPage.RemoveAnnotation(annot); + MergeFieldsWithTheSameName(existingField, clonedField); + } + else { + HashSet existingFields = new HashSet(); + GetAllFieldNames(formTo.GetFields(), existingFields); + AddChildToExistingParent(annot.GetPdfObject(), existingFields); + } + } + else { + if (parentField.GetKids().Contains(field.GetPdfObject())) { + field = PdfFormField.MakeFormField(field.GetPdfObject().Clone().MakeIndirect(documentTo), documentTo); + toPage.GetPdfObject().GetAsArray(PdfName.Annots).Add(field.GetPdfObject()); + toPage.RemoveAnnotation(annot); + } + parentField.AddKid(field); + } } } else { @@ -112,13 +146,21 @@ public virtual void Copy(PdfPage fromPage, PdfPage toPage) { annotNameString = annotName.ToUnicodeString(); } if (annotNameString != null && fieldsFrom.ContainsKey(annotNameString)) { - PdfFormField field = PdfFormField.MakeFormField(annot.GetPdfObject(), toPage.GetDocument()); - if (fieldsTo.ContainsKey(annotNameString)) { - field = MergeFieldsWithTheSameName(field, fieldsTo.Get(annotNameString)); - ILogger logger = LoggerFactory.GetLogger(typeof(PdfPageFormCopier)); + PdfFormField field = fieldsTo.Get(annotNameString); + if (field != null) { + PdfDictionary clonedAnnot = (PdfDictionary)annot.GetPdfObject().Clone().MakeIndirect(documentTo); + toPage.GetPdfObject().GetAsArray(PdfName.Annots).Add(clonedAnnot); + toPage.RemoveAnnotation(annot); + field = MergeFieldsWithTheSameName(field, PdfFormField.MakeFormField(clonedAnnot, toPage.GetDocument())); logger.Warn(String.Format(LogMessageConstant.DOCUMENT_ALREADY_HAS_FIELD, annotNameString)); + PdfArray kids = field.GetKids(); + field.GetPdfObject().Remove(PdfName.Kids); + formTo.AddField(field, toPage); + field.GetPdfObject().Put(PdfName.Kids, kids); + } + else { + formTo.AddField(PdfFormField.MakeFormField(annot.GetPdfObject(), documentTo), null); } - formTo.AddField(field, null); } } } @@ -128,28 +170,93 @@ public virtual void Copy(PdfPage fromPage, PdfPage toPage) { } private PdfFormField MergeFieldsWithTheSameName(PdfFormField existingField, PdfFormField newField) { - String fieldName = newField.GetFieldName().ToUnicodeString(); - existingField.GetPdfObject().Remove(PdfName.T); - PdfFormField mergedField = formTo.GetField(fieldName); - PdfArray kids = mergedField.GetKids(); + String fullFieldName = newField.GetFieldName().ToUnicodeString(); + PdfString fieldName = newField.GetPdfObject().GetAsString(PdfName.T); + newField.GetPdfObject().Remove(PdfName.T); + newField.GetPdfObject().Remove(PdfName.P); + existingField = formTo.GetField(fullFieldName); + PdfArray kids = existingField.GetKids(); if (kids != null && !kids.IsEmpty()) { - mergedField.AddKid(existingField); - return mergedField; + existingField.AddKid(newField); + return existingField; } - newField.GetPdfObject().Remove(PdfName.T); - mergedField = PdfFormField.CreateEmptyField(documentTo); - formTo.GetFields().Remove(newField.GetPdfObject()); - mergedField.Put(PdfName.FT, existingField.GetFormType()).Put(PdfName.T, new PdfString(fieldName)); + existingField.GetPdfObject().Remove(PdfName.T); + existingField.GetPdfObject().Remove(PdfName.P); + formTo.GetFields().Remove(existingField.GetPdfObject()); + PdfFormField mergedField = PdfFormField.CreateEmptyField(documentTo); + mergedField.Put(PdfName.FT, existingField.GetFormType()).Put(PdfName.T, fieldName); PdfDictionary parent = existingField.GetParent(); if (parent != null) { mergedField.Put(PdfName.Parent, parent); + PdfArray parentKids = parent.GetAsArray(PdfName.Kids); + for (int i = 0; i < parentKids.Size(); i++) { + PdfObject obj = parentKids.Get(i); + if (obj == existingField.GetPdfObject()) { + parentKids.Set(i, mergedField.GetPdfObject()); + break; + } + } } kids = existingField.GetKids(); if (kids != null) { mergedField.Put(PdfName.Kids, kids); } mergedField.AddKid(existingField).AddKid(newField); + PdfObject value = existingField.GetValue(); + if (value != null) { + mergedField.Put(PdfName.V, existingField.GetPdfObject().Get(PdfName.V)); + } return mergedField; } + + private PdfFormField GetParentField(PdfDictionary parent, PdfDocument pdfDoc) { + PdfFormField parentField = PdfFormField.MakeFormField(parent, pdfDoc); + PdfDictionary parentOfParent = parentField.GetParent(); + if (parentOfParent != null) { + parentField = GetParentField(parentOfParent, pdfDoc); + } + return parentField; + } + + private PdfFormField CreateParentFieldCopy(PdfDictionary fieldDic, PdfDocument pdfDoc) { + fieldDic.Remove(PdfName.Kids); + PdfDictionary parent = fieldDic.GetAsDictionary(PdfName.Parent); + PdfFormField field = PdfFormField.MakeFormField(fieldDic, pdfDoc); + if (parent != null) { + field = CreateParentFieldCopy(parent, pdfDoc); + parent.Put(PdfName.Kids, new PdfArray(fieldDic)); + } + return field; + } + + private void AddChildToExistingParent(PdfDictionary fieldDic, ICollection existingFields) { + PdfDictionary parent = fieldDic.GetAsDictionary(PdfName.Parent); + PdfString parentName = parent.GetAsString(PdfName.T); + if (parentName != null) { + String name = parentName.ToUnicodeString(); + if (existingFields.Contains(name)) { + PdfArray kids = parent.GetAsArray(PdfName.Kids); + kids.Add(fieldDic); + } + else { + parent.Put(PdfName.Kids, new PdfArray(fieldDic)); + AddChildToExistingParent(parent, existingFields); + } + } + } + + private void GetAllFieldNames(PdfArray fields, ICollection existingFields) { + foreach (PdfObject field in fields) { + PdfDictionary dic = (PdfDictionary)field; + PdfString name = dic.GetAsString(PdfName.T); + if (name != null) { + existingFields.Add(name.ToUnicodeString()); + } + PdfArray kids = dic.GetAsArray(PdfName.Kids); + if (kids != null) { + GetAllFieldNames(kids, existingFields); + } + } + } } } diff --git a/itext/itext.forms/itext/forms/fields/PdfFormField.cs b/itext/itext.forms/itext/forms/fields/PdfFormField.cs index f786999244..993cb425ec 100644 --- a/itext/itext.forms/itext/forms/fields/PdfFormField.cs +++ b/itext/itext.forms/itext/forms/fields/PdfFormField.cs @@ -43,9 +43,12 @@ source product. */ using System; using System.Collections.Generic; +using System.Text; +using iText.IO; using iText.IO.Codec; using iText.IO.Font; using iText.IO.Image; +using iText.IO.Log; using iText.IO.Source; using iText.Kernel; using iText.Kernel.Colors; @@ -64,6 +67,7 @@ namespace iText.Forms.Fields { /// This class represents a single field or field group in an /// AcroForm /// . + ///

///

/// To be able to be wrapped with this /// @@ -134,17 +138,17 @@ public class PdfFormField : PdfObjectWrapper { protected internal PdfFont font; - protected internal int fontSize; + protected internal float fontSize; protected internal Color color; protected internal int checkType; - protected internal float borderWidth = 1; + protected internal float borderWidth = 0; protected internal Color backgroundColor; - protected internal Color borderColor = Color.BLACK; + protected internal Color borderColor; protected internal int rotation = 0; @@ -384,7 +388,7 @@ public static PdfTextFormField CreateText(PdfDocument doc, Rectangle rect, Strin /// public static PdfTextFormField CreateText(PdfDocument doc, Rectangle rect, String name, String value) { try { - return CreateText(doc, rect, name, value, PdfFontFactory.CreateFont(), DEFAULT_FONT_SIZE); + return CreateText(doc, rect, name, value, PdfFontFactory.CreateFont(), (float)DEFAULT_FONT_SIZE); } catch (System.IO.IOException e) { throw new PdfException(e); @@ -409,13 +413,13 @@ public static PdfTextFormField CreateText(PdfDocument doc, Rectangle rect, Strin /// a /// /// - /// a positive integer + /// the size of the font /// /// a new /// /// public static PdfTextFormField CreateText(PdfDocument doc, Rectangle rect, String name, String value, PdfFont - font, int fontSize) { + font, float fontSize) { return CreateText(doc, rect, name, value, font, fontSize, false); } @@ -437,14 +441,75 @@ public static PdfTextFormField CreateText(PdfDocument doc, Rectangle rect, Strin /// a /// /// - /// a positive integer + /// the size of the font + /// + /// a new + /// + /// + [System.ObsoleteAttribute(@"Will be removed in 7.1. Use CreateText(iText.Kernel.Pdf.PdfDocument, iText.Kernel.Geom.Rectangle, System.String, System.String, iText.Kernel.Font.PdfFont, float) instead." + )] + public static PdfTextFormField CreateText(PdfDocument doc, Rectangle rect, String name, String value, PdfFont + font, int fontSize) { + return CreateText(doc, rect, name, value, font, (float)fontSize, false); + } + + ///

+ /// Creates a named + /// text form field + /// with an initial + /// value, with a specified font and font size. + /// + /// + /// the + /// + /// to create the text field in + /// + /// the location on the page for the text field + /// the name of the form field + /// the initial value + /// + /// a + /// + /// + /// the size of the font /// true for multiline text field /// /// a new /// /// + [System.ObsoleteAttribute(@"Will be removed in 7.1. Use CreateText(iText.Kernel.Pdf.PdfDocument, iText.Kernel.Geom.Rectangle, System.String, System.String, iText.Kernel.Font.PdfFont, float, bool) instead." + )] public static PdfTextFormField CreateText(PdfDocument doc, Rectangle rect, String name, String value, PdfFont font, int fontSize, bool multiline) { + return CreateText(doc, rect, name, value, font, (float)fontSize, multiline); + } + + /// + /// Creates a named + /// text form field + /// with an initial + /// value, with a specified font and font size. + /// + /// + /// the + /// + /// to create the text field in + /// + /// the location on the page for the text field + /// the name of the form field + /// the initial value + /// + /// a + /// + /// + /// the size of the font + /// true for multiline text field + /// + /// a new + /// + /// + public static PdfTextFormField CreateText(PdfDocument doc, Rectangle rect, String name, String value, PdfFont + font, float fontSize, bool multiline) { PdfWidgetAnnotation annot = new PdfWidgetAnnotation(rect); PdfTextFormField field = new PdfTextFormField(annot, doc); field.SetMultiline(multiline); @@ -473,16 +538,46 @@ public static PdfTextFormField CreateText(PdfDocument doc, Rectangle rect, Strin /// a /// /// - /// a positive integer + /// the size of the font /// /// a new /// /// public static PdfTextFormField CreateMultilineText(PdfDocument doc, Rectangle rect, String name, String value - , PdfFont font, int fontSize) { + , PdfFont font, float fontSize) { return CreateText(doc, rect, name, value, font, fontSize, true); } + /// + /// Creates a named + /// multilined text form field + /// with an initial + /// value, with a specified font and font size. + /// + /// + /// the + /// + /// to create the text field in + /// + /// the location on the page for the text field + /// the name of the form field + /// the initial value + /// + /// a + /// + /// + /// the size of the font + /// + /// a new + /// + /// + [System.ObsoleteAttribute(@"use CreateMultilineText(iText.Kernel.Pdf.PdfDocument, iText.Kernel.Geom.Rectangle, System.String, System.String, iText.Kernel.Font.PdfFont, float) instead" + )] + public static PdfTextFormField CreateMultilineText(PdfDocument doc, Rectangle rect, String name, String value + , PdfFont font, int fontSize) { + return CreateText(doc, rect, name, value, font, (float)fontSize, true); + } + /// /// Creates a named /// multiline text form field @@ -506,7 +601,7 @@ public static PdfTextFormField CreateMultilineText(PdfDocument doc, Rectangle re public static PdfTextFormField CreateMultilineText(PdfDocument doc, Rectangle rect, String name, String value ) { try { - return CreateText(doc, rect, name, value, PdfFontFactory.CreateFont(), DEFAULT_FONT_SIZE, true); + return CreateText(doc, rect, name, value, PdfFontFactory.CreateFont(), (float)DEFAULT_FONT_SIZE, true); } catch (System.IO.IOException e) { throw new PdfException(e); @@ -598,8 +693,8 @@ public static PdfChoiceFormField CreateChoice(PdfDocument doc, Rectangle rect, i public static PdfChoiceFormField CreateChoice(PdfDocument doc, Rectangle rect, String name, String value, PdfArray options, int flags) { try { - return CreateChoice(doc, rect, name, value, PdfFontFactory.CreateFont(), DEFAULT_FONT_SIZE, options, flags - ); + return CreateChoice(doc, rect, name, value, PdfFontFactory.CreateFont(), (float)DEFAULT_FONT_SIZE, options + , flags); } catch (System.IO.IOException e) { throw new PdfException(e); @@ -624,7 +719,7 @@ public static PdfChoiceFormField CreateChoice(PdfDocument doc, Rectangle rect, S /// a /// /// - /// a positive integer + /// the size of the font /// /// an array of /// @@ -640,8 +735,49 @@ public static PdfChoiceFormField CreateChoice(PdfDocument doc, Rectangle rect, S /// a new /// /// + [System.ObsoleteAttribute(@"Will be removed in 7.1. Use CreateChoice(iText.Kernel.Pdf.PdfDocument, iText.Kernel.Geom.Rectangle, System.String, System.String, iText.Kernel.Font.PdfFont, float, iText.Kernel.Pdf.PdfArray, int) instead" + )] public static PdfChoiceFormField CreateChoice(PdfDocument doc, Rectangle rect, String name, String value, PdfFont font, int fontSize, PdfArray options, int flags) { + return CreateChoice(doc, rect, name, value, font, (float)fontSize, options, flags); + } + + /// + /// Creates a + /// choice form field + /// with custom + /// behavior and layout, on a specified location. + /// + /// + /// the + /// + /// to create the choice field in + /// + /// the location on the page for the choice field + /// the name of the form field + /// the initial value + /// + /// a + /// + /// + /// the size of the font + /// + /// an array of + /// + /// objects that each represent + /// the 'on' state of one of the choices. + /// + /// + /// an int, containing a set of binary behavioral + /// flags. Do binary OR on this int to set the + /// flags you require. + /// + /// + /// a new + /// + /// + public static PdfChoiceFormField CreateChoice(PdfDocument doc, Rectangle rect, String name, String value, + PdfFont font, float fontSize, PdfArray options, int flags) { PdfWidgetAnnotation annot = new PdfWidgetAnnotation(rect); iText.Forms.Fields.PdfFormField field = new PdfChoiceFormField(annot, doc); field.font = font; @@ -824,7 +960,7 @@ public static PdfButtonFormField CreatePushButton(PdfDocument doc, Rectangle rec ) { PdfButtonFormField field; try { - field = CreatePushButton(doc, rect, name, caption, PdfFontFactory.CreateFont(), DEFAULT_FONT_SIZE); + field = CreatePushButton(doc, rect, name, caption, PdfFontFactory.CreateFont(), (float)DEFAULT_FONT_SIZE); } catch (System.IO.IOException e) { throw new PdfException(e); @@ -850,13 +986,43 @@ public static PdfButtonFormField CreatePushButton(PdfDocument doc, Rectangle rec /// a /// /// - /// a positive integer + /// the size of the font /// /// a new /// /// + [System.ObsoleteAttribute(@"Will be removed in 7.1. Use CreatePushButton(iText.Kernel.Pdf.PdfDocument, iText.Kernel.Geom.Rectangle, System.String, System.String, iText.Kernel.Font.PdfFont, float) instead." + )] public static PdfButtonFormField CreatePushButton(PdfDocument doc, Rectangle rect, String name, String caption , PdfFont font, int fontSize) { + return CreatePushButton(doc, rect, name, caption, font, (float)fontSize); + } + + /// + /// Creates a + /// + /// as a push button without data, with + /// its caption in a custom font. + /// + /// + /// the + /// + /// to create the radio group in + /// + /// the location on the page for the field + /// the name of the form field + /// the text to display on the button + /// + /// a + /// + /// + /// the size of the font + /// + /// a new + /// + /// + public static PdfButtonFormField CreatePushButton(PdfDocument doc, Rectangle rect, String name, String caption + , PdfFont font, float fontSize) { PdfWidgetAnnotation annot = new PdfWidgetAnnotation(rect); PdfButtonFormField field = new PdfButtonFormField(annot, doc); field.SetPushButton(true); @@ -1115,9 +1281,6 @@ public static PdfChoiceFormField CreateList(PdfDocument doc, Rectangle rect, Str /// public static iText.Forms.Fields.PdfFormField MakeFormField(PdfObject pdfObject, PdfDocument document) { iText.Forms.Fields.PdfFormField field = null; - if (pdfObject.IsIndirectReference()) { - pdfObject = ((PdfIndirectReference)pdfObject).GetRefersTo(); - } if (pdfObject.IsDictionary()) { PdfDictionary dictionary = (PdfDictionary)pdfObject; PdfName formType = dictionary.GetAsName(PdfName.FT); @@ -1239,9 +1402,22 @@ public virtual iText.Forms.Fields.PdfFormField SetValue(String value, bool gener /// a /// /// - /// a positive integer + /// the size of the font /// the edited field + [System.ObsoleteAttribute(@"Use SetValue(System.String, iText.Kernel.Font.PdfFont, float) instead")] public virtual iText.Forms.Fields.PdfFormField SetValue(String value, PdfFont font, int fontSize) { + return SetValue(value, font, (float)fontSize); + } + + /// Set text field value with given font and size + /// text value + /// + /// a + /// + /// + /// the size of the font + /// the edited field + public virtual iText.Forms.Fields.PdfFormField SetValue(String value, PdfFont font, float fontSize) { PdfName formType = GetFormType(); if (!formType.Equals(PdfName.Tx) && !formType.Equals(PdfName.Ch)) { return SetValue(value); @@ -1505,7 +1681,7 @@ public virtual iText.Forms.Fields.PdfFormField SetFieldFlag(int flag, bool value return SetFieldFlags(flags); } - /// If true, the field can contain multiple lines of text; if false, the field???s text is restricted to a single line. + /// If true, the field can contain multiple lines of text; if false, the field's text is restricted to a single line. /// /// whether the field can span over multiple lines. public virtual bool IsMultiline() { @@ -1685,7 +1861,7 @@ public virtual IList GetWidgets() { /// /// Gets default appearance string containing a sequence of valid page-content graphics or text state operators that - /// define such properties as the field???s text size and color. + /// define such properties as the field's text size and color. /// /// /// the default appearance graphics, as a @@ -1697,12 +1873,12 @@ public virtual PdfString GetDefaultAppearance() { /// /// Sets default appearance string containing a sequence of valid page-content graphics or text state operators that - /// define such properties as the field???s text size and color. + /// define such properties as the field's text size and color. /// /// a valid sequence of PDF content stream syntax /// the edited field public virtual iText.Forms.Fields.PdfFormField SetDefaultAppearance(String defaultAppearance) { - byte[] b = defaultAppearance.GetBytes(); + byte[] b = defaultAppearance.GetBytes(Encoding.UTF8); int len = b.Length; for (int k = 0; k < len; ++k) { if (b[k] == '\n') { @@ -1800,9 +1976,10 @@ public virtual PdfFont GetFont() { /// appearance after setting the new value. /// /// the new font to be set - public virtual void SetFont(PdfFont font) { + public virtual iText.Forms.Fields.PdfFormField SetFont(PdfFont font) { this.font = font; RegenerateField(); + return this; } /// Basic setter for the fontSize property. @@ -1811,9 +1988,21 @@ public virtual void SetFont(PdfFont font) { /// field appearance after setting the new value. /// /// the new font size to be set - public virtual void SetFontSize(int fontSize) { + public virtual iText.Forms.Fields.PdfFormField SetFontSize(float fontSize) { this.fontSize = fontSize; RegenerateField(); + return this; + } + + /// Basic setter for the fontSize property. + /// + /// Basic setter for the fontSize property. Regenerates the + /// field appearance after setting the new value. + /// + /// the new font size to be set + public virtual iText.Forms.Fields.PdfFormField SetFontSize(int fontSize) { + SetFontSize((float)fontSize); + return this; } /// @@ -1826,10 +2015,11 @@ public virtual void SetFontSize(int fontSize) { /// /// the new font to be set /// the new font size to be set - public virtual void SetFontAndSize(PdfFont font, int fontSize) { + public virtual iText.Forms.Fields.PdfFormField SetFontAndSize(PdfFont font, int fontSize) { this.font = font; this.fontSize = fontSize; RegenerateField(); + return this; } /// Basic setter for the backgroundColor property. @@ -1838,7 +2028,7 @@ public virtual void SetFontAndSize(PdfFont font, int fontSize) { /// the field appearance after setting the new value. /// /// the new color to be set - public virtual void SetBackgroundColor(Color backgroundColor) { + public virtual iText.Forms.Fields.PdfFormField SetBackgroundColor(Color backgroundColor) { this.backgroundColor = backgroundColor; PdfDictionary mk = GetWidgets()[0].GetAppearanceCharacteristics(); if (mk == null) { @@ -1846,6 +2036,7 @@ public virtual void SetBackgroundColor(Color backgroundColor) { } mk.Put(PdfName.BG, new PdfArray(backgroundColor.GetColorValue())); RegenerateField(); + return this; } /// Basic setter for the degRotation property. @@ -1854,7 +2045,7 @@ public virtual void SetBackgroundColor(Color backgroundColor) { /// the field appearance after setting the new value. /// /// the new degRotation to be set - public virtual void SetRotation(int degRotation) { + public virtual iText.Forms.Fields.PdfFormField SetRotation(int degRotation) { if (degRotation % 90 != 0) { throw new ArgumentException("degRotation.must.be.a.multiple.of.90"); } @@ -1868,10 +2059,12 @@ public virtual void SetRotation(int degRotation) { PdfDictionary mk = GetWidgets()[0].GetAppearanceCharacteristics(); if (mk == null) { mk = new PdfDictionary(); + this.Put(PdfName.MK, mk); } mk.Put(PdfName.R, new PdfNumber(degRotation)); this.rotation = degRotation; RegenerateField(); + return this; } /// @@ -1899,14 +2092,14 @@ public virtual iText.Forms.Fields.PdfFormField SetAction(PdfAction action) { /// method /// /// the new checkbox marker - public virtual void SetCheckType(int checkType) { + public virtual iText.Forms.Fields.PdfFormField SetCheckType(int checkType) { if (checkType < TYPE_CHECK || checkType > TYPE_STAR) { checkType = TYPE_CROSS; } this.checkType = checkType; text = typeChars[checkType - 1]; if (pdfAConformanceLevel != null) { - return; + return this; } try { font = PdfFontFactory.CreateFont(FontConstants.ZAPFDINGBATS); @@ -1914,6 +2107,7 @@ public virtual void SetCheckType(int checkType) { catch (System.IO.IOException e) { throw new PdfException(e); } + return this; } /// @@ -1952,6 +2146,10 @@ public virtual iText.Forms.Fields.PdfFormField SetVisibility(int visibility) { public virtual bool RegenerateField() { PdfName type = GetFormType(); String value = GetValueAsString(); + PdfPage page = null; + if (GetWidgets().Count > 0) { + page = GetWidgets()[0].GetPage(); + } if (PdfName.Tx.Equals(type) || PdfName.Ch.Equals(type)) { try { PdfDictionary apDic = GetPdfObject().GetAsDictionary(PdfName.AP); @@ -1969,10 +2167,94 @@ public virtual bool RegenerateField() { } Object[] fontAndSize = GetFontAndSize(asNormal); PdfFont localFont = (PdfFont)fontAndSize[0]; - int fontSz = (int)fontAndSize[1]; - if (fontSz == 0) { - fontSz = DEFAULT_FONT_SIZE; + float fontSize = (float)fontAndSize[1]; + if (fontSize == 0) { + fontSize = (float)DEFAULT_FONT_SIZE; + } + //Apply Page rotation + int pageRotation = 0; + if (page != null) { + pageRotation = page.GetRotation(); + //Clockwise, so negative + pageRotation *= -1; } + PdfArray matrix; + if (pageRotation % 90 == 0) { + //Cast angle to [-360, 360] + double angle = pageRotation % 360; + //Get angle in radians + angle = DegreeToRadians(angle); + //rotate the bounding box + Rectangle rect = bBox.ToRectangle(); + //Calculate origin offset + double translationWidth = 0; + double translationHeight = 0; + if (angle >= -1 * Math.PI && angle <= -1 * Math.PI / 2) { + translationWidth = rect.GetWidth(); + } + if (angle <= -1 * Math.PI) { + translationHeight = rect.GetHeight(); + } + //Store rotation and translation in the matrix + matrix = new PdfArray(new double[] { Math.Cos(angle), -Math.Sin(angle), Math.Sin(angle), Math.Cos(angle), + translationWidth, translationHeight }); + //If the angle is a multiple of 90 and not a multiple of 180, height and width of the bounding box need to be switched + if (angle % (Math.PI / 2) == 0 && angle % (Math.PI) != 0) { + rect.SetWidth(bBox.ToRectangle().GetHeight()); + rect.SetHeight(bBox.ToRectangle().GetWidth()); + } + // Adapt origin + rect.SetX(rect.GetX() + (float)translationWidth); + rect.SetY(rect.GetY() + (float)translationHeight); + //Copy Bounding box + bBox = new PdfArray(rect); + } + else { + //Avoid NPE when handling corrupt pdfs + ILogger logger = LoggerFactory.GetLogger(typeof(iText.Forms.Fields.PdfFormField)); + logger.Error(LogMessageConstant.INCORRECT_PAGEROTATION); + matrix = new PdfArray(new double[] { 1, 0, 0, 1, 0, 0 }); + } + //Apply field rotation + float fieldRotation = 0; + if (this.GetPdfObject().GetAsDictionary(PdfName.MK) != null && this.GetPdfObject().GetAsDictionary(PdfName + .MK).Get(PdfName.R) != null) { + fieldRotation = (float)this.GetPdfObject().GetAsDictionary(PdfName.MK).GetAsFloat(PdfName.R); + //Get relative field rotation + fieldRotation += pageRotation; + } + if (fieldRotation % 90 == 0) { + //Cast angle to [-360, 360] + double angle = fieldRotation % 360; + //Get angle in radians + angle = DegreeToRadians(angle); + //Calculate origin offset + double translationWidth = CalculateTranslationWidthAfterFieldRot(bBox.ToRectangle(), DegreeToRadians(pageRotation + ), angle); + double translationHeight = CalculateTranslationHeightAfterFieldRot(bBox.ToRectangle(), DegreeToRadians(pageRotation + ), angle); + //Concatenate rotation and translation into the matrix + Matrix currentMatrix = new Matrix(matrix.GetAsNumber(0).FloatValue(), matrix.GetAsNumber(1).FloatValue(), + matrix.GetAsNumber(2).FloatValue(), matrix.GetAsNumber(3).FloatValue(), matrix.GetAsNumber(4).FloatValue + (), matrix.GetAsNumber(5).FloatValue()); + Matrix toConcatenate = new Matrix((float)Math.Cos(angle), (float)(-Math.Sin(angle)), (float)(Math.Sin(angle + )), (float)(Math.Cos(angle)), (float)translationWidth, (float)translationHeight); + currentMatrix = currentMatrix.Multiply(toConcatenate); + matrix = new PdfArray(new float[] { currentMatrix.Get(0), currentMatrix.Get(1), currentMatrix.Get(3), currentMatrix + .Get(4), currentMatrix.Get(6), currentMatrix.Get(7) }); + //Construct bounding box + Rectangle rect = bBox.ToRectangle(); + //If the angle is a multiple of 90 and not a multiple of 180, height and width of the bounding box need to be switched + if (angle % (Math.PI / 2) == 0 && angle % (Math.PI) != 0) { + rect.SetWidth(bBox.ToRectangle().GetHeight()); + rect.SetHeight(bBox.ToRectangle().GetWidth()); + } + rect.SetX(rect.GetX() + (float)translationWidth); + rect.SetY(rect.GetY() + (float)translationHeight); + //Copy Bounding box + bBox = new PdfArray(rect); + } + //Create appearance PdfFormXObject appearance = null; if (asNormal != null) { appearance = new PdfFormXObject(asNormal); @@ -1983,12 +2265,16 @@ public virtual bool RegenerateField() { appearance = new PdfFormXObject(new Rectangle(0, 0, bBox.ToRectangle().GetWidth(), bBox.ToRectangle().GetHeight ())); } + if (matrix != null) { + appearance.Put(PdfName.Matrix, matrix); + } + //Create text appearance if (PdfName.Tx.Equals(type)) { if (!IsMultiline()) { - DrawTextAppearance(bBox.ToRectangle(), localFont, fontSz, value, appearance); + DrawTextAppearance(bBox.ToRectangle(), localFont, fontSize, value, appearance); } else { - DrawMultiLineTextAppearance(bBox.ToRectangle(), localFont, fontSz, value, appearance); + DrawMultiLineTextAppearance(bBox.ToRectangle(), localFont, fontSize, value, appearance); } } else { @@ -2002,7 +2288,7 @@ public virtual bool RegenerateField() { } value = OptionsArrayToString(options); } - DrawMultiLineTextAppearance(bBox.ToRectangle(), localFont, fontSz, value, appearance); + DrawMultiLineTextAppearance(bBox.ToRectangle(), localFont, fontSize, value, appearance); } appearance.GetResources().AddFont(GetDocument(), localFont); PdfDictionary ap = new PdfDictionary(); @@ -2043,8 +2329,8 @@ public virtual bool RegenerateField() { } Object[] fontAndSize = GetFontAndSize(asNormal); PdfFont localFont = (PdfFont)fontAndSize[0]; - int fontSz = (int)fontAndSize[1]; - appearance = DrawPushButtonAppearance(rect.GetWidth(), rect.GetHeight(), value, localFont, fontSz); + float fontSize = (float)fontAndSize[1]; + appearance = DrawPushButtonAppearance(rect.GetWidth(), rect.GetHeight(), value, localFont, fontSize); appearance.GetResources().AddFont(GetDocument(), localFont); } } @@ -2119,16 +2405,143 @@ public virtual bool RegenerateField() { return true; } + /// + /// Calculate the necessary height offset after applying field rotation + /// so that the origin of the bounding box is the lower left corner with respect to the field text. + /// + /// bounding box rectangle before rotation + /// rotation of the page + /// rotation of the field relative to the page + /// translation value for height + private float CalculateTranslationHeightAfterFieldRot(Rectangle bBox, double pageRotation, double relFieldRotation + ) { + if (relFieldRotation == 0) { + return 0.0f; + } + if (pageRotation == 0) { + if (relFieldRotation == Math.PI / 2) { + return bBox.GetHeight(); + } + if (relFieldRotation == Math.PI) { + return bBox.GetHeight(); + } + } + if (pageRotation == -Math.PI / 2) { + if (relFieldRotation == -Math.PI / 2) { + return bBox.GetWidth() - bBox.GetHeight(); + } + if (relFieldRotation == Math.PI / 2) { + return bBox.GetHeight(); + } + if (relFieldRotation == Math.PI) { + return bBox.GetWidth(); + } + } + if (pageRotation == -Math.PI) { + if (relFieldRotation == -1 * Math.PI) { + return bBox.GetHeight(); + } + if (relFieldRotation == -1 * Math.PI / 2) { + return bBox.GetHeight() - bBox.GetWidth(); + } + if (relFieldRotation == Math.PI / 2) { + return bBox.GetWidth(); + } + } + if (pageRotation == -3 * Math.PI / 2) { + if (relFieldRotation == -3 * Math.PI / 2) { + return bBox.GetWidth(); + } + if (relFieldRotation == -Math.PI) { + return bBox.GetWidth(); + } + } + return 0.0f; + } + + /// + /// Calculate the necessary width offset after applying field rotation + /// so that the origin of the bounding box is the lower left corner with respect to the field text. + /// + /// bounding box rectangle before rotation + /// rotation of the page + /// rotation of the field relative to the page + /// translation value for width + private float CalculateTranslationWidthAfterFieldRot(Rectangle bBox, double pageRotation, double relFieldRotation + ) { + if (relFieldRotation == 0) { + return 0.0f; + } + if (pageRotation == 0 && (relFieldRotation == Math.PI || relFieldRotation == 3 * Math.PI / 2)) { + return bBox.GetWidth(); + } + if (pageRotation == -Math.PI / 2) { + if (relFieldRotation == -Math.PI / 2 || relFieldRotation == Math.PI) { + return bBox.GetHeight(); + } + } + if (pageRotation == -Math.PI) { + if (relFieldRotation == -1 * Math.PI) { + return bBox.GetWidth(); + } + if (relFieldRotation == -1 * Math.PI / 2) { + return bBox.GetHeight(); + } + if (relFieldRotation == Math.PI / 2) { + return -1 * (bBox.GetHeight() - bBox.GetWidth()); + } + } + if (pageRotation == -3 * Math.PI / 2) { + if (relFieldRotation == -3 * Math.PI / 2) { + return -1 * (bBox.GetWidth() - bBox.GetHeight()); + } + if (relFieldRotation == -Math.PI) { + return bBox.GetHeight(); + } + if (relFieldRotation == -Math.PI / 2) { + return bBox.GetWidth(); + } + } + return 0.0f; + } + /// Gets the border width for the field. /// the current border width. public virtual float GetBorderWidth() { + PdfDictionary bs = GetWidgets()[0].GetBorderStyle(); + if (bs != null) { + PdfNumber w = bs.GetAsNumber(PdfName.W); + if (w != null) { + borderWidth = w.FloatValue(); + } + } return borderWidth; } /// Sets the border width for the field. /// the new border width. - public virtual void SetBorderWidth(float borderWidth) { + public virtual iText.Forms.Fields.PdfFormField SetBorderWidth(float borderWidth) { + PdfDictionary bs = GetWidgets()[0].GetBorderStyle(); + if (bs == null) { + bs = new PdfDictionary(); + Put(PdfName.BS, bs); + } + bs.Put(PdfName.W, new PdfNumber(borderWidth)); this.borderWidth = borderWidth; + RegenerateField(); + return this; + } + + public virtual iText.Forms.Fields.PdfFormField SetBorderStyle(PdfDictionary style) { + //PdfDictionary bs = getWidgets().get(0).getBorderStyle(); + GetWidgets()[0].SetBorderStyle(style); + // if (bs == null) { + // bs = new PdfDictionary(); + // put(PdfName.BS, bs); + // } + // bs.put(PdfName.S, style); + RegenerateField(); + return this; } /// Sets the Border Color. @@ -2139,6 +2552,7 @@ public virtual iText.Forms.Fields.PdfFormField SetBorderColor(Color color) { PdfDictionary mk = GetWidgets()[0].GetAppearanceCharacteristics(); if (mk == null) { mk = new PdfDictionary(); + Put(PdfName.MK, mk); } mk.Put(PdfName.BC, new PdfArray(color.GetColorValue())); RegenerateField(); @@ -2246,14 +2660,7 @@ public virtual String[] GetAppearanceStates() { PdfArray kids = GetKids(); if (kids != null) { foreach (PdfObject kid in kids) { - PdfDictionary kidDic; - if (kid.IsIndirectReference()) { - kidDic = (PdfDictionary)((PdfIndirectReference)kid).GetRefersTo(); - } - else { - kidDic = (PdfDictionary)kid; - } - iText.Forms.Fields.PdfFormField fld = new iText.Forms.Fields.PdfFormField(kidDic); + iText.Forms.Fields.PdfFormField fld = new iText.Forms.Fields.PdfFormField((PdfDictionary)kid); String[] states = fld.GetAppearanceStates(); foreach (String state in states) { names.Add(state); @@ -2360,14 +2767,24 @@ protected internal static PdfArray ProcessOptions(String[] options) { return array; } - protected internal virtual String GenerateDefaultAppearanceString(PdfFont font, int fontSize, PdfResources - res) { + protected internal virtual String GenerateDefaultAppearanceString(PdfFont font, float fontSize, Color color + , PdfResources res) { PdfStream stream = new PdfStream(); PdfCanvas canvas = new PdfCanvas(stream, res, GetDocument()); - canvas.SetFontAndSize(font, fontSize).ResetFillColorRgb(); + canvas.SetFontAndSize(font, fontSize); + if (color != null) { + canvas.SetColor(color, true); + } return iText.IO.Util.JavaUtil.GetStringForBytes(stream.GetBytes()); } + [System.ObsoleteAttribute(@"Will be removed in 7.1. Use GenerateDefaultAppearanceString(iText.Kernel.Font.PdfFont, float, iText.Kernel.Colors.Color, iText.Kernel.Pdf.PdfResources) instead." + )] + protected internal virtual String GenerateDefaultAppearanceString(PdfFont font, int fontSize, PdfResources + res) { + return GenerateDefaultAppearanceString(font, (float)fontSize, color, res); + } + /// protected internal virtual Object[] GetFontAndSize(PdfDictionary asNormal) { Object[] fontAndSize = new Object[2]; @@ -2375,11 +2792,20 @@ protected internal virtual Object[] GetFontAndSize(PdfDictionary asNormal) { if (asNormal != null) { resources = asNormal.GetAsDictionary(PdfName.Resources); } + if (resources == null) { + PdfDocument document = GetDocument(); + if (document != null) { + PdfDictionary acroformDictionary = document.GetCatalog().GetPdfObject().GetAsDictionary(PdfName.AcroForm); + if (acroformDictionary != null) { + resources = acroformDictionary.GetAsDictionary(PdfName.DR); + } + } + } if (resources != null) { PdfDictionary fontDic = resources.GetAsDictionary(PdfName.Font); - if (fontDic != null) { - String str = GetDefaultAppearance().ToUnicodeString(); - Object[] dab = SplitDAelements(str); + PdfString defaultAppearance = GetDefaultAppearance(); + if (fontDic != null && defaultAppearance != null) { + Object[] dab = SplitDAelements(defaultAppearance.ToUnicodeString()); PdfName fontName = new PdfName(dab[DA_FONT].ToString()); if (font != null) { fontAndSize[0] = font; @@ -2408,7 +2834,7 @@ protected internal virtual Object[] GetFontAndSize(PdfDictionary asNormal) { fontAndSize[1] = fontSize; } else { - fontAndSize[1] = DEFAULT_FONT_SIZE; + fontAndSize[1] = (float)DEFAULT_FONT_SIZE; } } } @@ -2423,7 +2849,7 @@ protected internal virtual Object[] GetFontAndSize(PdfDictionary asNormal) { fontAndSize[1] = fontSize; } else { - fontAndSize[1] = DEFAULT_FONT_SIZE; + fontAndSize[1] = (float)DEFAULT_FONT_SIZE; } } return fontAndSize; @@ -2444,13 +2870,15 @@ protected internal static Object[] SplitDAelements(String da) { if (@operator.Equals("Tf")) { if (stack.Count >= 2) { ret[DA_FONT] = stack[stack.Count - 2]; - ret[DA_SIZE] = System.Convert.ToInt32(stack[stack.Count - 1]); + ret[DA_SIZE] = System.Convert.ToSingle(stack[stack.Count - 1], System.Globalization.CultureInfo.InvariantCulture + ); } } else { if (@operator.Equals("g")) { if (stack.Count >= 1) { - float gray = System.Convert.ToSingle(stack[stack.Count - 1]); + float gray = System.Convert.ToSingle(stack[stack.Count - 1], System.Globalization.CultureInfo.InvariantCulture + ); if (gray != 0) { ret[DA_COLOR] = new DeviceGray(gray); } @@ -2459,19 +2887,26 @@ protected internal static Object[] SplitDAelements(String da) { else { if (@operator.Equals("rg")) { if (stack.Count >= 3) { - float red = System.Convert.ToSingle(stack[stack.Count - 3]); - float green = System.Convert.ToSingle(stack[stack.Count - 2]); - float blue = System.Convert.ToSingle(stack[stack.Count - 1]); + float red = System.Convert.ToSingle(stack[stack.Count - 3], System.Globalization.CultureInfo.InvariantCulture + ); + float green = System.Convert.ToSingle(stack[stack.Count - 2], System.Globalization.CultureInfo.InvariantCulture + ); + float blue = System.Convert.ToSingle(stack[stack.Count - 1], System.Globalization.CultureInfo.InvariantCulture + ); ret[DA_COLOR] = new DeviceRgb(red, green, blue); } } else { if (@operator.Equals("k")) { if (stack.Count >= 4) { - float cyan = System.Convert.ToSingle(stack[stack.Count - 4]); - float magenta = System.Convert.ToSingle(stack[stack.Count - 3]); - float yellow = System.Convert.ToSingle(stack[stack.Count - 2]); - float black = System.Convert.ToSingle(stack[stack.Count - 1]); + float cyan = System.Convert.ToSingle(stack[stack.Count - 4], System.Globalization.CultureInfo.InvariantCulture + ); + float magenta = System.Convert.ToSingle(stack[stack.Count - 3], System.Globalization.CultureInfo.InvariantCulture + ); + float yellow = System.Convert.ToSingle(stack[stack.Count - 2], System.Globalization.CultureInfo.InvariantCulture + ); + float black = System.Convert.ToSingle(stack[stack.Count - 1], System.Globalization.CultureInfo.InvariantCulture + ); ret[DA_COLOR] = new DeviceCmyk(cyan, magenta, yellow, black); } } @@ -2496,19 +2931,14 @@ protected internal static Object[] SplitDAelements(String da) { /// a /// /// - /// a positive integer + /// the size of the font /// the initial value - /// - /// the - /// Form XObject - /// that was drawn - /// - protected internal virtual void DrawTextAppearance(Rectangle rect, PdfFont font, int fontSize, String value + protected internal virtual void DrawTextAppearance(Rectangle rect, PdfFont font, float fontSize, String value , PdfFormXObject appearance) { PdfStream stream = ((PdfStream)new PdfStream().MakeIndirect(GetDocument())); PdfResources resources = appearance.GetResources(); PdfCanvas canvas = new PdfCanvas(stream, resources, GetDocument()); - SetDefaultAppearance(GenerateDefaultAppearanceString(font, fontSize, resources)); + SetDefaultAppearance(GenerateDefaultAppearanceString(font, fontSize, color, resources)); float height = rect.GetHeight(); float width = rect.GetWidth(); PdfFormXObject xObject = new PdfFormXObject(new Rectangle(0, 0, width, height)); @@ -2526,7 +2956,7 @@ protected internal virtual void DrawTextAppearance(Rectangle rect, PdfFont font, if (justification == null) { justification = 0; } - float x = 0; + float x = 2; TextAlignment? textAlignment = TextAlignment.LEFT; if (justification == ALIGN_RIGHT) { textAlignment = TextAlignment.RIGHT; @@ -2538,26 +2968,43 @@ protected internal virtual void DrawTextAppearance(Rectangle rect, PdfFont font, x = rect.GetWidth() / 2; } } - new iText.Layout.Canvas(canvas, GetDocument(), new Rectangle(0, -height, 0, 2 * height)).ShowTextAligned(paragraph - , x, rect.GetHeight() / 2, textAlignment, VerticalAlignment.MIDDLE); + iText.Layout.Canvas modelCanvas = new iText.Layout.Canvas(canvas, GetDocument(), new Rectangle(0, -height, + 0, 2 * height)); + modelCanvas.SetProperty(Property.APPEARANCE_STREAM_LAYOUT, true); + modelCanvas.ShowTextAligned(paragraph, x, rect.GetHeight() / 2, textAlignment, VerticalAlignment.MIDDLE); canvas.RestoreState().EndVariableText(); appearance.GetPdfObject().SetData(stream.GetBytes()); } + /// Draws the visual appearance of text in a form field. + /// the location on the page for the list field + /// + /// a + /// + /// + /// the size of the font + /// the initial value + [System.ObsoleteAttribute(@"Will be removed in 7.1. Use DrawTextAppearance(iText.Kernel.Geom.Rectangle, iText.Kernel.Font.PdfFont, float, System.String, iText.Kernel.Pdf.Xobject.PdfFormXObject) instead." + )] + protected internal virtual void DrawTextAppearance(Rectangle rect, PdfFont font, int fontSize, String value + , PdfFormXObject appearance) { + DrawTextAppearance(rect, font, (float)fontSize, value, appearance); + } + /// Draws the visual appearance of multiline text in a form field. /// the location on the page for the list field /// /// a /// /// - /// a positive integer + /// the size of the font /// the initial value - protected internal virtual void DrawMultiLineTextAppearance(Rectangle rect, PdfFont font, int fontSize, String - value, PdfFormXObject appearance) { + protected internal virtual void DrawMultiLineTextAppearance(Rectangle rect, PdfFont font, float fontSize, + String value, PdfFormXObject appearance) { PdfStream stream = ((PdfStream)new PdfStream().MakeIndirect(GetDocument())); PdfResources resources = appearance.GetResources(); PdfCanvas canvas = new PdfCanvas(stream, resources, GetDocument()); - SetDefaultAppearance(GenerateDefaultAppearanceString(font, fontSize, resources)); + SetDefaultAppearance(GenerateDefaultAppearanceString(font, fontSize, color, resources)); float width = rect.GetWidth(); float height = rect.GetHeight(); IList strings = font.SplitString(value, fontSize, width - 6); @@ -2565,6 +3012,7 @@ protected internal virtual void DrawMultiLineTextAppearance(Rectangle rect, PdfF canvas.BeginVariableText().SaveState().Rectangle(3, 3, width - 6, height - 6).Clip().NewPath(); iText.Layout.Canvas modelCanvas = new iText.Layout.Canvas(canvas, GetDocument(), new Rectangle(3, 0, Math. Max(0, width - 6), Math.Max(0, height - 2))); + modelCanvas.SetProperty(Property.APPEARANCE_STREAM_LAYOUT, true); for (int index = 0; index < strings.Count; index++) { bool? isFull = modelCanvas.GetRenderer().GetPropertyAsBoolean(Property.FULL); if (true.Equals(isFull)) { @@ -2594,6 +3042,21 @@ protected internal virtual void DrawMultiLineTextAppearance(Rectangle rect, PdfF appearance.GetPdfObject().SetData(stream.GetBytes()); } + /// Draws the visual appearance of multiline text in a form field. + /// the location on the page for the list field + /// + /// a + /// + /// + /// the size of the font + /// the initial value + [System.ObsoleteAttribute(@"Will be removed in 7.1. Use DrawMultiLineTextAppearance(iText.Kernel.Geom.Rectangle, iText.Kernel.Font.PdfFont, float, System.String, iText.Kernel.Pdf.Xobject.PdfFormXObject) instead." + )] + protected internal virtual void DrawMultiLineTextAppearance(Rectangle rect, PdfFont font, int fontSize, String + value, PdfFormXObject appearance) { + DrawMultiLineTextAppearance(rect, font, (float)fontSize, value, appearance); + } + /// Draws a border using the borderWidth and borderColor of the form field. /// /// the @@ -2605,6 +3068,8 @@ protected internal virtual void DrawMultiLineTextAppearance(Rectangle rect, PdfF protected internal virtual void DrawBorder(PdfCanvas canvas, PdfFormXObject xObject, float width, float height ) { canvas.SaveState(); + float borderWidth = GetBorderWidth(); + PdfDictionary bs = GetWidgets()[0].GetBorderStyle(); if (borderWidth < 0) { borderWidth = 0; } @@ -2617,7 +3082,40 @@ protected internal virtual void DrawBorder(PdfCanvas canvas, PdfFormXObject xObj } if (borderWidth > 0) { borderWidth = Math.Max(1, borderWidth); - canvas.SetStrokeColor(borderColor).SetLineWidth(borderWidth).Rectangle(0, 0, width, height).Stroke(); + canvas.SetStrokeColor(borderColor).SetLineWidth(borderWidth); + if (bs != null) { + PdfName borderType = bs.GetAsName(PdfName.S); + if (borderType != null && borderType.Equals(PdfName.D)) { + PdfArray dashArray = bs.GetAsArray(PdfName.D); + if (dashArray != null) { + int unitsOn = dashArray.GetAsNumber(0) != null ? dashArray.GetAsNumber(0).IntValue() : 0; + int unitsOff = dashArray.GetAsNumber(1) != null ? dashArray.GetAsNumber(1).IntValue() : 0; + canvas.SetLineDash(unitsOn, unitsOff, 0); + } + } + } + canvas.Rectangle(0, 0, width, height).Stroke(); + } + ApplyRotation(xObject, height, width); + canvas.RestoreState(); + } + + protected internal virtual void DrawRadioBorder(PdfCanvas canvas, PdfFormXObject xObject, float width, float + height) { + canvas.SaveState(); + float borderWidth = GetBorderWidth(); + float cx = width / 2; + float cy = height / 2; + if (borderWidth < 0) { + borderWidth = 0; + } + float r = (Math.Min(width, height) - borderWidth) / 2; + if (backgroundColor != null) { + canvas.SetFillColor(backgroundColor).Circle(cx, cy, r + borderWidth / 2).Fill(); + } + if (borderWidth > 0 && borderColor != null) { + borderWidth = Math.Max(1, borderWidth); + canvas.SetStrokeColor(borderColor).SetLineWidth(borderWidth).Circle(cx, cy, r).Stroke(); } ApplyRotation(xObject, height, width); canvas.RestoreState(); @@ -2633,11 +3131,11 @@ protected internal virtual void DrawRadioAppearance(float width, float height, S Rectangle rect = new Rectangle(0, 0, width, height); PdfFormXObject xObjectOn = new PdfFormXObject(rect); PdfFormXObject xObjectOff = new PdfFormXObject(rect); - DrawBorder(canvasOn, xObjectOn, width, height); + DrawRadioBorder(canvasOn, xObjectOn, width, height); DrawRadioField(canvasOn, width, height, true); PdfStream streamOff = ((PdfStream)new PdfStream().MakeIndirect(GetDocument())); PdfCanvas canvasOff = new PdfCanvas(streamOff, new PdfResources(), GetDocument()); - DrawBorder(canvasOff, xObjectOff, width, height); + DrawRadioBorder(canvasOff, xObjectOff, width, height); if (pdfAConformanceLevel != null && (pdfAConformanceLevel.GetPart().Equals("2") || pdfAConformanceLevel.GetPart ().Equals("3"))) { xObjectOn.GetResources(); @@ -2695,16 +3193,16 @@ protected internal virtual void DrawCheckAppearance(float width, float height, S PdfFormXObject xObjectOn = new PdfFormXObject(rect); PdfFormXObject xObjectOff = new PdfFormXObject(rect); DrawBorder(canvasOn, xObjectOn, width, height); - DrawCheckBox(canvasOn, width, height, DEFAULT_FONT_SIZE, true); + DrawCheckBox(canvasOn, width, height, (float)DEFAULT_FONT_SIZE, true); PdfStream streamOff = ((PdfStream)new PdfStream().MakeIndirect(GetDocument())); PdfCanvas canvasOff = new PdfCanvas(streamOff, new PdfResources(), GetDocument()); DrawBorder(canvasOff, xObjectOff, width, height); - DrawCheckBox(canvasOff, width, height, DEFAULT_FONT_SIZE, false); + DrawCheckBox(canvasOff, width, height, (float)DEFAULT_FONT_SIZE, false); PdfWidgetAnnotation widget = GetWidgets()[0]; xObjectOn.GetPdfObject().GetOutputStream().WriteBytes(streamOn.GetBytes()); xObjectOn.GetResources().AddFont(GetDocument(), GetFont()); - SetDefaultAppearance(GenerateDefaultAppearanceString(font, fontSize == 0 ? DEFAULT_FONT_SIZE : fontSize, xObjectOn - .GetResources())); + SetDefaultAppearance(GenerateDefaultAppearanceString(font, fontSize == 0 ? (float)DEFAULT_FONT_SIZE : fontSize + , color, xObjectOn.GetResources())); xObjectOff.GetPdfObject().GetOutputStream().WriteBytes(streamOff.GetBytes()); xObjectOff.GetResources().AddFont(GetDocument(), GetFont()); PdfDictionary normalAppearance = new PdfDictionary(); @@ -2770,13 +3268,13 @@ protected internal virtual void DrawPdfA2CheckAppearance(float width, float heig /// a /// /// - /// a positive integer + /// the size of the font /// /// a new /// /// protected internal virtual PdfFormXObject DrawPushButtonAppearance(float width, float height, String text, - PdfFont font, int fontSize) { + PdfFont font, float fontSize) { PdfStream stream = ((PdfStream)new PdfStream().MakeIndirect(GetDocument())); PdfCanvas canvas = new PdfCanvas(stream, new PdfResources(), GetDocument()); PdfFormXObject xObject = new PdfFormXObject(new Rectangle(0, 0, width, height)); @@ -2798,7 +3296,7 @@ protected internal virtual PdfFormXObject DrawPushButtonAppearance(float width, } else { DrawButton(canvas, 0, 0, width, height, text, font, fontSize); - SetDefaultAppearance(GenerateDefaultAppearanceString(font, fontSize, new PdfResources())); + SetDefaultAppearance(GenerateDefaultAppearanceString(font, fontSize, color, new PdfResources())); xObject.GetResources().AddFont(GetDocument(), font); } } @@ -2806,6 +3304,26 @@ protected internal virtual PdfFormXObject DrawPushButtonAppearance(float width, return xObject; } + /// Draws the appearance for a push button. + /// the width of the pushbutton + /// the width of the pushbutton + /// the text to display on the button + /// + /// a + /// + /// + /// the size of the font + /// + /// a new + /// + /// + [System.ObsoleteAttribute(@"Will be removed in 7.1. Use DrawPushButtonAppearance(float, float, System.String, iText.Kernel.Font.PdfFont, float) instead." + )] + protected internal virtual PdfFormXObject DrawPushButtonAppearance(float width, float height, String text, + PdfFont font, int fontSize) { + return DrawPushButtonAppearance(width, height, text, font, (float)fontSize); + } + /// Performs the low-level drawing operations to draw a button object. /// /// the @@ -2821,16 +3339,42 @@ protected internal virtual PdfFormXObject DrawPushButtonAppearance(float width, /// a /// /// - /// a positive integer + /// the size of the font protected internal virtual void DrawButton(PdfCanvas canvas, float x, float y, float width, float height, - String text, PdfFont font, int fontSize) { + String text, PdfFont font, float fontSize) { if (color == null) { color = Color.BLACK; } Paragraph paragraph = new Paragraph(text).SetFont(font).SetFontSize(fontSize).SetMargin(0).SetMultipliedLeading (1).SetVerticalAlignment(VerticalAlignment.MIDDLE); - new iText.Layout.Canvas(canvas, GetDocument(), new Rectangle(0, -height, width, 2 * height)).ShowTextAligned - (paragraph, width / 2, height / 2, TextAlignment.CENTER, VerticalAlignment.MIDDLE); + iText.Layout.Canvas modelCanvas = new iText.Layout.Canvas(canvas, GetDocument(), new Rectangle(0, -height, + width, 2 * height)); + modelCanvas.SetProperty(Property.APPEARANCE_STREAM_LAYOUT, true); + modelCanvas.ShowTextAligned(paragraph, width / 2, height / 2, TextAlignment.CENTER, VerticalAlignment.MIDDLE + ); + } + + /// Performs the low-level drawing operations to draw a button object. + /// + /// the + /// + /// of the page to draw on. + /// + /// the x coordinate of the lower left corner of the button rectangle + /// the y coordinate of the lower left corner of the button rectangle + /// the width of the button + /// the width of the button + /// the text to display on the button + /// + /// a + /// + /// + /// the size of the font + [System.ObsoleteAttribute(@"Will be removed in 7.1. Use DrawButton(iText.Kernel.Pdf.Canvas.PdfCanvas, float, float, float, float, System.String, iText.Kernel.Font.PdfFont, float) instead." + )] + protected internal virtual void DrawButton(PdfCanvas canvas, float x, float y, float width, float height, + String text, PdfFont font, int fontSize) { + DrawButton(canvas, x, y, width, height, text, font, (float)fontSize); } /// Performs the low-level drawing operations to draw a checkbox object. @@ -2841,10 +3385,10 @@ protected internal virtual void DrawButton(PdfCanvas canvas, float x, float y, f /// /// the width of the button /// the width of the button - /// a positive integer + /// the size of the font /// the boolean value of the checkbox - protected internal virtual void DrawCheckBox(PdfCanvas canvas, float width, float height, int fontSize, bool - on) { + protected internal virtual void DrawCheckBox(PdfCanvas canvas, float width, float height, float fontSize, + bool on) { if (!on) { return; } @@ -2861,6 +3405,23 @@ protected internal virtual void DrawCheckBox(PdfCanvas canvas, float width, floa (text, fontSize)) / 2, (height - ufont.GetAscent(text, fontSize)) / 2).ShowText(text).EndText(); } + /// Performs the low-level drawing operations to draw a checkbox object. + /// + /// the + /// + /// of the page to draw on. + /// + /// the width of the button + /// the width of the button + /// the size of the font + /// the boolean value of the checkbox + [System.ObsoleteAttribute(@"Will be removed in 7.1. Use DrawCheckBox(iText.Kernel.Pdf.Canvas.PdfCanvas, float, float, float, bool) instead." + )] + protected internal virtual void DrawCheckBox(PdfCanvas canvas, float width, float height, int fontSize, bool + on) { + DrawCheckBox(canvas, width, height, (float)fontSize, on); + } + protected internal virtual void DrawPdfACheckBox(PdfCanvas canvas, float width, float height, bool on) { if (!on) { return; @@ -2900,7 +3461,8 @@ protected internal virtual void DrawPdfACheckBox(PdfCanvas canvas, float width, canvas.SaveState(); canvas.ResetFillColorRgb(); canvas.ConcatMatrix(width, 0, 0, height, 0, 0); - canvas.GetContentStream().GetOutputStream().WriteBytes(appearanceString.GetBytes()); + canvas.GetContentStream().GetOutputStream().WriteBytes(appearanceString.GetBytes(iText.IO.Util.EncodingUtil.ISO_8859_1 + )); canvas.RestoreState(); } @@ -2961,5 +3523,9 @@ private String OptionsArrayToString(PdfArray options) { value = value.JSubstring(0, value.Length - 1); return value; } + + private static double DegreeToRadians(double angle) { + return Math.PI * angle / 180.0; + } } } diff --git a/itext/itext.forms/itext/forms/fields/PdfTextFormField.cs b/itext/itext.forms/itext/forms/fields/PdfTextFormField.cs index 0b09259a9c..2a1e8ede02 100644 --- a/itext/itext.forms/itext/forms/fields/PdfTextFormField.cs +++ b/itext/itext.forms/itext/forms/fields/PdfTextFormField.cs @@ -67,7 +67,6 @@ protected internal PdfTextFormField(PdfWidgetAnnotation widget, PdfDocument pdfD protected internal PdfTextFormField(PdfDictionary pdfObject) : base(pdfObject) { - SetBorderWidth(0); } /// Returns Tx, the form type for textual form fields. diff --git a/itext/itext.forms/itext/forms/xfa/XfaForm.cs b/itext/itext.forms/itext/forms/xfa/XfaForm.cs index 70f06c5460..4f178b033f 100644 --- a/itext/itext.forms/itext/forms/xfa/XfaForm.cs +++ b/itext/itext.forms/itext/forms/xfa/XfaForm.cs @@ -673,6 +673,8 @@ private void ExtractNodes() { datasetsNode = (XElement)xfaNodes["datasets"]; datasetsSom = new Xml2SomDatasets(datasetsNode.FirstNode); + XElement dataNode = FindDataNode(datasetsNode); + datasetsSom = new Xml2SomDatasets(dataNode != null ? dataNode : datasetsNode.FirstNode); } if (datasetsNode == null) { @@ -714,6 +716,12 @@ private XNode GetFirstElementNode(XNode src) return result; } + private XElement FindDataNode(XElement datasetsNode) + { + return datasetsNode.Element("{xfa}data"); + } + + private class UpperCaseUTF8Encoding : UTF8Encoding { // Code from a blog http://www.distribucon.com/blog/CategoryView,category,XML.aspx diff --git a/itext/itext.forms/itext/forms/xfa/Xml2SomDatasets.cs b/itext/itext.forms/itext/forms/xfa/Xml2SomDatasets.cs index 3b3b3413d2..9a10bad2b7 100644 --- a/itext/itext.forms/itext/forms/xfa/Xml2SomDatasets.cs +++ b/itext/itext.forms/itext/forms/xfa/Xml2SomDatasets.cs @@ -44,7 +44,6 @@ source product. using System; using System.Collections.Generic; using System.Linq; -using System.Xml; using System.Xml.Linq; namespace iText.Forms.Xfa @@ -162,29 +161,21 @@ private void ProcessDatasetsInternal(XNode n) String s = EscapeSom(((XElement) n2).Name.LocalName); int? i = ss.Get(s); if (i == null) - { - i = 0; - } - else - { - i += 1; - } - ss[s] = i; - if (HasChildren(n2)) - { - stack.Push(s + "[" + i.ToString() + "]"); - ProcessDatasetsInternal(n2); - stack.Pop(); - } - else - { - stack.Push(s + "[" + i.ToString() + "]"); - String unstack = PrintStack(); - order.Add(unstack); - InverseSearchAdd(unstack); - name2Node[unstack] = n2; - stack.Pop(); - } + i = 0; + else + i = i + 1; + ss[s] = i; + stack.Push(string.Format("{0}[{1}]", s, i)); + if (HasChildren(n2)) + { + ProcessDatasetsInternal(n2); + } + String unstack = PrintStack(); + order.Add(unstack); + InverseSearchAdd(unstack); + name2Node[unstack] = n2; + stack.Pop(); + } n2 = n2 is XElement ? ((XElement) n2).NextNode : (n2 is XText ? ((XText)n2).NextNode : null); } diff --git a/itext/itext.hyph/Properties/AssemblyInfo.cs b/itext/itext.hyph/Properties/AssemblyInfo.cs index 184652d85c..8a81341ea8 100644 --- a/itext/itext.hyph/Properties/AssemblyInfo.cs +++ b/itext/itext.hyph/Properties/AssemblyInfo.cs @@ -15,5 +15,5 @@ [assembly: Guid("56137079-541a-425a-ab97-43af63793c97")] -[assembly: AssemblyVersion("7.0.0.0")] -[assembly: AssemblyFileVersion("7.0.0.0")] +[assembly: AssemblyVersion("7.0.1.0")] +[assembly: AssemblyFileVersion("7.0.1.0")] diff --git a/itext/itext.io/Properties/AssemblyInfo.cs b/itext/itext.io/Properties/AssemblyInfo.cs index 25113447cb..3d106d1ee6 100644 --- a/itext/itext.io/Properties/AssemblyInfo.cs +++ b/itext/itext.io/Properties/AssemblyInfo.cs @@ -21,5 +21,5 @@ [assembly: Guid("39631ecb-1d39-4eb2-b775-37bd34cbf5a4")] -[assembly: AssemblyVersion("7.0.0.0")] -[assembly: AssemblyFileVersion("7.0.0.0")] +[assembly: AssemblyVersion("7.0.1.0")] +[assembly: AssemblyFileVersion("7.0.1.0")] diff --git a/itext/itext.io/itext/io/IOException.cs b/itext/itext.io/itext/io/IOException.cs index 9cdaaebac2..ac2777e261 100644 --- a/itext/itext.io/itext/io/IOException.cs +++ b/itext/itext.io/itext/io/IOException.cs @@ -46,217 +46,294 @@ source product. using iText.IO.Util; namespace iText.IO { + /// Exception class for exceptions in io module. public class IOException : Exception { - public const String _1BitSamplesAreNotSupportedForHorizontalDifferencingPredictor = "{0} bit.samples.are.not.supported.for.horizontal.differencing.predictor"; + public const String _1BitSamplesAreNotSupportedForHorizontalDifferencingPredictor = "{0} bit samples are not supported for horizontal differencing predictor."; - public const String _1CorruptedJfifMarker = "{0} corrupted.jfif.marker"; + public const String _1CorruptedJfifMarker = "{0} corrupted jfif marker."; - public const String _1IsNotAValidJpegFile = "{0} is.not.a.valid.jpeg.file"; + public const String _1IsNotAValidJpegFile = "{0} is not a valid jpeg file."; - public const String _1MustHave8BitsPerComponent = "{0} must.have.8.bits.per.component"; + public const String _1MustHave8BitsPerComponent = "{0} must have 8 bits per component."; - public const String _1UnsupportedJpegMarker2 = "{0} unsupported.jpeg.marker {1}"; + public const String _1UnsupportedJpegMarker2 = "{0} unsupported jpeg marker {1}."; - public const String _1IsNotAnAfmOrPfmFontFile = "{0} is.not.an.afm.or.pfm.font.file"; + public const String _1IsNotAnAfmOrPfmFontFile = "{0} is not an afm or pfm font file."; public const String _1NotFoundAsFileOrResource = "{0} not found as file or resource."; - public const String AllFillBitsPrecedingEolCodeMustBe0 = "all.fill.bits.preceding.eol.code.must.be.0"; + public const String AllFillBitsPrecedingEolCodeMustBe0 = "All fill bits preceding eol code must be 0."; - public const String BadEndiannessTagNot0x4949Or0x4d4d = "bad.endianness.tag.not.0x4949.or.0x4d4d"; + [Obsolete] + public const String BadEndiannessTagNot0x4949Or0x4d4d = "Bad endianness tag not 0x4949 or 0x4d4d."; - public const String BadMagicNumberShouldBe42 = "bad.magic.number.should.be.42"; + public const String BadEndiannessTag0x4949Or0x4d4d = "Bad endianness tag: 0x4949 or 0x4d4d."; - public const String BitsPerComponentMustBe1_2_4or8 = "bits.per.component.must.be.1.2.4.or.8"; + public const String BadMagicNumberShouldBe42 = "Bad magic number. Should be 42."; - public const String BitsPerSample1IsNotSupported = "bits.per.sample {0} is.not.supported"; + public const String BitsPerComponentMustBe1_2_4or8 = "Bits per component must be 1, 2, 4 or 8."; - public const String BmpImageException = "bmp.image.exception"; + public const String BitsPerSample1IsNotSupported = "Bits per sample {0} is not supported."; - public const String BytesCanBeAssignedToByteArrayOutputStreamOnly = "bytes.can.be.assigned.to.bytearrayoutputstream.only"; + public const String BmpImageException = "Bmp image exception."; - public const String BytesCanBeResetInByteArrayOutputStreamOnly = "bytes.can.be.reset.in.bytearrayoutputstream.only"; + public const String BytesCanBeAssignedToByteArrayOutputStreamOnly = "Bytes can be assigned to ByteArrayOutputStream only."; - public const String CannotGetTiffImageColor = "cannot.get.tiff.image.color"; + public const String BytesCanBeResetInByteArrayOutputStreamOnly = "Bytes can be reset in ByteArrayOutputStream only."; - public const String CannotFind1Frame = "cannot.find {0} frame"; + public const String CannotGetTiffImageColor = "Cannot get TIFF image color."; - public const String CannotHandleBoxSizesHigherThan2_32 = "cannot.handle.box.sizes.higher.than.2.32"; + public const String CannotFind1Frame = "Cannot find {0} frame."; - public const String CannotInflateTiffImage = "cannot.inflate.tiff.image"; + public const String CannotHandleBoxSizesHigherThan2_32 = "Cannot handle box sizes higher than 2^32."; - public const String CannotReadTiffImage = "cannot.read.tiff.image"; + public const String CannotInflateTiffImage = "Cannot inflate TIFF image."; - public const String CannotWriteByte = "cannot.write.byte"; + public const String CannotReadTiffImage = "Cannot read TIFF image."; - public const String CannotWriteBytes = "cannot.write.bytes"; + public const String CannotWriteByte = "Cannot write byte."; - public const String CannotWriteFloatNumber = "cannot.write.float.number"; + public const String CannotWriteBytes = "Cannot write bytes."; - public const String CannotWriteIntNumber = "cannot.write.int.number"; + public const String CannotWriteFloatNumber = "Cannot write float number."; - public const String CcittCompressionTypeMustBeCcittg4Ccittg3_1dOrCcittg3_2d = "ccitt.compression.type.must.be.ccittg4.ccittg3.1d.or.ccittg3.2d"; + public const String CannotWriteIntNumber = "Cannot write int number."; + public const String CcittCompressionTypeMustBeCcittg4Ccittg3_1dOrCcittg3_2d = "CCITT compression type must be CCITTG4, CCITTG3_1D or CCITTG3_2D."; + + [Obsolete] public const String TheCmap1WasNotFound = "The CMap {0} was not found"; - public const String ComponentsMustBe1_3Or4 = "components.must.be.1.3.or.4"; + public const String Cmap1WasNotFound = "The CMap {0} was not found."; + + public const String ComponentsMustBe1_3Or4 = "Components must be 1, 3 or 4."; - public const String Compression1IsNotSupported = "compression {0} is.not.supported"; + public const String Compression1IsNotSupported = "Compression {0} is not supported."; - public const String ColorDepthIsNotSupported = "the.color.depth {0} is.not.supported"; + public const String ColorDepthIsNotSupported = "The color depth {0} is not supported."; - public const String ColorSpaceIsNotSupported = "the.color.space {0} is.not.supported"; + public const String ColorSpaceIsNotSupported = "The color space {0} is not supported."; - public const String CompressionJpegIsOnlySupportedWithASingleStripThisImageHas1Strips = "compression.jpeg.is.only.supported.with.a.single.strip.this.image.has {0} strips"; + public const String CompressionJpegIsOnlySupportedWithASingleStripThisImageHas1Strips = "Compression jpeg is only supported with a single strip. This image has {0} strips."; + [Obsolete] public const String DirectoryNumberTooLarge = "directory.number.too.large"; - public const String EolCodeWordEncounteredInBlackRun = "eol.code.word.encountered.in.black.run"; + public const String DirectoryNumberIsTooLarge = "Directory number is too large."; + + public const String EolCodeWordEncounteredInBlackRun = "EOL code word encountered in Black run."; + + public const String EolCodeWordEncounteredInWhiteRun = "EOL code word encountered in White run."; + + public const String ErrorAtFilePointer1 = "Error at file pointer {0}."; + + public const String ErrorReadingString = "Error reading string."; + + public const String ErrorWithJpMarker = "Error with JP marker."; + + public const String ExpectedFtypMarker = "Expected FTYP marker."; + + public const String ExpectedIhdrMarker = "Expected IHDR marker."; + + public const String ExpectedJpMarker = "Expected JP marker."; + + public const String ExpectedJp2hMarker = "Expected JP2H marker."; + + public const String ExtraSamplesAreNotSupported = "Extra samples are not supported."; + + public const String FdfStartxrefNotFound = "FDF startxref not found."; + + public const String FirstScanlineMustBe1dEncoded = "First scanline must be 1D encoded."; + + public const String FontFile1NotFound = "Font file {0} not found."; + + public const String ImageFormatCannotBeRecognized = "Image format cannot be recognized."; - public const String EolCodeWordEncounteredInWhiteRun = "eol.code.word.encountered.in.white.run"; + public const String GifImageException = "GIF image exception."; - public const String ErrorAtFilePointer1 = "error.at.file.pointer {0}"; + public const String GtNotExpected = "'>' not expected."; - public const String ErrorReadingString = "error.reading.string"; + public const String GifSignatureNotFound = "GIF signature not found."; - public const String ErrorWithJpMarker = "error.with.jp.marker"; + public const String IllegalValueForPredictorInTiffFile = "Illegal value for predictor in TIFF file."; - public const String ExpectedFtypMarker = "expected.ftyp.marker"; + [Obsolete] + public const String Font1IsNotRecognized = "Font {0} is not recognized"; - public const String ExpectedIhdrMarker = "expected.ihdr.marker"; + [Obsolete] + public const String FontIsNotRecognized = "Font is not recognized"; - public const String ExpectedJpMarker = "expected.jp.marker"; + [Obsolete] + public const String ImageCanNotBeAnImageMask = "Image can not be an image mask."; - public const String ExpectedJp2hMarker = "expected.jp2h.marker"; + public const String ImageIsNotMaskYouMustCallImageDataMakeMask = "Image is not a mask. You must call ImageData#makeMask()."; - public const String ExtraSamplesAreNotSupported = "extra.samples.are.not.supported"; + public const String ImageMaskCannotContainAnotherImageMask = "Image mask cannot contain another image mask."; - public const String FdfStartxrefNotFound = "fdf.startxref.not.found"; + [Obsolete] + public const String ImageMaskIsNotAMaskDidYouDoMakeMask = "Image is not a mask. You must call ImageData#makeMask()."; - public const String FirstScanlineMustBe1dEncoded = "first.scanline.must.be.1d.encoded"; + public const String IncompletePalette = "Incomplete palette."; - public const String FontFile1NotFound = "font.file {0} not.found"; + [Obsolete] + public const String InvalidTTCFile = "{0} is not a valid TTC file."; - public const String ImageFormatCannotBeRecognized = "image.format.cannot.be.recognized"; + public const String InvalidTtcFile = "{0} is not a valid TTC file."; - public const String GifImageException = "gif.image.exception"; + public const String InvalidBmpFileCompression = "Invalid BMP file compression."; - public const String GtNotExpected = "gt.not.expected"; + public const String InvalidCodeEncountered = "Invalid code encountered."; - public const String GifSignatureNotFound = "gif.signature.not.found"; + public const String InvalidCodeEncounteredWhileDecoding2dGroup3CompressedData = "Invalid code encountered while decoding 2D group 3 compressed data."; - public const String IllegalValueForPredictorInTiffFile = "illegal.value.for.predictor.in.tiff.file"; + public const String InvalidCodeEncounteredWhileDecoding2dGroup4CompressedData = "Invalid code encountered while decoding 2D group 4 compressed data."; - public const String Font1IsNotRecognized = "font {0} is.not.recognized"; + public const String InvalidIccProfile = "Invalid ICC profile."; - public const String FontIsNotRecognized = "font.is.not.recognized"; + public const String InvalidJpeg2000File = "Invalid JPEG2000 file."; - public const String ImageCanNotBeAnImageMask = "image.can.not.be.an.image.mask"; + [Obsolete] + public const String InvalidMagicValueForBmpFile = "Invalid magic value for bmp file. Must be 'BM'"; - public const String ImageMaskCannotContainAnotherImageMask = "image.mask.cannot.contain.another.image.mask"; + public const String InvalidMagicValueForBmpFileMustBeBM = "Invalid magic value for bmp file. Must be 'BM'"; - public const String ImageMaskIsNotAMaskDidYouDoMakeMask = "image.mask.is.not.a.mask.did.you.do.makemask"; + public const String IoException = "I/O exception."; - public const String IncompletePalette = "incomplete.palette"; + public const String Jbig2ImageException = "JBIG2 image exception."; - public const String InvalidTTCFile = "{0} is.not.a.valid.ttc.file"; + public const String JpegImageException = "JPEG image exception."; - public const String InvalidBmpFileCompression = "invalid.bmp.file.compression"; + public const String Jpeg2000ImageException = "JPEG2000 image exception."; - public const String InvalidCodeEncountered = "invalid.code.encountered"; + [Obsolete] + public const String MissingTagSForOjpegCompression = "Missing tag(s) for OJPEG compression"; - public const String InvalidCodeEncounteredWhileDecoding2dGroup3CompressedData = "invalid.code.encountered.while.decoding.2d.group.3.compressed.data"; + public const String MissingTagsForOjpegCompression = "Missing tag(s) for OJPEG compression"; - public const String InvalidCodeEncounteredWhileDecoding2dGroup4CompressedData = "invalid.code.encountered.while.decoding.2d.group.4.compressed.data"; + public const String NValueIsNotSupported = "N value {1} is not supported."; - public const String InvalidIccProfile = "invalid.icc.profile"; + public const String PageNumberMustBeGtEq1 = "Page number must be >= 1."; - public const String InvalidJpeg2000File = "invalid.jpeg2000.file"; + [System.ObsoleteAttribute(@"because naming clash with Com itextpdf io font PdfEncodings may produce confusion with imports Superseded by CharacterCodeException" + )] + public const String PdfEncodings = "Pdf encodings."; - public const String InvalidMagicValueForBmpFile = "invalid.magic.value.for.bmp.file"; + public const String CharacterCodeException = "Character code exception."; - public const String IoException = "io.exception"; + public const String PdfHeaderNotFound = "PDF header not found."; - public const String Jbig2ImageException = "jbig2.image.exception"; + public const String PdfStartxrefNotFound = "PDF startxref not found."; - public const String JpegImageException = "jpeg.image.exception"; + public const String Photometric1IsNotSupported = "Photometric {0} is not supported."; - public const String Jpeg2000ImageException = "jpeg2000.image.exception"; + public const String PlanarImagesAreNotSupported = "Planar images are not supported."; - public const String MissingTagSForOjpegCompression = "missing.tag.s.for.ojpeg.compression"; + [Obsolete] + public const String PngFilterUnknown = "PNG filter unknown."; - public const String NValueIsNotSupported = "N.value.1.is.not.supported"; + public const String UnknownPngFilter = "Unknown PNG filter."; - public const String PageNumberMustBeGtEq1 = "page.number.must.be.gt.eq {0}"; + public const String PngImageException = "PNG image exception."; - public const String PdfEncodings = "pdf.encodings"; + [Obsolete] + public const String PrematureEofWhileReadingJpg = "Premature EOF while reading JPEG."; - public const String PdfHeaderNotFound = "pdf.header.not.found"; + public const String PrematureEofWhileReadingJpeg = "Premature EOF while reading JPEG."; - public const String PdfStartxrefNotFound = "pdf.startxref.not.found"; + public const String ScanlineMustBeginWithEolCodeWord = "Scanline must begin with EOL code word."; - public const String Photometric1IsNotSupported = "photometric.1.is.not.supported"; + public const String ThisImageCanNotBeAnImageMask = "This image can not be an image mask."; - public const String PlanarImagesAreNotSupported = "planar.images.are.not.supported"; + public const String Tiff50StyleLzwCodesAreNotSupported = "TIFF 5.0-style LZW codes are not supported."; - public const String PngFilterUnknown = "png.filter.unknown"; + public const String TiffFillOrderTagMustBeEither1Or2 = "TIFF_FILL_ORDER tag must be either 1 or 2."; - public const String PngImageException = "png.image.exception"; + public const String TiffImageException = "TIFF image exception."; - public const String PrematureEofWhileReadingJpg = "premature.eof.while.reading.jpg"; + [Obsolete] + public const String TTCIndexDoesNotExistInFile = "TTC index doesn't exist in ttc file."; - public const String ScanlineMustBeginWithEolCodeWord = "scanline.must.begin.with.eol.code.word"; + public const String TtcIndexDoesNotExistInThisTtcFile = "TTC index doesn't exist in this TTC file."; - public const String Tiff50StyleLzwCodesAreNotSupported = "tiff.5.0.style.lzw.codes.are.not.supported"; + public const String TilesAreNotSupported = "Tiles are not supported."; - public const String TiffFillOrderTagMustBeEither1Or2 = "tiff.fill.order.tag.must.be.either.1.or.2"; + public const String TransparencyLengthMustBeEqualTo2WithCcittImages = "Transparency length must be equal to 2 with CCITT images"; - public const String TiffImageException = "tiff.image.exception"; + public const String TypeOfFont1IsNotRecognized = "Type of font {0} is not recognized."; - public const String TTCIndexDoesNotExistInFile = "ttc.index.doesn't.exist.in.ttc.file"; + public const String TypeOfFontIsNotRecognized = "Type of font is not recognized."; - public const String TilesAreNotSupported = "tiles.are.not.supported"; + public const String UnexpectedCloseBracket = "Unexpected close bracket."; - public const String TransparencyLengthMustBeEqualTo2WithCcittImages = "transparency.length.must.be.equal.to.2.with.ccitt.images"; + public const String UnexpectedGtGt = "Unexpected '>>'."; - public const String UnexpectedCloseBracket = "unexpected.close.bracket"; + public const String UnknownCompressionType1 = "Unknown compression type {0}."; - public const String UnexpectedGtGt = "unexpected.gt.gt"; + public const String UnknownIOException = "Unknown I/O exception."; - public const String UnknownCompressionType1 = "unknown.compression.type {0}"; + public const String UnsupportedBoxSizeEqEq0 = "Unsupported box size == 0."; - public const String UnknownIOException = "unknown.io.exception"; + public const String UnsupportedEncodingException = "Unsupported encoding exception."; - public const String UnsupportedBoxSizeEqEq0 = "unsupported.box.size.eq.eq.0"; + [Obsolete] + public const String WrongNumberOfComponentsInIccProfile = "ICC profile contains {0} components the image data contains {1} components."; - public const String WrongNumberOfComponentsInIccProfile = "icc.profile.contains {0} components.the.image.data.contains {2} components"; + public const String IccProfileContains0ComponentsWhileImageDataContains1Components = "ICC profile contains {0} components, while the image data contains {1} components."; + /// Object for more details protected internal Object obj; private IList messageParams; + /// Creates a new IOException. + /// the detail message. public IOException(String message) : base(message) { } + /// Creates a new IOException. + /// + /// the cause (which is saved for later retrieval by + /// + /// method). + /// public IOException(Exception cause) : this(UnknownIOException, cause) { } + /// Creates a new IOException. + /// the detail message. + /// an object for more details. public IOException(String message, Object obj) : this(message) { this.obj = obj; } + /// Creates a new IOException. + /// the detail message. + /// + /// the cause (which is saved for later retrieval by + /// + /// method). + /// public IOException(String message, Exception cause) : base(message, cause) { } + /// Creates a new instance of IOException. + /// the detail message. + /// + /// the cause (which is saved for later retrieval by + /// + /// method). + /// + /// an object for more details. public IOException(String message, Exception cause, Object obj) : this(message, cause) { this.obj = obj; } + /// public override String Message { get { if (messageParams == null || messageParams.Count == 0) { @@ -268,12 +345,16 @@ public override String Message { } } + /// Sets additional params for Exception message. + /// additional params. + /// object itself. public virtual iText.IO.IOException SetMessageParams(params Object[] messageParams) { this.messageParams = new List(); this.messageParams.AddAll(messageParams); return this; } + /// Gets additional params for Exception message. protected internal virtual Object[] GetMessageParams() { Object[] parameters = new Object[messageParams.Count]; for (int i = 0; i < messageParams.Count; i++) { diff --git a/itext/itext.io/itext/io/IOExtension.cs b/itext/itext.io/itext/io/IOExtension.cs index f913eead05..c5be20cb2c 100644 --- a/itext/itext.io/itext/io/IOExtension.cs +++ b/itext/itext.io/itext/io/IOExtension.cs @@ -83,6 +83,10 @@ public static byte[] GetBytes(this String str) { return System.Text.Encoding.UTF8.GetBytes(str); } + public static byte[] GetBytes(this String str, Encoding encoding) { + return encoding.GetBytes(str); + } + public static long Seek(this FileStream fs, long offset) { return fs.Seek(offset, SeekOrigin.Begin); } diff --git a/itext/itext.io/itext/io/LogMessageConstant.cs b/itext/itext.io/itext/io/LogMessageConstant.cs index 77fbf09cd5..e262ed3339 100644 --- a/itext/itext.io/itext/io/LogMessageConstant.cs +++ b/itext/itext.io/itext/io/LogMessageConstant.cs @@ -46,81 +46,80 @@ source product. namespace iText.IO { /// Class containing constants to be used in logging. public sealed class LogMessageConstant { - /// Log message. + public const String COLORANT_INTENSITIES_INVALID = "Some of colorant intensities are invalid: they are bigger than 1 or less than 0. We will force them to become 1 or 0 respectively."; + public const String DOCUMENT_ALREADY_HAS_FIELD = "The document already has field {0}. Annotations of the fields with this name will be added to the existing one as children. If you want to have separate fields, please, rename them manually before copying."; - /// Log message. public const String DOCUMENT_SERIALIZATION_EXCEPTION_RAISED = "Unhandled exception while serialization"; - /// Log message. public const String DIRECTONLY_OBJECT_CANNOT_BE_INDIRECT = "DirectOnly object cannot be indirect"; - /// Log message. public const String ELEMENT_DOES_NOT_FIT_AREA = "Element does not fit current area. {0}"; - public const String EXCEPTION_WHILE_UPDATING_XMPMETADATA = "Exception while updating XmpMetadata"; + public const String ELEMENT_WAS_FORCE_PLACED_KEEP_WITH_NEXT_WILL_BE_IGNORED = "Element was placed in a forced way. Keep with next property will be ignored"; - /// Log message. - public const String REMOVING_PAGE_HAS_ALREADY_BEEN_FLUSHED = "The removing page has already been flushed."; + public const String ENCOUNTERED_INVALID_MCR = "Corrupted tag structure: encountered invalid marked content reference - it doesn't refer to any page or any mcid. This content reference will be ignored."; + + public const String EXCEPTION_WHILE_UPDATING_XMPMETADATA = "Exception while updating XmpMetadata"; - /// Log message. public const String FONT_HAS_INVALID_GLYPH = "Font {0} has invalid glyph: {1}"; - /// Log message. public const String FORBID_RELEASE_IS_SET = "ForbidRelease flag is set and release is called. Releasing will not be performed."; - /// Log message. public const String IMAGE_HAS_AMBIGUOUS_SCALE = "The image cannot be auto scaled and scaled by a certain parameter simultaneously"; - /// Log message. public const String IMAGE_HAS_JBIG2DECODE_FILTER = "Image cannot be inline if it has JBIG2Decode filter. It will be added as an ImageXObject"; - /// Log message. public const String IMAGE_HAS_MASK = "Image cannot be inline if it has a Mask"; - /// Log message. public const String IMAGE_HAS_JPXDECODE_FILTER = "Image cannot be inline if it has JPXDecode filter. It will be added as an ImageXObject"; - /// Log message. public const String IMAGE_SIZE_CANNOT_BE_MORE_4KB = "Inline image size cannot be more than 4KB. It will be added as an ImageXObject"; - /// Log message. public const String INVALID_INDIRECT_REFERENCE = "Invalid indirect reference"; - /// Log message. public const String INVALID_KEY_VALUE_KEY_0_HAS_NULL_VALUE = "Invalid key value: key {0} has null value."; - /// Log message. + public const String CALCULATE_HASHCODE_FOR_MODIFIED_PDFNUMBER = "Calculate hashcode for modified PdfNumber."; + public const String MAKE_COPY_OF_CATALOG_DICTIONARY_IS_FORBIDDEN = "Make copy of Catalog dictionary is forbidden."; - /// Log message. - public const String OCSP_STATUS_IS_UNKNOWN = "OCSP status is unknown."; + public const String NOT_TAGGED_PAGES_IN_TAGGED_DOCUMENT = "Not tagged pages are copied to the tagged document. Destination document now may contain not tagged content."; + + public const String PDF_READER_CLOSING_FAILED = "PdfReader closing failed due to the error occurred!"; + + public const String PDF_WRITER_CLOSING_FAILED = "PdfWriter closing failed due to the error occurred!"; + + public const String POPUP_ENTRY_IS_NOT_POPUP_ANNOTATION = "Popup entry in the markup annotations refers not to the annotation with Popup subtype."; - /// Log message. public const String OCSP_STATUS_IS_REVOKED = "OCSP status is revoked."; - /// Log message. + public const String OCSP_STATUS_IS_UNKNOWN = "OCSP status is unknown."; + + public const String ONE_OF_GROUPED_SOURCES_CLOSING_FAILED = "Closing of one of the grouped sources failed."; + public const String ONLY_ONE_OF_ARTBOX_OR_TRIMBOX_CAN_EXIST_IN_THE_PAGE = "Only one of artbox or trimbox can exist on the page. The trimbox will be deleted"; - /// Log message. public const String RECTANGLE_HAS_NEGATIVE_OR_ZERO_SIZES = "The {0} rectangle has negative or zero sizes. It will not be displayed."; - /// Log message. public const String REGISTERING_DIRECTORY = "Registering directory"; - /// Log message. + public const String REMOVING_PAGE_HAS_ALREADY_BEEN_FLUSHED = "The removing page has already been flushed."; + + public const String RENDERER_WAS_NOT_ABLE_TO_PROCESS_KEEP_WITH_NEXT = "The renderer was not able to process keep with next property properly"; + + public const String ROTATION_WAS_NOT_CORRECTLY_PROCESSED_FOR_RENDERER = "Rotation was not correctly processed for {0}"; + public const String SOURCE_DOCUMENT_HAS_ACROFORM_DICTIONARY = "Source document has AcroForm dictionary. The pages you are going to copy may have FormFields, but they will not be copied, because you have not used any IPdfPageExtraCopier"; - /// Log message. public const String START_MARKER_MISSING_IN_PFB_FILE = "Start marker is missing in the pfb file"; - /// Log message. + public const String TAG_STRUCTURE_INIT_FAILED = "Tag structure initialization failed, tag structure is ignored, it might be corrupted."; + public const String UNKNOWN_CMAP = "Unknown CMap {0}"; - /// Log message. public const String UNKNOWN_ERROR_WHILE_PROCESSING_CMAP = "Unknown error while processing CMap."; - /// Log message. public const String TOUNICODE_CMAP_MORE_THAN_2_BYTES_NOT_SUPPORTED = "ToUnicode CMap more than 2 bytes not supported."; public const String WRITER_ENCRYPTION_IS_IGNORED_APPEND = "Writer encryption will be ignored, because append mode is used. Document will preserve the original encryption (or will stay unencrypted)"; @@ -128,5 +127,7 @@ public sealed class LogMessageConstant { public const String WRITER_ENCRYPTION_IS_IGNORED_PRESERVE = "Writer encryption will be ignored, because preservation of encryption is enabled. Document will preserve the original encryption (or will stay unencrypted)"; public const String XREF_ERROR = "Error occurred while reading cross reference table. Cross reference table will be rebuilt."; + + public const String INCORRECT_PAGEROTATION = "Encounterd a page rotation that was not a multiple of 90°/ (Pi/2) when generating default appearances for form fields"; } } diff --git a/itext/itext.io/itext/io/codec/TIFFDirectory.cs b/itext/itext.io/itext/io/codec/TIFFDirectory.cs index c23951637b..015efda1b3 100644 --- a/itext/itext.io/itext/io/codec/TIFFDirectory.cs +++ b/itext/itext.io/itext/io/codec/TIFFDirectory.cs @@ -118,7 +118,7 @@ public TIFFDirectory(RandomAccessFileOrArray stream, int directory) { stream.Seek(0L); int endian = stream.ReadUnsignedShort(); if (!IsValidEndianTag(endian)) { - throw new iText.IO.IOException(iText.IO.IOException.BadEndiannessTagNot0x4949Or0x4d4d); + throw new iText.IO.IOException(iText.IO.IOException.BadEndiannessTag0x4949Or0x4d4d); } isBigEndian = endian == 0x4d4d; int magic = ReadUnsignedShort(stream); @@ -129,7 +129,7 @@ public TIFFDirectory(RandomAccessFileOrArray stream, int directory) { ifd_offset = ReadUnsignedInt(stream); for (int i = 0; i < directory; i++) { if (ifd_offset == 0L) { - throw new iText.IO.IOException(iText.IO.IOException.DirectoryNumberTooLarge); + throw new iText.IO.IOException(iText.IO.IOException.DirectoryNumberIsTooLarge); } stream.Seek(ifd_offset); int entries = ReadUnsignedShort(stream); @@ -162,7 +162,7 @@ public TIFFDirectory(RandomAccessFileOrArray stream, long ifd_offset, int direct stream.Seek(0L); int endian = stream.ReadUnsignedShort(); if (!IsValidEndianTag(endian)) { - throw new iText.IO.IOException(iText.IO.IOException.BadEndiannessTagNot0x4949Or0x4d4d); + throw new iText.IO.IOException(iText.IO.IOException.BadEndiannessTag0x4949Or0x4d4d); } isBigEndian = endian == 0x4d4d; // Seek to the first IFD. @@ -374,15 +374,12 @@ public virtual int GetNumEntries() { /// or null if the tag is not present. /// public virtual TIFFField GetField(int tag) { - int i = -1; - if (fieldIndex.ContainsKey(tag)) { - i = (int)fieldIndex.Get(tag); - } - if (i == -1) { + int? i = fieldIndex.Get(tag); + if (i == null) { return null; } else { - return fields[i]; + return fields[(int)i]; } } @@ -624,7 +621,7 @@ public static int GetNumDirectories(RandomAccessFileOrArray stream) { stream.Seek(0L); int endian = stream.ReadUnsignedShort(); if (!IsValidEndianTag(endian)) { - throw new iText.IO.IOException(iText.IO.IOException.BadEndiannessTagNot0x4949Or0x4d4d); + throw new iText.IO.IOException(iText.IO.IOException.BadEndiannessTag0x4949Or0x4d4d); } bool isBigEndian = endian == 0x4d4d; int magic = ReadUnsignedShort(stream, isBigEndian); diff --git a/itext/itext.io/itext/io/codec/TiffWriter.cs b/itext/itext.io/itext/io/codec/TiffWriter.cs index a99d8d4983..33a1ea1e19 100644 --- a/itext/itext.io/itext/io/codec/TiffWriter.cs +++ b/itext/itext.io/itext/io/codec/TiffWriter.cs @@ -44,6 +44,7 @@ source product. using System; using System.Collections.Generic; using System.IO; +using System.Text; namespace iText.IO.Codec { /// Exports images as TIFF. @@ -234,8 +235,8 @@ public FieldImage(byte[] values) /// Inner class containing info about an ASCII field. public class FieldAscii : TiffWriter.FieldBase { public FieldAscii(int tag, String values) - : base(tag, 2, values.GetBytes().Length + 1) { - byte[] b = values.GetBytes(); + : base(tag, 2, values.GetBytes(Encoding.ASCII).Length + 1) { + byte[] b = values.GetBytes(Encoding.ASCII); data = new byte[b.Length + 1]; System.Array.Copy(b, 0, data, 0, b.Length); } diff --git a/itext/itext.io/itext/io/colors/IccProfile.cs b/itext/itext.io/itext/io/colors/IccProfile.cs index 35e76fdcc3..5db030506e 100644 --- a/itext/itext.io/itext/io/colors/IccProfile.cs +++ b/itext/itext.io/itext/io/colors/IccProfile.cs @@ -69,8 +69,8 @@ public static iText.IO.Colors.IccProfile GetInstance(byte[] data, int numCompone icc.numComponents = nc; // invalid ICC if (nc != numComponents) { - throw new iText.IO.IOException(iText.IO.IOException.WrongNumberOfComponentsInIccProfile).SetMessageParams( - nc, numComponents); + throw new iText.IO.IOException(iText.IO.IOException.IccProfileContains0ComponentsWhileImageDataContains1Components + ).SetMessageParams(nc, numComponents); } return icc; } diff --git a/itext/itext.io/itext/io/font/AdobeGlyphList.cs b/itext/itext.io/itext/io/font/AdobeGlyphList.cs index 7af758d10d..ce1f9e8077 100644 --- a/itext/itext.io/itext/io/font/AdobeGlyphList.cs +++ b/itext/itext.io/itext/io/font/AdobeGlyphList.cs @@ -114,7 +114,7 @@ static AdobeGlyphList() { } // empty on purpose - public static int? NameToUnicode(String name) { + public static int NameToUnicode(String name) { int v = -1; if (names2unicode.ContainsKey(name)) { v = (int)names2unicode.Get(name); diff --git a/itext/itext.io/itext/io/font/FontCache.cs b/itext/itext.io/itext/io/font/FontCache.cs index 00a70922ef..83d3fecd11 100644 --- a/itext/itext.io/itext/io/font/FontCache.cs +++ b/itext/itext.io/itext/io/font/FontCache.cs @@ -54,8 +54,8 @@ public class FontCache { [Obsolete] public const String CMAP_RESOURCE_PATH = FontConstants.RESOURCE_PATH + "cmap/"; - private static readonly IDictionary> allFonts = new Dictionary>(); + private static readonly IDictionary> allCidFonts = new Dictionary>(); private static readonly IDictionary> registryNames = new Dictionary>(); @@ -77,7 +77,7 @@ static FontCache() { try { LoadRegistry(); foreach (String font in registryNames.Get(FONTS_PROP)) { - allFonts[font] = ReadFontProperties(font); + allCidFonts[font] = ReadFontProperties(font); } } catch (Exception) { @@ -110,7 +110,7 @@ public static String GetCompatibleCidFont(String cmap) { foreach (KeyValuePair> e in registryNames) { if (e.Value.Contains(cmap)) { String registry = e.Key; - foreach (KeyValuePair> e1 in allFonts) { + foreach (KeyValuePair> e1 in allCidFonts) { if (registry.Equals(e1.Value.Get(REGISTRY_PROP))) { return e1.Key; } @@ -125,8 +125,13 @@ public static ICollection GetCompatibleCmaps(String fontName) { return registryNames.Get(registry); } + public static IDictionary> GetAllPredefinedCidFonts() { + return allCidFonts; + } + + [System.ObsoleteAttribute(@"Use GetAllPredefinedCidFonts() instead.")] public static IDictionary> GetAllFonts() { - return allFonts; + return allCidFonts; } public static IDictionary> GetRegistryNames() { @@ -156,10 +161,7 @@ public static CMapCidByte GetCid2Byte(String cmap) { public static FontProgram GetFont(String fontName) { String key = GetFontCacheKey(fontName); FontProgram font = null; - if (fontCache.ContainsKey(key)) { - font = fontCache.Get(key); - } - return font; + return fontCache.Get(key); } public static FontProgram SaveFont(FontProgram font, String fontName) { diff --git a/itext/itext.io/itext/io/font/FontConstants.cs b/itext/itext.io/itext/io/font/FontConstants.cs index 8396513b3b..1f879c55cc 100644 --- a/itext/itext.io/itext/io/font/FontConstants.cs +++ b/itext/itext.io/itext/io/font/FontConstants.cs @@ -45,6 +45,11 @@ source product. using System.Collections.Generic; namespace iText.IO.Font { + /// + /// Font constants for + /// + /// and PdfFontFactory. + /// public class FontConstants { internal static readonly ICollection BUILTIN_FONTS_14 = new HashSet(); @@ -72,24 +77,25 @@ static FontConstants() { public const String CMAP_RESOURCE_PATH = "iText.IO.Font.Cmap."; + /// Undefined font style. public const int UNDEFINED = -1; - /// this is a possible style. + /// Normal font style. public const int NORMAL = 0; - /// this is a possible style. + /// Bold font style. public const int BOLD = 1; - /// this is a possible style. + /// Italic font style. public const int ITALIC = 2; - /// this is a possible style. + /// Underline font style. public const int UNDERLINE = 4; - /// this is a possible style. + /// Strikethru font style. public const int STRIKETHRU = 8; - /// this is a possible style. + /// Bold-Italic font style. public const int BOLDITALIC = BOLD | ITALIC; /// Type 1 PostScript font. diff --git a/itext/itext.io/itext/io/font/FontEncoding.cs b/itext/itext.io/itext/io/font/FontEncoding.cs index 569673c55a..6983c440f2 100644 --- a/itext/itext.io/itext/io/font/FontEncoding.cs +++ b/itext/itext.io/itext/io/font/FontEncoding.cs @@ -252,7 +252,7 @@ protected internal virtual void FillCustomEncoding() { String order = tok.NextToken(); String name = tok.NextToken(); char uni = (char)System.Convert.ToInt32(tok.NextToken(), 16); - int uniName = (int)AdobeGlyphList.NameToUnicode(name); + int uniName = AdobeGlyphList.NameToUnicode(name); int orderK; if (order.StartsWith("'")) { orderK = order[1]; @@ -363,6 +363,10 @@ protected internal static String NormalizeEncoding(String enc) { return PdfEncodings.MACROMAN; } + case "zapfdingbatsencoding": { + return PdfEncodings.ZAPFDINGBATS; + } + default: { return enc; } diff --git a/itext/itext.io/itext/io/font/FontProgramFactory.cs b/itext/itext.io/itext/io/font/FontProgramFactory.cs index 091c606146..3a0a10ed69 100644 --- a/itext/itext.io/itext/io/font/FontProgramFactory.cs +++ b/itext/itext.io/itext/io/font/FontProgramFactory.cs @@ -48,6 +48,9 @@ source product. namespace iText.IO.Font { /// Provides methods for creating various types of fonts. public sealed class FontProgramFactory { + /// This is the default value of the cached variable. + private static bool DEFAULT_CACHED = true; + private FontProgramFactory() { } @@ -107,11 +110,11 @@ public static FontProgram CreateFont() { /// createFont(name, null, true); /// /// - /// the name of the font or its location on file + /// the name of the font or its location on file /// returns a new font. This font may come from the cache /// - public static FontProgram CreateFont(String name) { - return CreateFont(name, null, true); + public static FontProgram CreateFont(String fontProgram) { + return CreateFont(fontProgram, null, DEFAULT_CACHED); } /// Creates a new font. @@ -157,15 +160,15 @@ public static FontProgram CreateFont(String name) { /// createFont(name, encoding, embedded, true, null, null); /// /// - /// the name of the font or its location on file + /// the name of the font or its location on file /// - /// ttrue if the font comes from the cache or is added to + /// true if the font comes from the cache or is added to /// the cache if new, false if the font is always created new /// /// returns a new font. This font may come from the cache /// - public static FontProgram CreateFont(String font, bool cached) { - return CreateFont(font, null, cached); + public static FontProgram CreateFont(String fontProgram, bool cached) { + return CreateFont(fontProgram, null, cached); } /// Creates a new font. @@ -203,7 +206,7 @@ public static FontProgram CreateFont(String font, bool cached) { /// "# full 'A' nottriangeqlleft 0041 'B' dividemultiply 0042 32 space 0020" /// /// - /// + /// /// the true type font or the afm in a byte array /// an exception if the font is not recognized. Note that even if true an exception may be thrown in some circumstances. /// This parameter is useful for FontProgramFactory that may have to check many invalid font names before finding the right one @@ -213,8 +216,8 @@ public static FontProgram CreateFont(String font, bool cached) { /// is true, otherwise it will always be created new /// /// - public static FontProgram CreateFont(byte[] font) { - return CreateFont(null, font, false); + public static FontProgram CreateFont(byte[] fontProgram) { + return CreateFont(null, fontProgram, DEFAULT_CACHED); } /// Creates a new font. @@ -274,53 +277,68 @@ public static FontProgram CreateFont(String name, byte[] font, bool cached) { bool isBuiltinFonts14 = FontConstants.BUILTIN_FONTS_14.Contains(name); bool isCidFont = !isBuiltinFonts14 && FontCache.IsPredefinedCidFont(baseName); FontProgram fontFound; - if (cached && name != null) { - fontFound = FontCache.GetFont(name); + String fontKey = null; + if (cached) { + if (name != null) { + fontKey = name; + } + else { + fontKey = iText.IO.Util.JavaUtil.IntegerToString(ArrayUtil.HashCode(font)); + } + fontFound = FontCache.GetFont(fontKey); if (fontFound != null) { return fontFound; } } + FontProgram fontBuilt = null; if (name == null) { if (font != null) { try { - return new TrueTypeFont(font); + fontBuilt = new TrueTypeFont(font); } catch (Exception) { } - try { - return new Type1Font(null, null, font, null); - } - catch (Exception) { + if (fontBuilt == null) { + try { + fontBuilt = new Type1Font(null, null, font, null); + } + catch (Exception) { + } } } - throw new iText.IO.IOException(iText.IO.IOException.FontIsNotRecognized); - } - FontProgram fontBuilt; - if (isBuiltinFonts14 || name.ToLower(System.Globalization.CultureInfo.InvariantCulture).EndsWith(".afm") || - name.ToLower(System.Globalization.CultureInfo.InvariantCulture).EndsWith(".pfm")) { - fontBuilt = new Type1Font(name, null, font, null); } else { - if (baseName.ToLower(System.Globalization.CultureInfo.InvariantCulture).EndsWith(".ttf") || baseName.ToLower - (System.Globalization.CultureInfo.InvariantCulture).EndsWith(".otf") || baseName.ToLower(System.Globalization.CultureInfo.InvariantCulture - ).IndexOf(".ttc,") > 0) { - if (font != null) { - fontBuilt = new TrueTypeFont(font); - } - else { - fontBuilt = new TrueTypeFont(name); - } + if (isBuiltinFonts14 || name.ToLower(System.Globalization.CultureInfo.InvariantCulture).EndsWith(".afm") || + name.ToLower(System.Globalization.CultureInfo.InvariantCulture).EndsWith(".pfm")) { + fontBuilt = new Type1Font(name, null, font, null); } else { - if (isCidFont) { - fontBuilt = new CidFont(name, FontCache.GetCompatibleCmaps(baseName)); + if (baseName.ToLower(System.Globalization.CultureInfo.InvariantCulture).EndsWith(".ttf") || baseName.ToLower + (System.Globalization.CultureInfo.InvariantCulture).EndsWith(".otf") || baseName.ToLower(System.Globalization.CultureInfo.InvariantCulture + ).IndexOf(".ttc,") > 0) { + if (font != null) { + fontBuilt = new TrueTypeFont(font); + } + else { + fontBuilt = new TrueTypeFont(name); + } } else { - throw new iText.IO.IOException(iText.IO.IOException.Font1IsNotRecognized).SetMessageParams(name); + if (isCidFont) { + fontBuilt = new CidFont(name, FontCache.GetCompatibleCmaps(baseName)); + } } } } - return cached ? FontCache.SaveFont(fontBuilt, name) : fontBuilt; + if (fontBuilt == null) { + if (name != null) { + throw new iText.IO.IOException(iText.IO.IOException.TypeOfFont1IsNotRecognized).SetMessageParams(name); + } + else { + throw new iText.IO.IOException(iText.IO.IOException.TypeOfFontIsNotRecognized); + } + } + return cached ? FontCache.SaveFont(fontBuilt, fontKey) : fontBuilt; } // todo make comment relevant to type 1 font creation @@ -378,14 +396,21 @@ public static FontProgram CreateFont(String name, byte[] font, bool cached) { /// public static FontProgram CreateType1Font(String name, byte[] afm, byte[] pfb, bool cached) { FontProgram fontProgram; - if (cached && name != null) { - fontProgram = FontCache.GetFont(name); + String fontKey = null; + if (cached) { + if (name != null) { + fontKey = name; + } + else { + fontKey = iText.IO.Util.JavaUtil.IntegerToString(ArrayUtil.HashCode(afm)); + } + fontProgram = FontCache.GetFont(fontKey); if (fontProgram != null) { return fontProgram; } } fontProgram = new Type1Font(name, null, afm, pfb); - return cached && name != null ? FontCache.SaveFont(fontProgram, name) : fontProgram; + return cached ? FontCache.SaveFont(fontProgram, fontKey) : fontProgram; } /// @@ -408,7 +433,7 @@ public static FontProgram CreateType1Font(String metricsPath, String binaryPath, /// public static FontProgram CreateType1Font(String metricsPath, String binaryPath) { - return CreateType1Font(metricsPath, binaryPath, true); + return CreateType1Font(metricsPath, binaryPath, DEFAULT_CACHED); } /// @@ -449,7 +474,7 @@ public static FontProgram CreateType1Font(String metricsPath, String binaryPath) /// "# full 'A' nottriangeqlleft 0041 'B' dividemultiply 0042 32 space 0020" /// /// - /// location of true type collection file (*.ttc) + /// location of true type collection file (*.ttc) /// the encoding to be applied to this font /// /// true if the font comes from the cache or is added to @@ -460,29 +485,30 @@ public static FontProgram CreateType1Font(String metricsPath, String binaryPath) /// is true, otherwise it will always be created new /// /// - public static FontProgram CreateFont(String ttcPath, int ttcIndex, bool cached) { + public static FontProgram CreateFont(String ttc, int ttcIndex, bool cached) { if (cached) { - FontProgram fontFound = FontCache.GetFont(ttcPath + ttcIndex); + FontProgram fontFound = FontCache.GetFont(ttc + ttcIndex); if (fontFound != null) { return fontFound; } } - FontProgram fontBuilt = new TrueTypeFont(ttcPath, ttcIndex); - return cached ? FontCache.SaveFont(fontBuilt, ttcPath + ttcIndex) : fontBuilt; + FontProgram fontBuilt = new TrueTypeFont(ttc, ttcIndex); + return cached ? FontCache.SaveFont(fontBuilt, ttc + ttcIndex) : fontBuilt; } /// public static FontProgram CreateFont(byte[] ttc, int ttcIndex, bool cached) { + String fontKey = null; if (cached) { - String ttcNameKey = String.Format("{0}{1}", ArrayUtil.HashCode(ttc), ttcIndex); - FontProgram fontFound = FontCache.GetFont(ttcNameKey); + fontKey = iText.IO.Util.JavaUtil.IntegerToString(ArrayUtil.HashCode(ttc)) + iText.IO.Util.JavaUtil.IntegerToString + (ttcIndex); + FontProgram fontFound = FontCache.GetFont(fontKey); if (fontFound != null) { return fontFound; } } FontProgram fontBuilt = new TrueTypeFont(ttc, ttcIndex); - String ttcNameKey_1 = String.Format("{0}{1}", ArrayUtil.HashCode(ttc), ttcIndex); - return cached ? FontCache.SaveFont(fontBuilt, ttcNameKey_1) : fontBuilt; + return cached ? FontCache.SaveFont(fontBuilt, fontKey) : fontBuilt; } /// diff --git a/itext/itext.io/itext/io/font/FontRegisterProvider.cs b/itext/itext.io/itext/io/font/FontRegisterProvider.cs index 7e70246774..5125ab8152 100644 --- a/itext/itext.io/itext/io/font/FontRegisterProvider.cs +++ b/itext/itext.io/itext/io/font/FontRegisterProvider.cs @@ -66,7 +66,7 @@ internal class FontRegisterProvider { private readonly IDictionary> fontFamilies = new Dictionary>(); /// Creates new FontRegisterProvider - public FontRegisterProvider() { + internal FontRegisterProvider() { fontNames[FontConstants.COURIER.ToLower(System.Globalization.CultureInfo.InvariantCulture)] = FontConstants .COURIER; fontNames[FontConstants.COURIER_BOLD.ToLower(System.Globalization.CultureInfo.InvariantCulture)] = FontConstants @@ -128,7 +128,7 @@ public FontRegisterProvider() { /// the style of this font /// the Font constructed based on the parameters /// - public virtual FontProgram GetFont(String fontName, int style) { + internal virtual FontProgram GetFont(String fontName, int style) { return GetFont(fontName, style, true); } @@ -141,7 +141,7 @@ public virtual FontProgram GetFont(String fontName, int style) { /// /// the Font constructed based on the parameters /// - public virtual FontProgram GetFont(String fontName, int style, bool cached) { + internal virtual FontProgram GetFont(String fontName, int style, bool cached) { if (fontName == null) { return null; } @@ -199,37 +199,37 @@ protected internal virtual FontProgram GetFontProgram(String fontName, bool cach /// the font family /// the font name /// the font path - public virtual void RegisterFontFamily(String familyName, String fullName, String path) { + internal virtual void RegisterFontFamily(String familyName, String fullName, String path) { if (path != null) { fontNames[fullName] = path; } - IList tmp; + IList family; lock (fontFamilies) { - tmp = fontFamilies.Get(familyName); - if (tmp == null) { - tmp = new List(); - fontFamilies[familyName] = tmp; + family = fontFamilies.Get(familyName); + if (family == null) { + family = new List(); + fontFamilies[familyName] = family; } } - lock (tmp) { - if (!tmp.Contains(fullName)) { + lock (family) { + if (!family.Contains(fullName)) { int fullNameLength = fullName.Length; bool inserted = false; - for (int j = 0; j < tmp.Count; ++j) { - if (tmp[j].Length >= fullNameLength) { - tmp.Add(j, fullName); + for (int j = 0; j < family.Count; ++j) { + if (family[j].Length >= fullNameLength) { + family.Add(j, fullName); inserted = true; break; } } if (!inserted) { - tmp.Add(fullName); + family.Add(fullName); String newFullName = fullName.ToLower(System.Globalization.CultureInfo.InvariantCulture); if (newFullName.EndsWith("regular")) { //remove "regular" at the end of the font name newFullName = newFullName.JSubstring(0, newFullName.Length - 7).Trim(); //insert this font name at the first position for higher priority - tmp.Add(0, fullName.JSubstring(0, newFullName.Length)); + family.Add(0, fullName.JSubstring(0, newFullName.Length)); } } } @@ -238,14 +238,14 @@ public virtual void RegisterFontFamily(String familyName, String fullName, Strin /// Register a ttf- or a ttc-file. /// the path to a ttf- or ttc-file - public virtual void RegisterFont(String path) { + internal virtual void RegisterFont(String path) { RegisterFont(path, null); } /// Register a font file and use an alias for the font contained in it. /// the path to a font file /// the alias you want to use for the font - public virtual void RegisterFont(String path, String alias) { + internal virtual void RegisterFont(String path, String alias) { try { if (path.ToLower(System.Globalization.CultureInfo.InvariantCulture).EndsWith(".ttf") || path.ToLower(System.Globalization.CultureInfo.InvariantCulture ).EndsWith(".otf") || path.ToLower(System.Globalization.CultureInfo.InvariantCulture).IndexOf(".ttc,") @@ -309,18 +309,21 @@ public virtual void RegisterFont(String path, String alias) { } else { if (path.ToLower(System.Globalization.CultureInfo.InvariantCulture).EndsWith(".ttc")) { - if (alias != null) { - LOGGER.Error("You can't define an alias for a true type collection."); - } - TrueTypeCollection ttc = new TrueTypeCollection(path, PdfEncodings.WINANSI); + TrueTypeCollection ttc = new TrueTypeCollection(path); for (int i = 0; i < ttc.GetTTCSize(); i++) { - RegisterFont(path + "," + i); + String fullPath = path + "," + i; + if (alias != null) { + RegisterFont(fullPath, alias + "," + i); + } + else { + RegisterFont(fullPath); + } } } else { if (path.ToLower(System.Globalization.CultureInfo.InvariantCulture).EndsWith(".afm") || path.ToLower(System.Globalization.CultureInfo.InvariantCulture ).EndsWith(".pfm")) { - FontProgram fontProgram = FontProgramFactory.CreateFont(path, false); + FontProgram fontProgram = FontProgramFactory.CreateFont(path); String fullName = fontProgram.GetFontNames().GetFullName()[0][3].ToLower(System.Globalization.CultureInfo.InvariantCulture ); String familyName = fontProgram.GetFontNames().GetFamilyName()[0][3].ToLower(System.Globalization.CultureInfo.InvariantCulture @@ -343,7 +346,7 @@ public virtual void RegisterFont(String path, String alias) { // remove regular and correct last symbol // do this job to give higher priority to regular fonts in comparison with light, narrow, etc // Don't use this method for not regular fonts! - protected internal virtual bool SaveCopyOfRegularFont(String regularFontName, String path) { + internal virtual bool SaveCopyOfRegularFont(String regularFontName, String path) { //remove "regular" at the end of the font name String alias = regularFontName.JSubstring(0, regularFontName.Length - 7).Trim(); if (!fontNames.ContainsKey(alias)) { @@ -356,7 +359,7 @@ protected internal virtual bool SaveCopyOfRegularFont(String regularFontName, St /// Register all the fonts in a directory. /// the directory /// the number of fonts registered - public virtual int RegisterFontDirectory(String dir) { + internal virtual int RegisterFontDirectory(String dir) { return RegisterFontDirectory(dir, false); } @@ -364,7 +367,7 @@ public virtual int RegisterFontDirectory(String dir) { /// the directory /// recursively scan subdirectories if true /// the number of fonts registered - public virtual int RegisterFontDirectory(String dir, bool scanSubdirectories) { + internal virtual int RegisterFontDirectory(String dir, bool scanSubdirectories) { LOGGER.Debug(String.Format("Registering directory {0}, looking for fonts", dir)); int count = 0; try { @@ -408,7 +411,7 @@ public virtual int RegisterFontDirectory(String dir, bool scanSubdirectories) { /// Linux and Solaris. /// /// the number of fonts registered - public virtual int RegisterSystemFontDirectories() { + internal virtual int RegisterSystemFontDirectories() { int count = 0; String[] withSubDirs = new String[] { FileUtil.GetFontsDir(), "/usr/share/X11/fonts", "/usr/X/lib/X11/fonts" , "/usr/openwin/lib/X11/fonts", "/usr/share/fonts", "/usr/X11R6/lib/X11/fonts" }; @@ -424,20 +427,20 @@ public virtual int RegisterSystemFontDirectories() { /// Gets a set of registered font names. /// a set of registered fonts - public virtual ICollection GetRegisteredFonts() { + internal virtual ICollection GetRegisteredFonts() { return fontNames.Keys; } /// Gets a set of registered font names. /// a set of registered font families - public virtual ICollection GetRegisteredFontFamilies() { + internal virtual ICollection GetRegisteredFontFamilies() { return fontFamilies.Keys; } /// Checks if a certain font is registered. /// the name of the font that has to be checked. /// true if the font is found - public virtual bool IsRegisteredFont(String fontname) { + internal virtual bool IsRegisteredFont(String fontname) { return fontNames.ContainsKey(fontname.ToLower(System.Globalization.CultureInfo.InvariantCulture)); } } diff --git a/itext/itext.io/itext/io/font/PdfEncodings.cs b/itext/itext.io/itext/io/font/PdfEncodings.cs index 2b1ee818eb..8b66fe8486 100644 --- a/itext/itext.io/itext/io/font/PdfEncodings.cs +++ b/itext/itext.io/itext/io/font/PdfEncodings.cs @@ -270,7 +270,7 @@ public static byte[] ConvertToBytes(String text, String encoding) { return EncodingUtil.ConvertToBytes(text.ToCharArray(), encoding); } catch (System.IO.IOException e) { - throw new iText.IO.IOException(iText.IO.IOException.PdfEncodings, e); + throw new iText.IO.IOException(iText.IO.IOException.CharacterCodeException, e); } } @@ -325,7 +325,7 @@ public static byte[] ConvertToBytes(char ch, String encoding) { return EncodingUtil.ConvertToBytes(new char[] { ch }, encoding); } catch (System.IO.IOException e) { - throw new iText.IO.IOException(iText.IO.IOException.PdfEncodings, e); + throw new iText.IO.IOException(iText.IO.IOException.CharacterCodeException, e); } } @@ -383,7 +383,7 @@ public static String ConvertToString(byte[] bytes, String encoding) { return EncodingUtil.ConvertToString(bytes, encoding); } catch (ArgumentException e) { - throw new iText.IO.IOException(iText.IO.IOException.PdfEncodings, e); + throw new iText.IO.IOException(iText.IO.IOException.UnsupportedEncodingException, e); } } diff --git a/itext/itext.io/itext/io/font/TrueTypeCollection.cs b/itext/itext.io/itext/io/font/TrueTypeCollection.cs index 54c4781138..38745eec34 100644 --- a/itext/itext.io/itext/io/font/TrueTypeCollection.cs +++ b/itext/itext.io/itext/io/font/TrueTypeCollection.cs @@ -50,32 +50,52 @@ namespace iText.IO.Font { public class TrueTypeCollection { protected internal RandomAccessFileOrArray raf; - internal String encoding; + private int TTCSize = 0; - internal int TTCSize = 0; + private String ttcPath; - internal String ttcPath; + private byte[] ttc; - internal byte[] ttc; - - internal bool cached = false; + private bool cached = true; /// - public TrueTypeCollection(byte[] ttc, String encoding) { + [System.ObsoleteAttribute(@"Will be removed in 7.1. Use TrueTypeCollection(byte[]) instead")] + public TrueTypeCollection(byte[] ttc, String encoding) + : this(ttc) { + } + + /// + /// Creates a new + /// + /// instance by its bytes. + /// + /// the byte contents of the collection + /// in case the input in mal-formatted + public TrueTypeCollection(byte[] ttc) { raf = new RandomAccessFileOrArray(new RandomAccessSourceFactory().CreateSource(ttc)); this.ttc = ttc; - this.encoding = encoding; InitFontSize(); } /// - public TrueTypeCollection(String ttcPath, String encoding) { + [System.ObsoleteAttribute(@"Will be removed in 7.1. Use TrueTypeCollection(System.String) instead")] + public TrueTypeCollection(String ttcPath, String encoding) + : this(ttcPath) { + } + + /// + /// Creates a new + /// + /// instance by its file path. + /// + /// the path of the collection + /// in case the input in mal-formatted + public TrueTypeCollection(String ttcPath) { if (!FileUtil.FileExists(ttcPath)) { throw new iText.IO.IOException(iText.IO.IOException.FontFile1NotFound).SetMessageParams(ttcPath); } raf = new RandomAccessFileOrArray(new RandomAccessSourceFactory().CreateBestSource(ttcPath)); this.ttcPath = ttcPath; - this.encoding = encoding; InitFontSize(); } @@ -85,7 +105,7 @@ public TrueTypeCollection(String ttcPath, String encoding) { /// public virtual FontProgram GetFontByTccIndex(int ttcIndex) { if (ttcIndex > TTCSize - 1) { - throw new iText.IO.IOException(iText.IO.IOException.TTCIndexDoesNotExistInFile); + throw new iText.IO.IOException(iText.IO.IOException.TtcIndexDoesNotExistInThisTtcFile); } if (ttcPath != null) { return FontProgramFactory.CreateFont(ttcPath, ttcIndex, cached); @@ -101,10 +121,22 @@ public virtual int GetTTCSize() { return TTCSize; } + /// + /// Indicates if fonts created by the call to + /// + /// will be cached or not. + /// + /// true if the created fonts will be cached, false otherwise public virtual bool IsCached() { return cached; } + /// + /// Sets if fonts created by the call to + /// + /// will be cached or not. + /// + /// true if the created fonts will be cached, false otherwise public virtual void SetCached(bool cached) { this.cached = cached; } diff --git a/itext/itext.io/itext/io/font/TrueTypeFont.cs b/itext/itext.io/itext/io/font/TrueTypeFont.cs index cb5a15aa92..1021bb7903 100644 --- a/itext/itext.io/itext/io/font/TrueTypeFont.cs +++ b/itext/itext.io/itext/io/font/TrueTypeFont.cs @@ -198,6 +198,10 @@ public virtual GlyphPositioningTableReader GetGposTable() { return gposTable; } + public virtual OpenTypeGdefTableReader GetGdefTable() { + return gdefTable; + } + public virtual byte[] GetSubset(ICollection glyphs, bool subset) { try { return fontParser.GetSubset(glyphs, subset); @@ -216,6 +220,7 @@ protected internal virtual void ReadGdefTable() { else { gdefTable = new OpenTypeGdefTableReader(fontParser.raf, 0); } + gdefTable.ReadTable(); } /// diff --git a/itext/itext.io/itext/io/font/Type1Font.cs b/itext/itext.io/itext/io/font/Type1Font.cs index 63d43c192f..e934d02e47 100644 --- a/itext/itext.io/itext/io/font/Type1Font.cs +++ b/itext/itext.io/itext/io/font/Type1Font.cs @@ -131,7 +131,7 @@ public override bool HasKernPairs() { public override int GetKerning(Glyph first, Glyph second) { if (first.HasValidUnicode() && second.HasValidUnicode()) { - long record = ((long)first.GetUnicode() << 32) + (int)second.GetUnicode(); + long record = ((long)first.GetUnicode() << 32) + second.GetUnicode(); if (kernPairs.ContainsKey(record)) { return (int)kernPairs.Get(record); } @@ -163,7 +163,7 @@ public virtual bool SetKerning(int first, int second, int kern) { /// Glyph name /// Glyph instance if found, otherwise null. public virtual Glyph GetGlyph(String name) { - int unicode = (int)AdobeGlyphList.NameToUnicode(name); + int unicode = AdobeGlyphList.NameToUnicode(name); if (unicode != -1) { return GetGlyph((int)unicode); } @@ -406,7 +406,7 @@ protected internal virtual void Process() { } } } - int unicode = (int)AdobeGlyphList.NameToUnicode(N); + int unicode = AdobeGlyphList.NameToUnicode(N); Glyph glyph = new Glyph(C, WX, unicode, B); if (C >= 0) { codeToGlyph[C] = glyph; @@ -433,10 +433,7 @@ protected internal virtual void Process() { // nonbreakingspace;00A0 // space;0020 if (!unicodeToGlyph.ContainsKey(0x00A0)) { - Glyph space = null; - if (unicodeToGlyph.ContainsKey(0x0020)) { - space = unicodeToGlyph.Get(0x0020); - } + Glyph space = unicodeToGlyph.Get(0x0020); if (space != null) { unicodeToGlyph[0x00A0] = new Glyph(space.GetCode(), space.GetWidth(), 0x00A0, space.GetBbox()); } @@ -470,8 +467,8 @@ protected internal virtual void Process() { String first = tok.NextToken(); String second = tok.NextToken(); int? width = (int)float.Parse(tok.NextToken(), System.Globalization.CultureInfo.InvariantCulture); - int firstUni = (int)AdobeGlyphList.NameToUnicode(first); - int secondUni = (int)AdobeGlyphList.NameToUnicode(second); + int firstUni = AdobeGlyphList.NameToUnicode(first); + int secondUni = AdobeGlyphList.NameToUnicode(second); if (firstUni != -1 && secondUni != -1) { long record = ((long)firstUni << 32) + secondUni; kernPairs[record] = width; diff --git a/itext/itext.io/itext/io/font/cmap/CMapLocationResource.cs b/itext/itext.io/itext/io/font/cmap/CMapLocationResource.cs index be550ee089..3d67028064 100644 --- a/itext/itext.io/itext/io/font/cmap/CMapLocationResource.cs +++ b/itext/itext.io/itext/io/font/cmap/CMapLocationResource.cs @@ -55,7 +55,7 @@ public virtual PdfTokenizer GetLocation(String location) { String fullName = FontConstants.CMAP_RESOURCE_PATH + location; Stream inp = ResourceUtil.GetResourceStream(fullName); if (inp == null) { - throw new iText.IO.IOException(iText.IO.IOException.TheCmap1WasNotFound).SetMessageParams(fullName); + throw new iText.IO.IOException(iText.IO.IOException.Cmap1WasNotFound).SetMessageParams(fullName); } return new PdfTokenizer(new RandomAccessFileOrArray(new RandomAccessSourceFactory().CreateSource(inp))); } diff --git a/itext/itext.io/itext/io/font/otf/ActualTextIterator.cs b/itext/itext.io/itext/io/font/otf/ActualTextIterator.cs index 4578dc4ade..d894145560 100644 --- a/itext/itext.io/itext/io/font/otf/ActualTextIterator.cs +++ b/itext/itext.io/itext/io/font/otf/ActualTextIterator.cs @@ -151,7 +151,7 @@ private bool GlyphLinePartNeedsActualText(GlyphLine.GlyphLinePart glyphLinePart) break; } // TODO zero glyph is a special case. Unicode might be special - toUnicodeMapResult.Append(TextUtil.ConvertFromUtf32((int) currentGlyph.GetUnicode())); + toUnicodeMapResult.Append(TextUtil.ConvertFromUtf32(currentGlyph.GetUnicode())); } return needsActualText || !toUnicodeMapResult.ToString().Equals(glyphLinePart.actualText ); diff --git a/itext/itext.io/itext/io/font/otf/Glyph.cs b/itext/itext.io/itext/io/font/otf/Glyph.cs index 5c2ace4ed2..dcc93f5c7a 100644 --- a/itext/itext.io/itext/io/font/otf/Glyph.cs +++ b/itext/itext.io/itext/io/font/otf/Glyph.cs @@ -69,7 +69,7 @@ public class Glyph internal short yAdvance = 0; - internal byte anchorDelta = 0; + internal short anchorDelta = 0; public Glyph(int code, int width, int unicode) : this(code, width, unicode, null, false) @@ -133,7 +133,7 @@ public Glyph(iText.IO.Font.Otf.Glyph glyph, int xPlacement, int yPlacement, this.yPlacement = (short)yPlacement; this.xAdvance = (short)xAdvance; this.yAdvance = (short)yAdvance; - this.anchorDelta = (byte)anchorDelta; + this.anchorDelta = (short)anchorDelta; } public Glyph(iText.IO.Font.Otf.Glyph glyph, int unicode) @@ -227,12 +227,16 @@ public virtual void SetYAdvance(short yAdvance) this.yAdvance = yAdvance; } - public virtual byte GetAnchorDelta() + public virtual short GetAnchorDelta() { return anchorDelta; - } + } + + public void SetAnchorDelta(short anchorDelta) { + this.anchorDelta = anchorDelta; + } - public virtual bool HasOffsets() + public virtual bool HasOffsets() { return xPlacement != 0 || yPlacement != 0 || xAdvance != 0 || yAdvance != 0; } diff --git a/itext/itext.io/itext/io/font/otf/GlyphLine.cs b/itext/itext.io/itext/io/font/otf/GlyphLine.cs index d6dfd8090a..11969503a9 100644 --- a/itext/itext.io/itext/io/font/otf/GlyphLine.cs +++ b/itext/itext.io/itext/io/font/otf/GlyphLine.cs @@ -113,7 +113,7 @@ public virtual String ToUnicodeString(int start, int end) { } else { if (glyphs[i].HasValidUnicode()) { - str.Append(TextUtil.ConvertFromUtf32((int)glyphs[i].GetUnicode())); + str.Append(TextUtil.ConvertFromUtf32(glyphs[i].GetUnicode())); } } } @@ -193,7 +193,7 @@ public virtual void SubstituteManyToOne(OpenTypeFontTableReader tableReader, int } else { if (currentGlyph.HasValidUnicode()) { - chars.Append(TextUtil.ConvertFromUtf32((int)currentGlyph.GetUnicode())); + chars.Append(TextUtil.ConvertFromUtf32(currentGlyph.GetUnicode())); } } for (int j = 0; j < rightPartLen; ++j) { @@ -204,7 +204,7 @@ public virtual void SubstituteManyToOne(OpenTypeFontTableReader tableReader, int } else { if (currentGlyph.HasValidUnicode()) { - chars.Append(TextUtil.ConvertFromUtf32((int)currentGlyph.GetUnicode())); + chars.Append(TextUtil.ConvertFromUtf32(currentGlyph.GetUnicode())); } } RemoveGlyph(gidx.idx--); @@ -225,11 +225,11 @@ public virtual void SubstituteOneToOne(OpenTypeFontTableReader tableReader, int } else { if (newGlyph.HasValidUnicode()) { - newGlyph.SetChars(TextUtil.ConvertFromUtf32((int)newGlyph.GetUnicode())); + newGlyph.SetChars(TextUtil.ConvertFromUtf32(newGlyph.GetUnicode())); } else { if (oldGlyph.HasValidUnicode()) { - newGlyph.SetChars(TextUtil.ConvertFromUtf32((int)oldGlyph.GetUnicode())); + newGlyph.SetChars(TextUtil.ConvertFromUtf32(oldGlyph.GetUnicode())); } } } diff --git a/itext/itext.io/itext/io/font/otf/GlyphPositioningTableReader.cs b/itext/itext.io/itext/io/font/otf/GlyphPositioningTableReader.cs index ac93815a80..e7254c6d82 100644 --- a/itext/itext.io/itext/io/font/otf/GlyphPositioningTableReader.cs +++ b/itext/itext.io/itext/io/font/otf/GlyphPositioningTableReader.cs @@ -83,6 +83,10 @@ protected internal override OpenTableLookup ReadLookupTable(int lookupType, int return new GposLookupType5(this, lookupFlag, subTableLocations); } + case 6: { + return new GposLookupType6(this, lookupFlag, subTableLocations); + } + default: { return null; } diff --git a/itext/itext.io/itext/io/font/otf/GposLookupType6.cs b/itext/itext.io/itext/io/font/otf/GposLookupType6.cs new file mode 100644 index 0000000000..3ddfc4e7b0 --- /dev/null +++ b/itext/itext.io/itext/io/font/otf/GposLookupType6.cs @@ -0,0 +1,153 @@ +/* +This file is part of the iText (R) project. +Copyright (c) 1998-2016 iText Group NV +Authors: Bruno Lowagie, Paulo Soares, et al. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License version 3 +as published by the Free Software Foundation with the addition of the +following permission added to Section 15 as permitted in Section 7(a): +FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY +ITEXT GROUP. ITEXT GROUP DISCLAIMS THE WARRANTY OF NON INFRINGEMENT +OF THIRD PARTY RIGHTS + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. +See the GNU Affero General Public License for more details. +You should have received a copy of the GNU Affero General Public License +along with this program; if not, see http://www.gnu.org/licenses or write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +Boston, MA, 02110-1301 USA, or download the license from the following URL: +http://itextpdf.com/terms-of-use/ + +The interactive user interfaces in modified source and object code versions +of this program must display Appropriate Legal Notices, as required under +Section 5 of the GNU Affero General Public License. + +In accordance with Section 7(b) of the GNU Affero General Public License, +a covered work must retain the producer line in every PDF that is created +or manipulated using iText. + +You can be released from the requirements of the license by purchasing +a commercial license. Buying such a license is mandatory as soon as you +develop commercial activities involving the iText software without +disclosing the source code of your own applications. +These activities include: offering paid services to customers as an ASP, +serving PDFs on the fly in a web application, shipping iText with a closed +source product. + +For more information, please contact iText Software Corp. at this +address: sales@itextpdf.com +*/ +using System.Collections.Generic; + +namespace iText.IO.Font.Otf { + /// + /// Lookup Type 6: + /// MarkToMark Attachment Positioning Subtable + /// + public class GposLookupType6 : OpenTableLookup { + private readonly IList marksbases; + + /// + public GposLookupType6(OpenTypeFontTableReader openReader, int lookupFlag, int[] subTableLocations) + : base(openReader, lookupFlag, subTableLocations) { + marksbases = new List(); + ReadSubTables(); + } + + public override bool TransformOne(GlyphLine line) { + if (line.idx >= line.end) { + return false; + } + if (openReader.IsSkip(line.Get(line.idx).GetCode(), lookupFlag)) { + line.idx++; + return false; + } + bool changed = false; + OpenTableLookup.GlyphIndexer gi = null; + foreach (GposLookupType6.MarkToBaseMark mb in marksbases) { + OtfMarkRecord omr = mb.marks.Get(line.Get(line.idx).GetCode()); + if (omr == null) { + continue; + } + if (gi == null) { + gi = new OpenTableLookup.GlyphIndexer(); + gi.idx = line.idx; + gi.line = line; + while (true) { + int prev = gi.idx; + // avoid attaching this mark glyph to another very distant mark glyph + bool foundBaseGlyph = false; + gi.PreviousGlyph(openReader, lookupFlag); + if (gi.idx != -1) { + for (int i = gi.idx; i < prev; i++) { + if (openReader.GetGlyphClass(line.Get(i).GetCode()) == OtfClass.GLYPH_BASE) { + foundBaseGlyph = true; + break; + } + } + } + if (foundBaseGlyph) { + gi.glyph = null; + break; + } + if (gi.glyph == null) { + break; + } + if (mb.baseMarks.ContainsKey(gi.glyph.GetCode())) { + break; + } + } + if (gi.glyph == null) { + break; + } + } + GposAnchor[] gpas = mb.baseMarks.Get(gi.glyph.GetCode()); + if (gpas == null) { + continue; + } + int markClass = omr.markClass; + GposAnchor baseAnchor = gpas[markClass]; + GposAnchor markAnchor = omr.anchor; + line.Set(line.idx, new Glyph(line.Get(line.idx), -markAnchor.XCoordinate + baseAnchor.XCoordinate, -markAnchor + .YCoordinate + baseAnchor.YCoordinate, 0, 0, gi.idx - line.idx)); + changed = true; + break; + } + line.idx++; + return changed; + } + + /// + protected internal override void ReadSubTable(int subTableLocation) { + openReader.rf.Seek(subTableLocation); + openReader.rf.ReadUnsignedShort(); + //skip format, always 1 + int markCoverageLocation = openReader.rf.ReadUnsignedShort() + subTableLocation; + int baseCoverageLocation = openReader.rf.ReadUnsignedShort() + subTableLocation; + int classCount = openReader.rf.ReadUnsignedShort(); + int markArrayLocation = openReader.rf.ReadUnsignedShort() + subTableLocation; + int baseArrayLocation = openReader.rf.ReadUnsignedShort() + subTableLocation; + IList markCoverage = openReader.ReadCoverageFormat(markCoverageLocation); + IList baseCoverage = openReader.ReadCoverageFormat(baseCoverageLocation); + IList markRecords = OtfReadCommon.ReadMarkArray(openReader, markArrayLocation); + GposLookupType6.MarkToBaseMark markToBaseMark = new GposLookupType6.MarkToBaseMark(); + for (int k = 0; k < markCoverage.Count; ++k) { + markToBaseMark.marks[markCoverage[k]] = markRecords[k]; + } + IList baseArray = OtfReadCommon.ReadBaseArray(openReader, classCount, baseArrayLocation); + for (int k_1 = 0; k_1 < baseCoverage.Count; ++k_1) { + markToBaseMark.baseMarks[baseCoverage[k_1]] = baseArray[k_1]; + } + marksbases.Add(markToBaseMark); + } + + private class MarkToBaseMark { + public readonly IDictionary marks = new Dictionary(); + + public readonly IDictionary baseMarks = new Dictionary(); + } + } +} diff --git a/itext/itext.io/itext/io/font/otf/GsubLookupType1.cs b/itext/itext.io/itext/io/font/otf/GsubLookupType1.cs index 395d3175bb..d678a2b432 100644 --- a/itext/itext.io/itext/io/font/otf/GsubLookupType1.cs +++ b/itext/itext.io/itext/io/font/otf/GsubLookupType1.cs @@ -43,17 +43,18 @@ source product. */ using System; using System.Collections.Generic; +using iText.IO.Util; namespace iText.IO.Font.Otf { /// LookupType 1: Single Substitution Subtable /// psoares public class GsubLookupType1 : OpenTableLookup { - private IDictionary substMap; + private IntHashtable substMap; /// public GsubLookupType1(OpenTypeFontTableReader openReader, int lookupFlag, int[] subTableLocations) : base(openReader, lookupFlag, subTableLocations) { - substMap = new Dictionary(); + substMap = new IntHashtable(); ReadSubTables(); } @@ -64,9 +65,9 @@ public override bool TransformOne(GlyphLine line) { Glyph g = line.Get(line.idx); bool changed = false; if (!openReader.IsSkip(g.GetCode(), lookupFlag)) { - int? substCode = substMap.Get(g.GetCode()); - if (substCode != null) { - line.SubstituteOneToOne(openReader, (int)substCode); + int substCode = substMap.Get(g.GetCode()); + if (substCode != 0) { + line.SubstituteOneToOne(openReader, substCode); changed = true; } } @@ -84,7 +85,7 @@ protected internal override void ReadSubTable(int subTableLocation) { IList coverageGlyphIds = openReader.ReadCoverageFormat(subTableLocation + coverage); foreach (int coverageGlyphId in coverageGlyphIds) { int substituteGlyphId = coverageGlyphId + deltaGlyphID; - substMap[coverageGlyphId] = substituteGlyphId; + substMap.Put(coverageGlyphId, substituteGlyphId); } } else { @@ -97,7 +98,7 @@ protected internal override void ReadSubTable(int subTableLocation) { } IList coverageGlyphIds = openReader.ReadCoverageFormat(subTableLocation + coverage); for (int k_1 = 0; k_1 < glyphCount; ++k_1) { - substMap[coverageGlyphIds[k_1]] = substitute[k_1]; + substMap.Put(coverageGlyphIds[k_1], substitute[k_1]); } } else { diff --git a/itext/itext.io/itext/io/font/otf/OpenTypeFontTableReader.cs b/itext/itext.io/itext/io/font/otf/OpenTypeFontTableReader.cs index f094dd92de..c2ed7fe844 100644 --- a/itext/itext.io/itext/io/font/otf/OpenTypeFontTableReader.cs +++ b/itext/itext.io/itext/io/font/otf/OpenTypeFontTableReader.cs @@ -159,6 +159,10 @@ public virtual bool IsSkip(int glyph, int flag) { return gdef.IsSkip(glyph, flag); } + public virtual int GetGlyphClass(int glyphCode) { + return gdef.GetGlyphClassTable().GetOtfClass(glyphCode); + } + public virtual int GetUnitsPerEm() { return unitsPerEm; } diff --git a/itext/itext.io/itext/io/font/otf/OpenTypeGdefTableReader.cs b/itext/itext.io/itext/io/font/otf/OpenTypeGdefTableReader.cs index 6d96b02e7f..79e5e76cbb 100644 --- a/itext/itext.io/itext/io/font/otf/OpenTypeGdefTableReader.cs +++ b/itext/itext.io/itext/io/font/otf/OpenTypeGdefTableReader.cs @@ -45,12 +45,6 @@ source product. namespace iText.IO.Font.Otf { public class OpenTypeGdefTableReader { - private readonly int GLYPH_SKIP_BASE = 1; - - private readonly int GLYPH_SKIP_MARK = 2; - - private readonly int GLYPH_SKIP_LIGATURE = 3; - private readonly int FLAG_IGNORE_BASE = 2; private readonly int FLAG_IGNORE_LIGATURE = 4; @@ -94,20 +88,24 @@ public virtual void ReadTable() { public virtual bool IsSkip(int glyph, int flag) { if (glyphClass != null && (flag & (FLAG_IGNORE_BASE | FLAG_IGNORE_LIGATURE | FLAG_IGNORE_MARK)) != 0) { int cla = glyphClass.GetOtfClass(glyph); - if (cla == GLYPH_SKIP_BASE && (flag & FLAG_IGNORE_BASE) != 0) { + if (cla == OtfClass.GLYPH_BASE && (flag & FLAG_IGNORE_BASE) != 0) { return true; } - if (cla == GLYPH_SKIP_MARK && (flag & FLAG_IGNORE_MARK) != 0) { + if (cla == OtfClass.GLYPH_MARK && (flag & FLAG_IGNORE_MARK) != 0) { return true; } - if (cla == GLYPH_SKIP_LIGATURE && (flag & FLAG_IGNORE_LIGATURE) != 0) { + if (cla == OtfClass.GLYPH_LIGATURE && (flag & FLAG_IGNORE_LIGATURE) != 0) { return true; } } - if (markAttachmentClass != null && (flag >> 8) > 0) { + if (markAttachmentClass != null && markAttachmentClass.GetOtfClass(glyph) > 0 && (flag >> 8) > 0) { return markAttachmentClass.GetOtfClass(glyph) != (flag >> 8); } return false; } + + public virtual OtfClass GetGlyphClassTable() { + return glyphClass; + } } } diff --git a/itext/itext.io/itext/io/font/otf/OtfClass.cs b/itext/itext.io/itext/io/font/otf/OtfClass.cs index a45d207302..e1029067fe 100644 --- a/itext/itext.io/itext/io/font/otf/OtfClass.cs +++ b/itext/itext.io/itext/io/font/otf/OtfClass.cs @@ -46,6 +46,12 @@ source product. namespace iText.IO.Font.Otf { public class OtfClass { + public const int GLYPH_BASE = 1; + + public const int GLYPH_LIGATURE = 2; + + public const int GLYPH_MARK = 3; + private IntHashtable mapClass = new IntHashtable(); /// @@ -84,6 +90,10 @@ public virtual int GetOtfClass(int glyph) { return mapClass.Get(glyph); } + public virtual bool IsMarkOtfClass(int glyph) { + return HasClass(glyph) && GetOtfClass(glyph) == GLYPH_MARK; + } + public virtual bool HasClass(int glyph) { return mapClass.ContainsKey(glyph); } diff --git a/itext/itext.io/itext/io/image/BmpImageHelper.cs b/itext/itext.io/itext/io/image/BmpImageHelper.cs index dd6b6886f4..2ae4508afc 100644 --- a/itext/itext.io/itext/io/image/BmpImageHelper.cs +++ b/itext/itext.io/itext/io/image/BmpImageHelper.cs @@ -178,7 +178,7 @@ private static void Process(BmpImageHelper.BmpParameters bmp, Stream stream) { if (!bmp.image.IsNoHeader()) { // Start File Header if (!(ReadUnsignedByte(bmp.inputStream) == 'B' && ReadUnsignedByte(bmp.inputStream) == 'M')) { - throw new iText.IO.IOException(iText.IO.IOException.InvalidMagicValueForBmpFile); + throw new iText.IO.IOException(iText.IO.IOException.InvalidMagicValueForBmpFileMustBeBM); } // Read file size bmp.bitmapFileSize = ReadDWord(bmp.inputStream); diff --git a/itext/itext.io/itext/io/image/ImageData.cs b/itext/itext.io/itext/io/image/ImageData.cs index e63d2ff419..17ed2f3584 100644 --- a/itext/itext.io/itext/io/image/ImageData.cs +++ b/itext/itext.io/itext/io/image/ImageData.cs @@ -222,7 +222,7 @@ public virtual void SetImageMask(iText.IO.Image.ImageData imageMask) { throw new iText.IO.IOException(iText.IO.IOException.ImageMaskCannotContainAnotherImageMask); } if (!imageMask.mask) { - throw new iText.IO.IOException(iText.IO.IOException.ImageMaskIsNotAMaskDidYouDoMakeMask); + throw new iText.IO.IOException(iText.IO.IOException.ImageIsNotMaskYouMustCallImageDataMakeMask); } this.imageMask = imageMask; } @@ -233,7 +233,7 @@ public virtual bool IsSoftMask() { public virtual void MakeMask() { if (!CanBeMask()) { - throw new iText.IO.IOException(iText.IO.IOException.ImageCanNotBeAnImageMask); + throw new iText.IO.IOException(iText.IO.IOException.ThisImageCanNotBeAnImageMask); } mask = true; } diff --git a/itext/itext.io/itext/io/image/Jpeg2000ImageHelper.cs b/itext/itext.io/itext/io/image/Jpeg2000ImageHelper.cs index f6e8a07abd..107dd21a6f 100644 --- a/itext/itext.io/itext/io/image/Jpeg2000ImageHelper.cs +++ b/itext/itext.io/itext/io/image/Jpeg2000ImageHelper.cs @@ -55,17 +55,17 @@ private class Jpeg2000Box { } private class ZeroBoxSizeException : System.IO.IOException { - public ZeroBoxSizeException(String s) + internal ZeroBoxSizeException(String s) : base(s) { } } + private const int JPIP_JPIP = 0x6a706970; + private const int JP2_JP = 0x6a502020; private const int JP2_IHDR = 0x69686472; - private const int JPIP_JPIP = 0x6a706970; - private const int JP2_FTYP = 0x66747970; private const int JP2_JP2H = 0x6a703268; diff --git a/itext/itext.io/itext/io/image/JpegImageHelper.cs b/itext/itext.io/itext/io/image/JpegImageHelper.cs index 8fed120843..0abc781a97 100644 --- a/itext/itext.io/itext/io/image/JpegImageHelper.cs +++ b/itext/itext.io/itext/io/image/JpegImageHelper.cs @@ -149,7 +149,7 @@ private static void ProcessParameters(Stream jpegStream, String errorID, ImageDa while (true) { int v = jpegStream.Read(); if (v < 0) { - throw new iText.IO.IOException(iText.IO.IOException.PrematureEofWhileReadingJpg); + throw new iText.IO.IOException(iText.IO.IOException.PrematureEofWhileReadingJpeg); } if (v == 0xFF) { int marker = jpegStream.Read(); diff --git a/itext/itext.io/itext/io/image/PngImageHelper.cs b/itext/itext.io/itext/io/image/PngImageHelper.cs index 3969346cbf..b7c3e4e2e3 100644 --- a/itext/itext.io/itext/io/image/PngImageHelper.cs +++ b/itext/itext.io/itext/io/image/PngImageHelper.cs @@ -745,7 +745,7 @@ private static void DecodePass(int xOffset, int yOffset, int xStep, int yStep, i default: { // Error -- uknown filter type - throw new iText.IO.IOException(iText.IO.IOException.PngFilterUnknown); + throw new iText.IO.IOException(iText.IO.IOException.UnknownPngFilter); } } ProcessPixels(curr, xOffset, xStep, dstY, passWidth, png); diff --git a/itext/itext.io/itext/io/image/TiffImageHelper.cs b/itext/itext.io/itext/io/image/TiffImageHelper.cs index 8f1d50f8de..eebd2346ac 100644 --- a/itext/itext.io/itext/io/image/TiffImageHelper.cs +++ b/itext/itext.io/itext/io/image/TiffImageHelper.cs @@ -472,7 +472,7 @@ private static void ProcessTiffImageColor(TIFFDirectory dir, RandomAccessFileOrA // Assume that the TIFFTAG_JPEGIFBYTECOUNT tag is optional, since it's obsolete and // is often missing if ((!dir.IsTagPresent(TIFFConstants.TIFFTAG_JPEGIFOFFSET))) { - throw new iText.IO.IOException(iText.IO.IOException.MissingTagSForOjpegCompression); + throw new iText.IO.IOException(iText.IO.IOException.MissingTagsForOjpegCompression); } int jpegOffset = (int)dir.GetFieldAsLong(TIFFConstants.TIFFTAG_JPEGIFOFFSET); int jpegLength = (int)s.Length() - jpegOffset; diff --git a/itext/itext.io/itext/io/source/ByteUtils.cs b/itext/itext.io/itext/io/source/ByteUtils.cs index d274f2a9d2..10a702111e 100644 --- a/itext/itext.io/itext/io/source/ByteUtils.cs +++ b/itext/itext.io/itext/io/source/ByteUtils.cs @@ -131,7 +131,17 @@ internal static byte[] GetIsoBytes(double d, ByteBuffer buffer) { internal static byte[] GetIsoBytes(double d, ByteBuffer buffer, bool highPrecision) { if (highPrecision) { - byte[] result = DecimalFormatUtil.FormatNumber(d, "0.######").GetBytes(); + if (Math.Abs(d) < 0.000001) { + if (buffer != null) { + buffer.Prepend(zero); + return null; + } + else { + return zero; + } + } + byte[] result = DecimalFormatUtil.FormatNumber(d, "0.######").GetBytes(iText.IO.Util.EncodingUtil.ISO_8859_1 + ); if (buffer != null) { buffer.Prepend(result); return null; diff --git a/itext/itext.io/itext/io/source/GroupedRandomAccessSource.cs b/itext/itext.io/itext/io/source/GroupedRandomAccessSource.cs index b43663392b..e5f3a414ab 100644 --- a/itext/itext.io/itext/io/source/GroupedRandomAccessSource.cs +++ b/itext/itext.io/itext/io/source/GroupedRandomAccessSource.cs @@ -41,6 +41,10 @@ source product. For more information, please contact iText Software Corp. at this address: sales@itextpdf.com */ +using System; +using iText.IO; +using iText.IO.Log; + namespace iText.IO.Source { /// /// A RandomAccessSource that is based on a set of underlying sources, @@ -196,12 +200,32 @@ public virtual long Length() { /// /// - /// Closes all of the underlying sources + ///
+ /// Closes all of the underlying sources. ///
/// public virtual void Close() { + System.IO.IOException firstThrownIOExc = null; foreach (GroupedRandomAccessSource.SourceEntry entry in sources) { - entry.source.Close(); + try { + entry.source.Close(); + } + catch (System.IO.IOException ex) { + if (firstThrownIOExc == null) { + firstThrownIOExc = ex; + } + else { + ILogger logger = LoggerFactory.GetLogger(typeof(iText.IO.Source.GroupedRandomAccessSource)); + logger.Error(LogMessageConstant.ONE_OF_GROUPED_SOURCES_CLOSING_FAILED, ex); + } + } + catch (Exception ex) { + ILogger logger = LoggerFactory.GetLogger(typeof(iText.IO.Source.GroupedRandomAccessSource)); + logger.Error(LogMessageConstant.ONE_OF_GROUPED_SOURCES_CLOSING_FAILED, ex); + } + } + if (firstThrownIOExc != null) { + throw firstThrownIOExc; } } diff --git a/itext/itext.io/itext/io/source/PdfTokenizer.cs b/itext/itext.io/itext/io/source/PdfTokenizer.cs index bd355bee7d..cdbfb6881d 100644 --- a/itext/itext.io/itext/io/source/PdfTokenizer.cs +++ b/itext/itext.io/itext/io/source/PdfTokenizer.cs @@ -340,6 +340,7 @@ public virtual void NextValidToken() { if (level == 1) { // if the level 1 check returns EOF, then we are still looking at a number - set the type back to Number type = PdfTokenizer.TokenType.Number; + outBuf.Reset().Append(n1); } } diff --git a/itext/itext.io/itext/io/source/RAFRandomAccessSource.cs b/itext/itext.io/itext/io/source/RAFRandomAccessSource.cs index a1881ac527..c24352910b 100644 --- a/itext/itext.io/itext/io/source/RAFRandomAccessSource.cs +++ b/itext/itext.io/itext/io/source/RAFRandomAccessSource.cs @@ -73,7 +73,7 @@ public RAFRandomAccessSource(FileStream raf) { /// public virtual int Get(long position) { // TODO: test to make sure we are handling the length properly (i.e. is raf.length() the last byte in the file, or one past the last byte?) - if (position > raf.Length) { + if (position > length) { return -1; } // Not thread safe! diff --git a/itext/itext.io/itext/io/util/EncodingUtil.cs b/itext/itext.io/itext/io/util/EncodingUtil.cs index 755131a33f..b7d60fcecf 100644 --- a/itext/itext.io/itext/io/util/EncodingUtil.cs +++ b/itext/itext.io/itext/io/util/EncodingUtil.cs @@ -51,6 +51,9 @@ namespace iText.IO.Util { /// Be aware that it's API and functionality may be changed in future. ///
public static class EncodingUtil { + + public static Encoding ISO_8859_1 = Encoding.GetEncoding("ISO-8859-1"); + /// public static byte[] ConvertToBytes(char[] chars, String encoding) { Encoding encw = IanaEncodings.GetEncodingEncoding(encoding); diff --git a/itext/itext.io/itext/io/util/FileUtil.cs b/itext/itext.io/itext/io/util/FileUtil.cs index 1760e79d35..3ae44475ca 100644 --- a/itext/itext.io/itext/io/util/FileUtil.cs +++ b/itext/itext.io/itext/io/util/FileUtil.cs @@ -43,7 +43,9 @@ source product. */ using System; +using System.Collections.Generic; using System.IO; +using System.Linq; using System.Text; using System.Threading; @@ -88,18 +90,40 @@ public static String[] ListFilesInDirectory(String path, bool recursive) { return null; } + public static FileInfo[] ListFilesInDirectoryByFilter(String path, IFileFilter filter) { + return ListFilesInDirectoryByFilter(path, false, filter); + } + + public static FileInfo[] ListFilesInDirectoryByFilter(String path, bool recursive, IFileFilter filter) { + if (!String.IsNullOrEmpty(path)) { + DirectoryInfo dir = new DirectoryInfo(path); + if (dir.Exists) { + FileInfo[] files = dir.GetFiles("*.*", recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly); + List list = new List(); + foreach (FileInfo f in files) { + if (filter.Accept(f)) { + list.Add(f); + } + } + return list.ToArray(); + } + } + return null; + } + + [Obsolete] public static String[] ListFilesInDirectoryByFilter(String path, bool recursive, FileFilter filter) { if (!String.IsNullOrEmpty(path)) { DirectoryInfo dir = new DirectoryInfo(path); if (dir.Exists) { FileInfo[] files = dir.GetFiles("*.*", recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly); - String[] list = new String[files.Length]; + var list = new LinkedList(); for (int i = 0; i < files.Length; i++) { if (filter.Accept(files[i].Name)) { - list[i] = files[i].FullName; + list.AddLast(files[i].FullName); } } - return list; + return list.ToArray(); } } return null; @@ -129,10 +153,29 @@ public static FileStream GetRandomAccessFile(FileInfo file) { return file.Open(FileMode.Open); } - public class FileFilter { + public static Stream WrapWithBufferedOutputStream(Stream outputStream) + { + //.NET standard stream already has buffer + return outputStream; + } + + public static void CreateDirectories(String outPath) { + Directory.CreateDirectory(outPath); + } + + public interface IFileFilter { + bool Accept(FileInfo pathname); + } + + [Obsolete] + public class FileFilter : IFileFilter { public virtual bool Accept(String pathname) { return true; } + + public bool Accept(FileInfo pathname) { + return Accept(pathname.Name); + } } } } diff --git a/itext/itext.io/itext/io/util/IntHashtable.cs b/itext/itext.io/itext/io/util/IntHashtable.cs index fcce1d4db4..80979ae96c 100644 --- a/itext/itext.io/itext/io/util/IntHashtable.cs +++ b/itext/itext.io/itext/io/util/IntHashtable.cs @@ -377,6 +377,10 @@ public virtual int GetValue() { protected internal virtual Object Clone() { return new IntHashtable.Entry(key, value, next != null ? (IntHashtable.Entry)next.Clone() : null); } + + public override String ToString() { + return String.Format("{0}={1}", key, value); + } } public virtual int[] ToOrderedKeys() { diff --git a/itext/itext.io/itext/io/util/JavaUtil.cs b/itext/itext.io/itext/io/util/JavaUtil.cs index 89b12aeead..5f8a9e14be 100644 --- a/itext/itext.io/itext/io/util/JavaUtil.cs +++ b/itext/itext.io/itext/io/util/JavaUtil.cs @@ -98,22 +98,23 @@ public static String IntegerToOctalString(int i) { return Convert.ToString(i, 8); } - public static bool ArraysEquals(T[] a, T[] a2) where T : IComparable { + public static bool ArraysEquals(T[] a, T[] a2) { if (a == a2) return true; if (a == null || a2 == null) return false; - if (a.Length != a2.Length) return false; + if (a.Length != a2.Length) + return false; for (int i = 0; i < a.Length; i++) - if (a[i].CompareTo(a2[i]) != 0) + if (!(a[i] == null ? a2[i] == null : a[i].Equals(a2[i]))) return false; return true; } - public static int ArraysHashCode(T[] a) { + public static int ArraysHashCode(params T[] a) { if (a == null) return 0; int result = 1; diff --git a/itext/itext.io/itext/io/util/ResourceUtil.cs b/itext/itext.io/itext/io/util/ResourceUtil.cs index 1d36efc8e7..0bafbff83d 100644 --- a/itext/itext.io/itext/io/util/ResourceUtil.cs +++ b/itext/itext.io/itext/io/util/ResourceUtil.cs @@ -42,6 +42,7 @@ source product. address: sales@itextpdf.com */ +using System; using System.Collections.Generic; using System.IO; using System.Reflection; @@ -75,11 +76,11 @@ public static void AddToResourceSearch(object obj) { /// /// if not found. /// - public static Stream GetResourceStream(string key) { + public static Stream GetResourceStream(string key, Type definedClassType) { Stream istr = null; // Try to use resource loader to load the properties file. try { - Assembly assm = Assembly.GetExecutingAssembly(); + Assembly assm = definedClassType != null ? Assembly.GetAssembly(definedClassType) : Assembly.GetExecutingAssembly(); istr = assm.GetManifestResourceStream(key); } catch { } @@ -126,6 +127,10 @@ public static Stream GetResourceStream(string key) { return istr; } + + public static Stream GetResourceStream(string key) { + return GetResourceStream(key, null); + } } } diff --git a/itext/itext.io/itext/io/util/StringUtil.cs b/itext/itext.io/itext/io/util/StringUtil.cs index 224fb778be..e570940fb8 100644 --- a/itext/itext.io/itext/io/util/StringUtil.cs +++ b/itext/itext.io/itext/io/util/StringUtil.cs @@ -43,6 +43,7 @@ source product. */ using System; +using System.Text; using System.Text.RegularExpressions; namespace iText.IO.Util { @@ -66,5 +67,9 @@ public static Match Match(Regex r, String s) { public static String Group(Match match, int index) { return match.Groups[index].Value; } + + public static String Normalize(String s, NormalizationForm form) { + return s.Normalize(form); + } } } diff --git a/itext/itext.io/itext/io/util/SystemUtil.cs b/itext/itext.io/itext/io/util/SystemUtil.cs index 727410a545..950febd51f 100644 --- a/itext/itext.io/itext/io/util/SystemUtil.cs +++ b/itext/itext.io/itext/io/util/SystemUtil.cs @@ -43,6 +43,8 @@ source product. */ using System; +using System.Diagnostics; +using System.Text; namespace iText.IO.Util { /// @@ -57,5 +59,48 @@ public static long GetSystemTimeTicks() { public static long GetFreeMemory() { return GC.GetTotalMemory(false); } + + /// + /// Gets environment variable with given name. + /// + /// the name of environment variable. + /// variable value or null if there is no such. + public static String GetEnvironmentVariable(String name) { + return Environment.GetEnvironmentVariable(name); + } + + /// + /// + public static bool RunProcessAndWait(String execPath, String @params) { + StringTokenizer st = new StringTokenizer(@params); + String[] cmdArray = new String[st.CountTokens() + 1]; + cmdArray[0] = execPath; + for (int i = 1; st.HasMoreTokens(); ++i) { + cmdArray[i] = st.NextToken(); + } + Process p = new Process(); + p.StartInfo = new ProcessStartInfo(execPath, @params); + p.StartInfo.RedirectStandardOutput = true; + p.StartInfo.RedirectStandardError = true; + p.StartInfo.UseShellExecute = false; + p.StartInfo.CreateNoWindow = true; + p.Start(); + + PrintProcessOutput(p); + p.WaitForExit(); + return true; + } + + /// + private static void PrintProcessOutput(Process p) { + StringBuilder bri = new StringBuilder(); + StringBuilder bre = new StringBuilder(); + while (!p.HasExited) { + bri.Append(p.StandardOutput.ReadToEnd()); + bre.Append(p.StandardError.ReadToEnd()); + } + System.Console.Out.WriteLine(bri.ToString()); + System.Console.Out.WriteLine(bre.ToString()); + } } } \ No newline at end of file diff --git a/itext/itext.io/itext/io/util/UnicodeScriptUtil.cs b/itext/itext.io/itext/io/util/UnicodeScriptUtil.cs index cc23c04b92..81a4476bd9 100644 --- a/itext/itext.io/itext/io/util/UnicodeScriptUtil.cs +++ b/itext/itext.io/itext/io/util/UnicodeScriptUtil.cs @@ -43,10 +43,7 @@ source product. */ using System; -using System.Collections.Generic; using System.Globalization; -using System.Linq; -using System.Text; namespace iText.IO.Util { /// @@ -56,7 +53,7 @@ namespace iText.IO.Util { public static class UnicodeScriptUtil { public const int MAX_CODE_POINT = 0X10FFFF; - private static readonly UnicodeScript[] scripts = { + private static readonly UnicodeScript[] Scripts = { UnicodeScript.COMMON, UnicodeScript.LATIN, UnicodeScript.COMMON, @@ -376,7 +373,7 @@ public static class UnicodeScriptUtil { UnicodeScript.UNKNOWN }; - public static readonly int[] scriptStarts = { + public static readonly int[] ScriptStarts = { 0x0000, // 0000..0040; COMMON 0x0041, // 0041..005A; LATIN 0x005B, // 005B..0060; COMMON @@ -711,7 +708,7 @@ public static class UnicodeScriptUtil { */ public static UnicodeScript Of(int codePoint) { - if (!isValidCodePoint(codePoint)) + if (!IsValidCodePoint(codePoint)) throw new Exception(); char ch = Convert.ToChar(codePoint); UnicodeCategory type = CharUnicodeInfo.GetUnicodeCategory(ch); @@ -719,14 +716,14 @@ public static UnicodeScript Of(int codePoint) { if (type == 0) { return UnicodeScript.UNKNOWN; } - int index = Array.BinarySearch(scriptStarts, codePoint); + int index = Array.BinarySearch(ScriptStarts, codePoint); if (index < 0) { index = -index - 2; } - return scripts[index]; + return Scripts[index]; } - public static bool isValidCodePoint(int codePoint) { + public static bool IsValidCodePoint(int codePoint) { // Optimized form of: // codePoint >= MIN_CODE_POINT && codePoint <= MAX_CODE_POINT int plane = (int) ((uint) codePoint >> 16); diff --git a/itext/itext.io/itext/io/util/UrlUtil.cs b/itext/itext.io/itext/io/util/UrlUtil.cs index 34214f0e7a..e21d89fa88 100644 --- a/itext/itext.io/itext/io/util/UrlUtil.cs +++ b/itext/itext.io/itext/io/util/UrlUtil.cs @@ -68,7 +68,7 @@ public static Uri ToURL(String filename) { public static Stream OpenStream(Uri url) { Stream isp; if (url.IsFile) { - isp = new FileStream(url.AbsolutePath, FileMode.Open, FileAccess.Read); + isp = new FileStream(url.LocalPath, FileMode.Open, FileAccess.Read); } else { WebRequest req = WebRequest.Create(url); req.Credentials = CredentialCache.DefaultCredentials; diff --git a/itext/itext.kernel/Properties/AssemblyInfo.cs b/itext/itext.kernel/Properties/AssemblyInfo.cs index 7ccdaa0f27..e463959943 100644 --- a/itext/itext.kernel/Properties/AssemblyInfo.cs +++ b/itext/itext.kernel/Properties/AssemblyInfo.cs @@ -21,5 +21,5 @@ [assembly: Guid("be4c62cc-6495-47e1-ab00-05b1bfe331f6")] -[assembly: AssemblyVersion("7.0.0.0")] -[assembly: AssemblyFileVersion("7.0.0.0")] +[assembly: AssemblyVersion("7.0.1.0")] +[assembly: AssemblyFileVersion("7.0.1.0")] diff --git a/itext/itext.kernel/itext/kernel/KernelExtensions.cs b/itext/itext.kernel/itext/kernel/KernelExtensions.cs index 4486a7cfaf..423c5503c7 100644 --- a/itext/itext.kernel/itext/kernel/KernelExtensions.cs +++ b/itext/itext.kernel/itext/kernel/KernelExtensions.cs @@ -99,6 +99,10 @@ public static byte[] GetBytes(this String str, String encoding) { return Encoding.GetEncoding(encoding).GetBytes(str); } + public static byte[] GetBytes(this String str, Encoding encoding) { + return encoding.GetBytes(str); + } + public static long Seek(this FileStream fs, long offset) { return fs.Seek(offset, SeekOrigin.Begin); } @@ -151,7 +155,19 @@ public static bool Matches(this String str, String regex) { } public static T[] ToArray(this ICollection col, T[] toArray) { - T[] r = col.ToArray(); + T[] r; + int colSize = col.Count; + if (colSize <= toArray.Length) { + col.CopyTo(toArray, 0); + if (colSize != toArray.Length) { + toArray[colSize] = default(T); + } + r = toArray; + } else { + r = new T[colSize]; + col.CopyTo(r, 0); + } + return r; } @@ -233,6 +249,10 @@ public static bool Contains(this IDictionary diction return dictionary.ContainsKey(key); } + public static Stack Clone(this Stack stack) { + return new Stack(new Stack(stack)); // create stack twice to retain the original order + } + public static void Update(this IDigest dgst, byte[] input) { dgst.Update(input, 0, input.Length); } diff --git a/itext/itext.kernel/itext/kernel/PdfException.cs b/itext/itext.kernel/itext/kernel/PdfException.cs index 6e5e0f8c3e..88430a04b4 100644 --- a/itext/itext.kernel/itext/kernel/PdfException.cs +++ b/itext/itext.kernel/itext/kernel/PdfException.cs @@ -46,409 +46,545 @@ source product. using iText.IO.Util; namespace iText.Kernel { + /// Exception class for exceptions in kernel module. public class PdfException : Exception { - public const String _1IsAnUnknownGraphicsStateDictionary = "{0} is.an.unknown.graphics.state.dictionary"; + public const String _1IsAnUnknownGraphicsStateDictionary = "{0} is an unknown graphics state dictionary."; - public const String _1IsNotAValidPlaceableWindowsMetafile = "{0} is.not.a.valid.placeable.windows.metafile"; + public const String _1IsNotAnAcceptableValueForTheField2 = "{0} is not an acceptable value for the field {1}."; - public const String AnnotShallHaveReferenceToPage = "annot.shall.have.reference.to.page"; + public const String _1IsNotAValidPlaceableWindowsMetafile = "{0} is not a valid placeable windows metafile."; - public const String AppendModeRequiresADocumentWithoutErrorsEvenIfRecoveryWasPossible = "append.mode.requires.a.document.without.errors.even.if.recovery.was.possible"; + [Obsolete] + public const String AnnotShallHaveReferenceToPage = "Annotation shall have reference to page."; - public const String AuthenticatedAttributeIsMissingTheDigest = "authenticated.attribute.is.missing.the.digest"; + public const String AnnotationShallHaveReferenceToPage = "Annotation shall have reference to page."; - public const String AvailableSpaceIsNotEnoughForSignature = "available.space.is.not.enough.for.signature"; + public const String AppendModeRequiresADocumentWithoutErrorsEvenIfRecoveryWasPossible = "Append mode requires a document without errors, even if recovery is possible."; - public const String BadCertificateAndKey = "bad.certificate.and.key"; + public const String AuthenticatedAttributeIsMissingTheDigest = "Authenticated attribute is missing the digest."; - public const String BadUserPassword = "bad.user.password"; + public const String AvailableSpaceIsNotEnoughForSignature = "Available space is not enough for signature."; - public const String CannotAddKidToTheFlushedElement = "cannot.add.kid.to.the.flushed.element"; + public const String BadCertificateAndKey = "Bad public key certificate and/or private key."; - public const String CannotCloseDocument = "cannot.close.document"; + public const String BadUserPassword = "Bad user password. Password is not provided or wrong password provided. Correct password should be passed to PdfReader constructor with properties. See ReaderProperties#setPassword() method."; - public const String CannotCloseDocumentWithAlreadyFlushedPdfCatalog = "cannot.close.document.with.already.flushed.pdf.catalog"; + public const String CannotAddKidToTheFlushedElement = "Cannot add kid to the flushed element."; - public const String CannotConvertPdfArrayToRectanle = "cannot.convert.pdfarray.to.rectangle"; + public const String CannotAddNonDictionaryExtGStateToResources1 = "Cannot add graphic state to resources. The PdfObject type is {0}, but should be PdfDictionary."; - public const String CannotCopyFlushedObject = "cannot.copy.flushed.object"; + public const String CannotAddNonDictionaryPatternToResources1 = "Cannot add pattern to resources. The PdfObject type is {0}, but should be PdfDictionary or PdfStream."; - public const String CannotCopyFlushedTag = "cannot.copy.flushed.tag"; + public const String CannotAddNonDictionaryPropertiesToResources1 = "Cannot add properties to resources. The PdfObject type is {0}, but should be PdfDictionary."; - public const String CannotCopyObjectContent = "cannot.copy.object.content"; + public const String CannotAddNonDictionaryShadingToResources1 = "Cannot add shading to resources. The PdfObject type is {0}, but should be PdfDictionary or PdfStream."; - public const String CannotCopyIndirectObjectFromTheDocumentThatIsBeingWritten = "cannot.copy.indirect.object.from.the.document.that.is.being.written"; + public const String CannotAddNonStreamFormToResources1 = "Cannot add form to resources. The PdfObject type is {0}, but should be PdfStream."; - public const String CannotCopyToDocumentOpenedInReadingMode = "cannot.copy.to.document.opened.in.reading.mode"; + public const String CannotAddNonStreamImageToResources1 = "Cannot add image to resources. The PdfObject type is {0}, but should be PdfStream."; - public const String CannotCreateLayoutImageByWmfImage = "Cannot create layout image by WmfImage instance. First convert the image into FormXObject and then use the corresponding layout image constructor"; + public const String CannotCloseDocument = "Cannot close document."; + + public const String CannotCloseDocumentWithAlreadyFlushedPdfCatalog = "Cannot close document with already flushed PDF Catalog."; + + public const String CannotConvertPdfArrayToRectanle = "Cannot convert PdfArray to Rectangle."; + + public const String CannotCopyFlushedObject = "Cannot copy flushed object."; + + public const String CannotCopyFlushedTag = "Cannot copy flushed tag."; + + public const String CannotCopyObjectContent = "Cannot copy object content."; + + public const String CannotCopyIndirectObjectFromTheDocumentThatIsBeingWritten = "Cannot copy indirect object from the document that is being written."; + + public const String CannotCopyToDocumentOpenedInReadingMode = "Cannot copy to document opened in reading mode."; + + public const String CannotCreateLayoutImageByWmfImage = "Cannot create layout image by WmfImage instance. First convert the image into FormXObject and then use the corresponding layout image constructor."; public const String CannotCreatePdfImageXObjectByWmfImage = "Cannot create PdfImageXObject instance by WmfImage. Use PdfFormXObject constructor instead."; - public const String CannotCreatePdfStreamByInputStreamWithoutPdfDocument = "cannot.create.pdfstream.by.inputstream.without.pdfdocument"; + public const String CannotCreatePdfStreamByInputStreamWithoutPdfDocument = "Cannot create pdfstream by InputStream without PdfDocument."; + + public const String CannotGetContentBytes = "Cannot get content bytes."; + + public const String CannotGetPdfStreamBytes = "Cannot get PdfStream bytes."; + + public const String CannotRetrieveMediaBoxAttribute = "Invalid PDF. There is no media box attribute for page or its parents."; + + public const String CannotFindImageDataOrEI = "Cannot find image data or EI."; + + public const String CannotFlushDocumentRootTagBeforeDocumentIsClosed = "Cannot flush document root tag before document is closed."; + + public const String CannotFlushObject = "Cannot flush object."; + + public const String CannotMoveToFlushedKid = "Cannot move to flushed kid."; + + public const String CannotMoveToMarkedContentReference = "Cannot move to marked content reference."; + + public const String CannotMoveToParentCurrentElementIsRoot = "Cannot move to parent current element is root."; + + public const String CannotOpenDocument = "Cannot open document."; + + public const String CannotParseContentStream = "Cannot parse content stream."; + + public const String CannotReadAStreamInOrderToAppendNewBytes = "Cannot read a stream in order to append new bytes."; + + public const String CannotReadPdfObject = "Cannot read PdfObject."; + + public const String CannotRemoveDocumentRootTag = "Cannot remove document root tag."; + + public const String CannotRemoveMarkedContentReferenceBecauseItsPageWasAlreadyFlushed = "Cannot remove marked content reference, because its page has been already flushed."; + + public const String CannotRemoveTagBecauseItsParentIsFlushed = "Cannot remove tag, because its parent is flushed."; + + [Obsolete] + public const String CannotSetDataToPdfstreamWhichWasCreatedByInputstream = "Cannot set data to PdfStream which was created by InputStream."; + + public const String CannotSetDataToPdfstreamWhichWasCreatedByInputStream = "Cannot set data to PdfStream which was created by InputStream."; + + public const String CannotSplitDocumentThatIsBeingWritten = "Cannot split document that is being written."; + + [Obsolete] + public const String CannotWritePdfStream = "Cannot write pdf stream."; + + public const String CannotWriteToPdfStream = "Cannot write to PdfStream."; + + public const String CannotWriteObjectAfterItWasReleased = "Cannot write object after it was released. In normal situation the object must be read once again before being written."; + + [Obsolete] + public const String CantDecodePkcs7SigneddataObject = "Cannot decode PKCS#7 SignedData object."; + + public const String CannotDecodePkcs7SigneddataObject = "Cannot decode PKCS#7 SignedData object."; + + [Obsolete] + public const String CantFindSigningCertificateWithSerial1 = "Cannot find signing certificate with serial {0}."; + + public const String CannotFindSigningCertificateWithSerial1 = "Cannot find signing certificate with serial {0}."; + + public const String CertificateIsNotProvidedDocumentIsEncryptedWithPublicKeyCertificate = "Certificate is not provided. Document is encrypted with public key certificate, it should be passed to PdfReader constructor with properties. See ReaderProperties#setPublicKeySecurityParams() method."; + + public const String CfNotFoundEncryption = "/CF not found (encryption)"; + + [Obsolete] + public const String CodabarCharacterOneIsIllegal = "the character {0} is illegal in codabar."; + + [Obsolete] + public const String CodabarMustHaveAtLeastAStartAndStopCharacter = "Codabar must have at least start and stop character."; + + public const String CodabarMustHaveAtLeastStartAndStopCharacter = "Codabar must have at least start and stop character."; + + public const String CodabarMustHaveOneAbcdAsStartStopCharacter = "Codabar must have one of 'ABCD' as start/stop character."; + + [Obsolete] + public const String CodabarStartStopCharacterAreOnlyExtremes = "In codabar, start/stop characters are only allowed at the extremes."; - public const String CannotGetContentBytes = "cannot.get.content.bytes"; + public const String ColorNotFound = "Color not found."; - public const String CannotGetPdfStreamBytes = "cannot.get.pdfstream.bytes"; + public const String ColorSpaceNotFound = "ColorSpace not found."; - public const String CannotFindImageDataOrEI = "cannot.find.image.data.or.EI"; + public const String ContentStreamMustNotInvokeOperatorsThatSpecifyColorsOrOtherColorRelatedParameters = "Content stream must not invoke operators that specify colors or other color related parameters in the graphics state."; - public const String CannotFlushDocumentRootTagBeforeDocumentIsClosed = "cannot.flush.document.root.tag.before.document.is.closed"; + public const String DecodeParameterType1IsNotSupported = "Decode parameter type {0} is not supported."; - public const String CannotFlushObject = "cannot.flush.object"; + public const String DefaultcryptfilterNotFoundEncryption = "/DefaultCryptFilter not found (encryption)."; - public const String CannotMoveToFlushedKid = "cannot.move.to.flushed.kid"; + public const String DictionaryKey1IsNotAName = "Dictionary key {0} is not a name."; - public const String CannotMoveToMarkedContentReference = "cannot.move.to.marked.content.reference"; + [Obsolete] + public const String DictionaryNotContainFontData = "Dictionary doesn't have font data."; - public const String CannotMoveToParentCurrentElementIsRoot = "cannot.move.to.parent.current.element.is.root"; + public const String DictionaryDoesntHave1FontData = "Dictionary doesn't have {0} font data."; - public const String CannotOpenDocument = "cannot.open.document"; + public const String DictionaryDoesntHaveSupportedFontData = "Dictionary doesn't have supported font data."; - public const String CannotParseContentStream = "could.not.parse.content.stream"; + public const String DocumentAlreadyPreClosed = "Document has been already pre closed."; - public const String CannotReadAStreamInOrderToAppendNewBytes = "cannot.read.a.stream.in.order.to.append.new.bytes.reason {0}"; + [Obsolete] + public const String DocumentClosedImpossibleExecuteAction = "Document was closed. It is impossible to execute action."; - public const String CannotReadPdfObject = "cannot.read.pdf.object"; + public const String DocumentClosedItIsImpossibleToExecuteAction = "Document was closed. It is impossible to execute action."; - public const String CannotRemoveDocumentRootTag = "cannot.remove.document.root.tag"; + public const String DocumentDoesntContainStructTreeRoot = "Document doesn't contain StructTreeRoot."; - public const String CannotRemoveMarkedContentReferenceBecauseItsPageWasAlreadyFlushed = "cannot.remove.marked.content.reference.because.its.page.was.already.flushed"; + public const String DocumentHasNoPages = "Document has no pages."; - public const String CannotRemoveTagBecauseItsParentIsFlushed = "cannot.remove.tag.because.its.parent.is.flushed"; + [Obsolete] + public const String DocumentHasNoCatalogObject = "Document has no PDF Catalog object."; - public const String CannotSetDataToPdfstreamWhichWasCreatedByInputstream = "cannot.set.data.to.pdfstream.which.was.created.by.inputstream"; + public const String DocumentHasNoPdfCatalogObject = "Document has no PDF Catalog object."; - public const String CannotSplitDocumentThatIsBeingWritten = "cannot.split.document.that.is.being.written"; + [Obsolete] + public const String DocumentMustBePreclosed = "Document must be preClosed."; - public const String CannotWritePdfStream = "cannot.write.pdf.stream"; + public const String DocumentMustBePreClosed = "Document must be preClosed."; - public const String CannotWriteObjectAfterItWasReleased = "Cannot write object after it was released. In normal situation the object must be read once again before being written"; + [Obsolete] + public const String DocumentToCopyToCannotBeNull = "Document for copyTo cannot be null."; - public const String CantDecodePkcs7SigneddataObject = "can.t.decode.pkcs7signeddata.object"; + public const String DocumentForCopyToCannotBeNull = "Document for copyTo cannot be null."; - public const String CantFindSigningCertificateWithSerial1 = "can.t.find.signing.certificate.with.serial {0}"; + public const String ElementCannotFitAnyArea = "Element cannot fit any area."; - public const String CfNotFoundEncryption = "cf.not.found.encryption"; + public const String EncryptionCanOnlyBeAddedBeforeOpeningDocument = "Encryption can only be added before opening the document."; - public const String CodabarCharacterOneIsIllegal = "the.character {0} is.illegal.in.codabar"; + public const String EndOfContentStreamReachedBeforeEndOfImageData = "End of content stream reached before end of image data."; - public const String CodabarMustHaveAtLeastAStartAndStopCharacter = "codabar.must.have.at.least.a.start.and.stop.character"; + [Obsolete] + public const String ErrorReadingObjectStream = "Error while reading Object Stream."; - public const String CodabarMustHaveOneAbcdAsStartStopCharacter = "codabar.must.have.one.of.abcd.as.start.stop.character"; + public const String ErrorWhileReadingObjectStream = "Error while reading Object Stream."; - public const String CodabarStartStopCharacterAreOnlyExtremes = "in.codabar.start.stop.characters.are.only.allowed.at.the.extremes"; + public const String FailedToGetTsaResponseFrom1 = "Failed to get TSA response from {0}."; - public const String ColorNotFound = "color.not.found"; + public const String FieldFlatteningIsNotSupportedInAppendMode = "Field flattening is not supported in append mode."; - public const String ContentStreamMustNotInvokeOperatorsThatSpecifyColorsOrOtherColorRelatedParameters = "content.stream.must.not.invoke.operators.that.specify.colors.or.other.color.related.parameters.in.the.graphics.state"; + [Obsolete] + public const String FieldIsAlreadySigned = "Field has been already signed."; - public const String DecodeParameterType1IsNotSupported = "decode.parameter.type {0} is.not.supported"; + public const String FieldAlreadySigned = "Field has been already signed."; - public const String DefaultcryptfilterNotFoundEncryption = "defaultcryptfilter.not.found.encryption"; + public const String FieldNamesCannotContainADot = "Field names cannot contain a dot."; - public const String DictionaryKey1IsNotAName = "dictionary.key {0} is.not.a.name"; + public const String FieldTypeIsNotASignatureFieldType = "Field type is not a signature field type."; - public const String DictionaryNotContainFontData = "dict.not.contain.font.data"; + public const String Filter1IsNotSupported = "Filter {0} is not supported."; - public const String DocumentAlreadyPreClosed = "document.already.pre.closed"; + [Obsolete] + public const String FilePosition0CrossReferenceEntryInThisXrefSubsection = "file position {0} cross reference entry in this xref subsection."; - public const String DocumentClosedImpossibleExecuteAction = "document.was.closed.it.is.impossible.execute.action"; + public const String FilePosition1CrossReferenceEntryInThisXrefSubsection = "file position {0} cross reference entry in this xref subsection."; - public const String DocumentDoesntContainStructTreeRoot = "document.doesn't.contain.structtreeroot"; + public const String FilterCcittfaxdecodeIsOnlySupportedForImages = "Filter CCITTFaxDecode is only supported for images"; - public const String DocumentHasNoPages = "document.has.no.pages"; + public const String FilterIsNotANameOrArray = "filter is not a name or array."; - public const String DocumentHasNoCatalogObject = "document.has.no.catalog.object"; + public const String FlushedPageCannotBeAddedOrInserted = "Flushed page cannot be added or inserted."; - public const String DocumentMustBePreclosed = "document.must.be.preclosed"; + public const String FontAndSizeMustBeSetBeforeWritingAnyText = "Font and size must be set before writing any text."; - public const String DocumentToCopyToCannotBeNull = "document.to.copy.to.cannot.be.null"; + public const String FontEmbeddingIssue = "Font embedding issue."; - public const String ElementCannotFitAnyArea = "element.cannot.fit.any.area"; + [Obsolete] + public const String FontSizeTooSmall = "Font size is too small."; - public const String EncryptionCanOnlyBeAddedBeforeOpeningDocument = "encryption.can.only.be.added.before.opening.the.document"; + public const String FontSizeIsTooSmall = "Font size is too small."; - public const String EndOfContentStreamReachedBeforeEndOfImageData = "end.of.content.stream.reached.before.end.of.image.data"; + public const String FormXObjectMustHaveBbox = "Form XObject must have BBox."; - public const String ErrorReadingObjectStream = "error.reading.objstm"; + public const String FunctionIsNotCompatibleWitColorSpace = "Function is not compatible with ColorSpace."; - public const String FailedToGetTsaResponseFrom1 = "failed.to.get.tsa.response.from {0}"; + public const String GivenAccessibleElementIsNotConnectedToAnyTag = "Given accessible element is not connected to any tag."; - public const String FieldFlatteningIsNotSupportedInAppendMode = "field.flattening.is.not.supported.in.append.mode"; + public const String IllegalCharacterInAsciihexdecode = "illegal character in ASCIIHexDecode."; - public const String FieldIsAlreadySigned = "field.flattening.is.not.supported.in.append.mode"; + public const String IllegalCharacterInAscii85decode = "Illegal character in ASCII85Decode."; - public const String FieldNamesCannotContainADot = "field.names.cannot.contain.a.dot"; + public const String IllegalCharacterInCodabarBarcode = "Illegal character in Codabar Barcode."; - public const String FieldTypeIsNotASignatureFieldType = "the.field.type.is.not.a.signature.field.type"; + public const String IllegalLengthValue = "Illegal length value."; - public const String Filter1IsNotSupported = "filter {0} is.not.supported"; + public const String IllegalPValue = "Illegal P value."; - public const String FilePosition0CrossReferenceEntryInThisXrefSubsection = "file.position {0} cross.reference.entry.in.this.xref.subsection"; + public const String IllegalRValue = "Illegal R value."; - public const String FilterCcittfaxdecodeIsOnlySupportedForImages = "filter.ccittfaxdecode.is.only.supported.for.images"; + public const String IllegalVValue = "Illegal V value."; - public const String FilterIsNotANameOrArray = "filter.is.not.a.name.or.array"; + public const String InAPageLabelThePageNumbersMustBeGreaterOrEqualTo1 = "In a page label the page numbers must be greater or equal to 1."; - public const String FlushedPageCannotBeAddedOrInserted = "flushed.page.cannot.be.added.or.inserted"; + public const String InCodabarStartStopCharactersAreOnlyAllowedAtTheExtremes = "In Codabar, start/stop characters are only allowed at the extremes."; - public const String FontAndSizeMustBeSetBeforeWritingAnyText = "font.and.size.must.be.set.before.writing.any.text"; + public const String InvalidHttpResponse1 = "Invalid http response {0}."; - public const String FontEmbeddingIssue = "font.embedding.issue"; + public const String InvalidTsa1ResponseCode2 = "Invalid TSA {0} response code {1}."; - public const String FontSizeTooSmall = "font.size.too.small"; + public const String IncorrectNumberOfComponents = "Incorrect number of components."; - public const String FormXObjectMustHaveBbox = "form.xobject.must.have.bbox"; + public const String InlineLevelOrIllustrationElementCannotContainKids = "Inline level or illustration element cannot contain kids."; - public const String FunctionIsNotCompatibleWitColorSpace = "function.is.not.compatible.with.color.space"; + public const String InvalidCodewordSize = "Invalid codeword size."; - public const String GivenAccessibleElementIsNotConnectedToAnyTag = "given.accessible.element.is.not.connected.to.any.tag"; + public const String InvalidCrossReferenceEntryInThisXrefSubsection = "Invalid cross reference entry in this xref subsection."; - public const String IllegalCharacterInAsciihexdecode = "illegal.character.in.asciihexdecode"; + public const String InvalidIndirectReference1 = "Invalid indirect reference {0}."; - public const String IllegalCharacterInAscii85decode = "illegal.character.in.ascii85decode"; + public const String InvalidMediaBoxValue = "Tne media box object has incorrect values."; - public const String IllegalLengthValue = "illegal.length.value"; + public const String InvalidPageStructure1 = "Invalid page structure {0}."; - public const String IllegalPValue = "illegal.p.value"; + public const String InvalidPageStructurePagesPagesMustBePdfDictionary = "Invalid page structure. /Pages must be PdfDictionary."; - public const String IllegalRValue = "illegal.r.value"; + public const String InvalidRangeArray = "Invalid range array."; - public const String IllegalVValue = "illegal.v.value"; + public const String InvalidOffsetForObject1 = "Invalid offset for object {0}."; - public const String InAPageLabelThePageNumbersMustBeGreaterOrEqualTo1 = "in.a.page.label.the.page.numbers.must.be.greater.or.equal.to.1"; + public const String InvalidXrefStream = "Invalid xref stream."; - public const String InvalidHttpResponse1 = "invalid.http.response {0}"; + public const String InvalidXrefTable = "Invalid xref table."; - public const String InvalidTsa1ResponseCode2 = "invalid.tsa {0} response.code {1}"; + public const String IoException = "I/O exception."; - public const String IncorrectNumberOfComponents = "incorrect.number.of.components"; + [Obsolete] + public const String IsNotAnAcceptableValueForTheField = "{0} is not an acceptable value for the field {1}."; - public const String InlineLevelOrIllustrationElementCannotContainKids = "inline.level.or.illustration.element.cannot.contain.kids"; + [Obsolete] + public const String IsNotWmfImage = "Not a WMF image."; - public const String InvalidCodewordSize = "invalid.codeword.size"; + public const String LzwDecoderException = "LZW decoder exception."; - public const String InvalidCrossReferenceEntryInThisXrefSubsection = "invalid.cross.reference.entry.in.this.xref.subsection"; + public const String LzwFlavourNotSupported = "LZW flavour not supported."; - public const String InvalidIndirectReference1 = "invalid.indirect.reference {0}"; + public const String MacroSegmentIdMustBeGtOrEqZero = "macroSegmentId must be >= 0"; - public const String InvalidPageStructure1 = "invalid.page.structure {0}"; + public const String MacroSegmentIdMustBeGtZero = "macroSegmentId must be > 0"; - public const String InvalidPageStructurePagesPagesMustBePdfDictionary = "invalid.page.structure.pages.must.be.pdfdictionary"; + public const String MacroSegmentIdMustBeLtMacroSegmentCount = "macroSegmentId must be < macroSemgentCount"; - public const String InvalidRangeArray = "invalid.range.array"; + public const String MustBeATaggedDocument = "Must be a tagged document."; - public const String InvalidOffsetForObject1 = "invalid.offset.for.object {0}"; + public const String NumberOfEntriesInThisXrefSubsectionNotFound = "Number of entries in this xref subsection not found."; - public const String InvalidXrefStream = "invalid.xref.stream"; + public const String NameAlreadyExistsInTheNameTree = "Name already exists in the name tree."; - public const String InvalidXrefTable = "invalid.xref.table"; + public const String NoCompatibleEncryptionFound = "No compatible encryption found."; - public const String IoException = "io.exception"; + public const String NoCryptoDictionaryDefined = "No crypto dictionary defined."; - public const String IsNotAnAcceptableValueForTheField = "{0}.is.not.an.acceptable.value.for.the.field.{1}"; + public const String NoKidWithSuchRole = "No kid with such role."; - public const String IsNotWmfImage = "is.not.wmf.image"; + public const String NotAPlaceableWindowsMetafile = "Not a placeable windows metafile."; - public const String LzwDecoderException = "lzw.decoder.exception"; + public const String NotAValidPkcs7ObjectNotASequence = "Not a valid PKCS#7 object - not a sequence"; - public const String LzwFlavourNotSupported = "lzw.flavour.not.supported"; + public const String NotAValidPkcs7ObjectNotSignedData = "Not a valid PKCS#7 object - not signed data."; - public const String MacroSegmentIdMustBeGtOrEqZero = "macrosegmentid.must.be.gt.eq.0"; + public const String NotAWmfImage = "Not a WMF image."; - public const String MacroSegmentIdMustBeGtZero = "macrosegmentid.must.be.gt.0"; + public const String NoValidEncryptionMode = "No valid encryption mode."; - public const String MacroSegmentIdMustBeLtMacroSegmentCount = "macrosegmentid.must.be.lt.macrosegmentcount"; + public const String NumberOfBooleansInTheArrayDoesntCorrespondWithTheNumberOfFields = "The number of booleans in the array doesn't correspond with the number of fields."; - public const String MustBeATaggedDocument = "must.be.a.tagged.document"; + public const String ObjectMustBeIndirectToWorkWithThisWrapper = "Object must be indirect to work with this wrapper."; - public const String NumberOfEntriesInThisXrefSubsectionNotFound = "number.of.entries.in.this.xref.subsection.not.found"; + public const String ObjectNumberOfTheFirstObjectInThisXrefSubsectionNotFound = "Object number of the first object in this xref subsection not found."; - public const String NameAlreadyExistsInTheNameTree = "name.already.exist.in.the.name.tree"; + public const String OcspStatusIsRevoked = "OCSP status is revoked."; - public const String NoCompatibleEncryptionFound = "no.compatible.encryption.found"; + public const String OcspStatusIsUnknown = "OCSP status is unknown."; - public const String NoCryptoDictionaryDefined = "no.crypto.dictionary.defined"; + public const String OnlyBmpCanBeWrappedInWmf = "Only BMP can be wrapped in WMF."; - public const String NoKidWithSuchRole = "no.kid.with.such.role"; + public const String OperatorEINotFoundAfterEndOfImageData = "Operator EI not found after the end of image data."; - public const String NotAPlaceableWindowsMetafile = "not.a.placeable.windows.metafile"; + public const String Page1CannotBeAddedToDocument2BecauseItBelongsToDocument3 = "Page {0} cannot be added to document {1}, because it belongs to document {2}."; - public const String NotAValidPkcs7ObjectNotASequence = "not.a.valid.pkcs.7.object.not.a.sequence"; + public const String PageIsNotSetForThePdfTagStructure = "Page is not set for the pdf tag structure."; - public const String NotAValidPkcs7ObjectNotSignedData = "not.a.valid.pkcs.7.object.not.signed.data"; + [Obsolete] + public const String PageWasAlreadyFlushed = "The page has been already flushed."; - public const String NoValidEncryptionMode = "no.valid.encryption.mode"; + public const String PageAlreadyFlushed = "The page has been already flushed."; - public const String ObjectMustBeIndirectToWorkWithThisWrapper = "object.must.be.indirect.to.work.with.this.wrapper"; + [Obsolete] + public const String PageWasAlreadyFlushedUseAddFieldAppearanceToPageMethodBeforePageFlushing = "The page has been already flushed. Use PdfAcroForm#addFieldAppearanceToPage() method before page flushing."; - public const String ObjectNumberOfTheFirstObjectInThisXrefSubsectionNotFound = "object.number.of.the.first.object.in.this.xref.subsection.not.found"; + public const String PageAlreadyFlushedUseAddFieldAppearanceToPageMethodBeforePageFlushing = "The page has been already flushed. Use PdfAcroForm#addFieldAppearanceToPage() method before page flushing."; - public const String OcspStatusIsRevoked = "ocsp.status.is.revoked"; + public const String PdfEncodings = "PdfEncodings exception."; - public const String OcspStatusIsUnknown = "ocsp.status.is.unknown"; + public const String PdfEncryption = "PdfEncryption exception."; - public const String OnlyBmpCanBeWrappedInWmf = "only.bmp.can.be.wrapped.in.wmf"; + public const String PdfDecryption = "Exception occurred with PDF document decryption. One of the possible reasons is wrong password or wrong public key certificate and private key."; - public const String OperatorEINotFoundAfterEndOfImageData = "operator.EI.not.found.after.end.of.image.data"; + public const String PdfDocumentMustBeOpenedInStampingMode = "PdfDocument must be opened in stamping mode."; - public const String Page1CannotBeAddedToDocument2BecauseItBelongsToDocument3 = "page {0} cannot.be.added.to.document {1} because.it.belongs.to.document {2}"; + public const String PdfFormXobjectHasInvalidBbox = "PdfFormXObject has invalid BBox."; - public const String PageIsNotSetForThePdfTagStructure = "page.is.not.set.for.the.pdf.tag.structure"; + public const String PdfObjectStreamReachMaxSize = "PdfObjectStream reach max size."; - public const String PageWasAlreadyFlushed = "the.page.was.already.flushed"; + public const String PdfPageShallHaveContent = "PdfPage shall have content."; - public const String PageWasAlreadyFlushedUseAddFieldAppearanceToPageMethodBeforePageFlushing = "the.page.was.already.flushed.use.add.field.appearance.to.page.method.before.page.flushing"; + public const String PdfPagesTreeCouldBeGeneratedOnlyOnce = "PdfPages tree could be generated only once."; - public const String PdfEncodings = "pdf.encodings"; + public const String PdfStartxrefIsNotFollowedByANumber = "PDF startxref is not followed by a number."; - public const String PdfEncryption = "pdf.encryption"; + public const String PdfStartxrefNotFound = "PDF startxref not found."; - public const String PdfDecryption = "pdf.decryption"; + [System.ObsoleteAttribute(@"Will be removed in iText 7.1.0.

There is a typo in the name of the constant. Use PdfIndirectObjectBelongsToOtherPdfDocument instead." + )] + public const String PdfInderectObjectBelongToOtherPdfDocument = "pdf inderect object belong to other pdf document Copy object to current pdf document."; - public const String PdfDocumentMustBeOpenedInStampingMode = "pdf.document.must.be.opened.in.stamping.mode"; + public const String PdfIndirectObjectBelongsToOtherPdfDocument = "Pdf indirect object belongs to other PDF document. Copy object to current pdf document."; - public const String PdfFormXobjectHasInvalidBbox = "pdf.form.xobject.has.invalid.bbox"; + public const String PdfVersionNotValid = "PDF version is not valid."; - public const String PdfObjectStreamReachMaxSize = "pdf.object.stream.reach.max.size"; + public const String PngFilterUnknown = "PNG filter unknown."; - public const String PdfPageShallHaveContent = "pdf.page.shall.have.content"; + public const String ResourcesCannotBeNull = "Resources cannot be null."; - public const String PdfPagesTreeCouldBeGeneratedOnlyOnce = "pdf.pages.tree.could.be.generated.only.once"; + public const String ResourcesDoNotContainExtgstateEntryUnableToProcessOperator1 = "Resources do not contain ExtGState entry. Unable to process operator {0}."; - public const String PdfStartxrefIsNotFollowedByANumber = "pdf.startxref.is.not.followed.by.a.number"; + public const String RoleIsNotMappedWithAnyStandardRole = "Role is not mapped with any standard role."; - public const String PdfStartxrefNotFound = "pdf.startxref.not.found"; + public const String ShadingTypeNotFound = "Shading type not found."; - public const String PdfInderectObjectBelongToOtherPdfDocument = "pdf.inderect.object.belong.to.other.pdf.document.Copy.object.to.current.pdf.document"; + public const String SignatureWithName1IsNotTheLastItDoesntCoverWholeDocument = "Signature with name {0} is not the last. It doesn't cover the whole document."; - public const String PdfVersionNotValid = "pdf.version.not.valid"; + public const String StdcfNotFoundEncryption = "/StdCF not found (encryption)"; - public const String PngFilterUnknown = "png.filter.unknown"; + public const String StructParentIndexNotFoundInTaggedObject = "StructParent index not found in tagged object."; - public const String ResourcesCannotBeNull = "resources.cannot.be.null"; + public const String StructureElementShallContainParentObject = "StructureElement shall contain parent object."; - public const String ResourcesDoNotContainExtgstateEntryUnableToProcessOperator1 = "resources.do.not.contain.extgstate.entry.unable.to.process.operator {0}"; + public const String TagCannotBeMovedToTheAnotherDocumentsTagStructure = "Tag cannot be moved to the another document's tag structure."; - public const String RoleIsNotMappedWithAnyStandardRole = "role.is.not.mapped.with.any.standard.role"; + public const String TagFromTheExistingTagStructureIsFlushedCannotAddCopiedPageTags = "Tag from the existing tag structure is flushed. Cannot add copied page tags."; - public const String SignatureWithName1IsNotTheLastItDoesntCoverWholeDocument = "signature.with.name.1.is.not.the.last.it.doesnt.cover.whole.document"; + public const String TagStructureCopyingFailedItMightBeCorruptedInOneOfTheDocuments = "Tag structure copying failed: it might be corrupted in one of the documents."; - public const String StdcfNotFoundEncryption = "stdcf.not.found.encryption"; + public const String TagStructureFlushingFailedItMightBeCorrupted = "Tag structure flushing failed: it might be corrupted."; - public const String StructParentIndexNotFoundInTaggedObject = "struct.parent.index.not.found.in.tagged.object"; + public const String TagTreePointerIsInInvalidStateItPointsAtFlushedElementUseMoveToRoot = "TagTreePointer is in invalid state: it points at flushed element. Use TagTreePointer#moveToRoot."; - public const String StructureElementShallContainParentObject = "structure.element.shall.contain.parent.object"; + public const String TagTreePointerIsInInvalidStateItPointsAtRemovedElementUseMoveToRoot = "TagTreePointer is in invalid state: it points at removed element use TagTreePointer#moveToRoot."; - public const String TagCannotBeMovedToTheAnotherDocumentsTagStructure = "tag.cannot.be.moved.to.the.another.documents.tag.structure"; + public const String TextCannotBeNull = "Text cannot be null."; - public const String TagFromTheExistingTagStructureIsFlushedCannotAddCopiedPageTags = "tag.from.the.existing.tag.structure.is.flushed.cannot.add.copied.page.tags"; + public const String TextIsTooBig = "Text is too big."; - public const String TagTreePointerIsInInvalidStateItPointsAtFlushedElementUseMoveToRoot = "tagtreepointer.is.in.invalid.state.it.points.at.flushed.element.use.movetoroot"; + public const String TextMustBeEven = "The text length must be even."; - public const String TagTreePointerIsInInvalidStateItPointsAtRemovedElementUseMoveToRoot = "tagtreepointer.is.in.invalid.state.it.points.at.removed.element.use.movetoroot"; + public const String TwoBarcodeMustBeExternally = "The two barcodes must be composed externally."; - public const String TextCannotBeNull = "text.cannot.be.null"; + [Obsolete] + public const String TheNumberOfBooleansInTheArrayDoesntCorrespondWithTheNumberOfFields = "The number of booleans in the array doesn't correspond with the number of fields."; - public const String TextIsTooBig = "text.is.too.big"; + public const String ThereAreIllegalCharactersForBarcode128In1 = "There are illegal characters for barcode 128 in {0}."; - public const String TextMustBeEven = "the.text.length.must.be.even"; + public const String ThereIsNoAssociatePdfWriterForMakingIndirects = "There is no associate PdfWriter for making indirects."; - public const String TwoBarcodeMustBeExternally = "the.two.barcodes.must.be.composed.externally"; + public const String ThereIsNoFieldInTheDocumentWithSuchName1 = "There is no field in the document with such name: {0}."; - public const String TheNumberOfBooleansInTheArrayDoesntCorrespondWithTheNumberOfFields = "the.number.of.booleans.in.the.array.doesn.t.correspond.with.the.number.of.fields"; + public const String ThisPkcs7ObjectHasMultipleSignerinfosOnlyOneIsSupportedAtThisTime = "This PKCS#7 object has multiple SignerInfos. Only one is supported at this time."; - public const String ThereAreIllegalCharactersForBarcode128In1 = "there.are.illegal.characters.for.barcode.128.in {0}"; + [Obsolete] + public const String ThisInstanceOfPdfSignerIsAlreadyClosed = "This instance of PdfSigner has been already closed."; - public const String ThereIsNoAssociatePdfWriterForMakingIndirects = "there.is.no.associate.pdf.writer.for.making.indirects"; + public const String ThisInstanceOfPdfSignerAlreadyClosed = "This instance of PdfSigner has been already closed."; - public const String ThereIsNoFieldInTheDocumentWithSuchName1 = "there.is.no.field.in.the.document.with.such.name {0}"; + public const String Tsa1FailedToReturnTimeStampToken2 = "TSA {0} failed to return time stamp token: {1}."; - public const String ThisPkcs7ObjectHasMultipleSignerinfosOnlyOneIsSupportedAtThisTime = "this.pkcs.7.object.has.multiple.signerinfos.only.one.is.supported.at.this.time"; + public const String TrailerNotFound = "Trailer not found."; - public const String ThisInstanceOfPdfSignerIsAlreadyClosed = "this.instance.of.PdfSigner.is.already.closed"; + public const String TrailerPrevEntryPointsToItsOwnCrossReferenceSection = "Trailer prev entry points to its own cross reference section."; - public const String Tsa1FailedToReturnTimeStampToken2 = "tsa {0} failed.to.return.time.stamp.token {1}"; + public const String UnbalancedBeginEndMarkedContentOperators = "Unbalanced begin/end marked content operators."; - public const String TrailerNotFound = "trailer.not.found"; + public const String UnbalancedLayerOperators = "Unbalanced layer operators."; - public const String TrailerPrevEntryPointsToItsOwnCrossReferenceSection = "trailer.prev.entry.points.to.its.own.cross.reference.section"; + public const String UnbalancedSaveRestoreStateOperators = "Unbalanced save restore state operators."; - public const String UnbalancedBeginEndMarkedContentOperators = "unbalanced.begin.end.marked.content.operators"; + public const String UnexpectedCharacter1FoundAfterIDInInlineImage = "Unexpected character {0} found after ID in inline image."; - public const String UnbalancedLayerOperators = "unbalanced.layer.operators"; + public const String UnexpectedCloseBracket = "Unexpected close bracket."; - public const String UnbalancedSaveRestoreStateOperators = "unbalanced.save.restore.state.operators"; + public const String UnexpectedColorSpace1 = "Unexpected ColorSpace: {0}."; - public const String UnexpectedCharacter1FoundAfterIDInInlineImage = "unexpected.character.1.found.after.ID.in.inline.image"; + public const String UnexpectedEndOfFile = "Unexpected end of file."; - public const String UnexpectedCloseBracket = "unexpected.close.bracket"; + public const String UnexpectedGtGt = "unexpected >>."; - public const String UnexpectedColorSpace1 = "unexpected.color.space {0}"; + public const String UnexpectedShadingType = "Unexpected shading type."; - public const String UnexpectedEndOfFile = "unexpected.end.of.file"; + public const String UnknownEncryptionTypeREq1 = "Unknown encryption type R == {0}."; - public const String UnexpectedGtGt = "unexpected.gt.gt"; + public const String UnknownEncryptionTypeVEq1 = "Unknown encryption type V == {0}."; - public const String UnexpectedShadingType = "unexpected.shading.type"; + public const String UnknownPdfException = "Unknown PdfException."; - public const String UnknownEncryptionTypeREq1 = "unknown.encryption.type.r.eq {0}"; + public const String UnknownHashAlgorithm1 = "Unknown hash algorithm: {0}."; - public const String UnknownEncryptionTypeVEq1 = "unknown.encryption.type.v.eq {0}"; + public const String UnknownKeyAlgorithm1 = "Unknown key algorithm: {0}."; - public const String UnknownPdfException = "unknown.pdf.exception"; + public const String UnknownColorFormatMustBeRGBorRRGGBB = "Unknown color format: must be rgb or rrggbb."; - public const String UnknownHashAlgorithm1 = "unknown.hash.algorithm {0}"; + public const String UnsupportedDefaultColorSpaceName1 = "Unsupported default color space name. Was {0}, but should be DefaultCMYK, DefaultGray or DefaultRGB"; - public const String UnknownKeyAlgorithm1 = "unknown.key.algorithm {0}"; + public const String UnsupportedXObjectType = "Unsupported XObject type."; - public const String UnknownColorFormatMustBeRGBorRRGGBB = "unknown.color.format.must.be.rgb.or.rrggbb"; + public const String VerificationAlreadyOutput = "Verification already output."; - public const String VerificationAlreadyOutput = "verification.already.output"; + public const String WhenAddingObjectReferenceToTheTagTreeItMustBeConnectedToNotFlushedObject = "When adding object reference to the tag tree, it must be connected to not flushed object."; - public const String WhenAddingObjectReferenceToTheTagTreeItMustBeConnectedToNotFlushedObject = "when.adding.object.reference.to.the.tag.tree.it.must.be.connected.to.not.flushed.object"; + public const String WhitePointIsIncorrectlySpecified = "White point is incorrectly specified."; - public const String WhitePointIsIncorrectlySpecified = "white.point.is.incorrectly.specified"; + public const String WmfImageException = "WMF image exception."; - public const String WmfImageException = "wmf.image.exception"; + public const String WrongFormFieldAddAnnotationToTheField = "Wrong form field. Add annotation to the field."; - public const String WrongFormFieldAddAnnotationToTheField = "wrong.form.field.add.annotation.to.the.field"; + public const String WrongMediaBoxSize1 = "Wrong media box size: {0}."; - public const String XrefSubsectionNotFound = "xref.subsection.not.found"; + public const String XrefSubsectionNotFound = "xref subsection not found."; - public const String YouCannotFlushPdfCatalogManually = "you.cannot.flush.pdf.catalog.manually"; + [Obsolete] + public const String YouCannotFlushPdfCatalogManually = "You cannot flush PdfCatalog manually."; - public const String YouHaveToDefineABooleanArrayForThisCollectionSortDictionary = "you.have.to.define.a.boolean.array.for.this.collection.sort.dictionary"; + public const String YouHaveToDefineABooleanArrayForThisCollectionSortDictionary = "You have to define a boolean array for this collection sort dictionary."; - public const String YouMustSetAValueBeforeAddingAPrefix = "you.must.set.a.value.before.adding.a.prefix"; + public const String YouMustSetAValueBeforeAddingAPrefix = "You must set a value before adding a prefix."; - public const String YouNeedASingleBooleanForThisCollectionSortDictionary = "you.need.a.single.boolean.for.this.collection.sort.dictionary"; + public const String YouNeedASingleBooleanForThisCollectionSortDictionary = "You need a single boolean for this collection sort dictionary."; + ///

Object for more details protected internal Object @object; private IList messageParams; + /// Creates a new instance of PdfException. + /// the detail message. public PdfException(String message) : base(message) { } + /// Creates a new instance of PdfException. + /// + /// the cause (which is saved for later retrieval by + /// + /// method). + /// public PdfException(Exception cause) : this(UnknownPdfException, cause) { } - public PdfException(String message, Object @object) + /// Creates a new instance of PdfException. + /// the detail message. + /// an object for more details. + public PdfException(String message, Object obj) : this(message) { - this.@object = @object; + this.@object = obj; } + /// Creates a new instance of PdfException. + /// the detail message. + /// + /// the cause (which is saved for later retrieval by + /// + /// method). + /// public PdfException(String message, Exception cause) : base(message, cause) { } - public PdfException(String message, Exception cause, Object @object) + /// Creates a new instance of PdfException. + /// the detail message. + /// + /// the cause (which is saved for later retrieval by + /// + /// method). + /// + /// an object for more details. + public PdfException(String message, Exception cause, Object obj) : this(message, cause) { - this.@object = @object; + this.@object = obj; } public override String Message { @@ -462,12 +598,16 @@ public override String Message { } } + /// Sets additional params for Exception message. + /// additional params. + /// object itself. public virtual iText.Kernel.PdfException SetMessageParams(params Object[] messageParams) { this.messageParams = new List(); this.messageParams.AddAll(messageParams); return this; } + /// Gets additional params for Exception message. protected internal virtual Object[] GetMessageParams() { Object[] parameters = new Object[messageParams.Count]; for (int i = 0; i < messageParams.Count; i++) { diff --git a/itext/itext.kernel/itext/kernel/Version.cs b/itext/itext.kernel/itext/kernel/Version.cs index 11a7c11625..4d2cdc1a70 100644 --- a/itext/itext.kernel/itext/kernel/Version.cs +++ b/itext/itext.kernel/itext/kernel/Version.cs @@ -72,7 +72,7 @@ public sealed class Version { /// This String contains the version number of this iText release. /// For debugging purposes, we request you NOT to change this constant. /// - private static String release = "7.0.0"; + private static String release = "7.0.1"; /// This String contains the iText version as shown in the producer line. /// @@ -86,7 +86,7 @@ public sealed class Version { /// The license key. private String key = null; - private static bool expired; + private bool expired; /// Gets an instance of the iText version that is currently used. /// @@ -102,69 +102,58 @@ public static Version GetInstance() { String licenseKeyClassFullName = "iText.License.LicenseKey, itext.licensekey"; String licenseeInfoMethodName = "GetLicenseeInfo"; Type klass = System.Type.GetType(licenseKeyClassFullName); - MethodInfo m = klass.GetMethod(licenseeInfoMethodName); - String[] info = (String[])m.Invoke(System.Activator.CreateInstance(klass), null); - if (info[3] != null && info[3].Trim().Length > 0) { - version.key = info[3]; - } - else { - version.key = "Trial version"; - if (info[5] == null) { - version.key += "unauthorised"; + if (klass != null) { + MethodInfo m = klass.GetMethod(licenseeInfoMethodName); + String[] info = (String[])m.Invoke(System.Activator.CreateInstance(klass), null); + if (info[3] != null && info[3].Trim().Length > 0) { + version.key = info[3]; } else { - version.key += info[5]; - } - } - if (info.Length > 6) { - if (info[6] != null && info[6].Trim().Length > 0) { - String versionToCheck = release.JSubstring(0, release.LastIndexOf(".")); - if (!info[6].EqualsIgnoreCase(versionToCheck)) { - throw new ArgumentException("Your license key version doesn't match the iText version."); - } - } - } - if (info[4] != null && info[4].Trim().Length > 0) { - version.iTextVersion = info[4]; - } - else { - if (info[2] != null && info[2].Trim().Length > 0) { - version.iTextVersion += " (" + info[2]; - if (!version.key.ToLower(System.Globalization.CultureInfo.InvariantCulture).StartsWith("trial")) { - version.iTextVersion += "; licensed version)"; + version.key = "Trial version "; + if (info[5] == null) { + version.key += "unauthorised"; } else { - version.iTextVersion += "; " + version.key + ")"; + version.key += info[5]; } } + if (info.Length > 6) { + if (info[6] != null && info[6].Trim().Length > 0) { + String versionToCheck = release.JSubstring(0, release.LastIndexOf(".")); + if (!info[6].EqualsIgnoreCase(versionToCheck)) { + throw new ArgumentException("Your license key version doesn't match the iText version."); + } + } + } + if (info[4] != null && info[4].Trim().Length > 0) { + version.iTextVersion = info[4]; + } else { - if (info[0] != null && info[0].Trim().Length > 0) { - // fall back to contact name, if company name is unavailable - version.iTextVersion += " (" + info[0]; - if (!version.key.ToLower(System.Globalization.CultureInfo.InvariantCulture).StartsWith("trial")) { + if (info[2] != null && info[2].Trim().Length > 0) { + version.AddLicensedPostfix(info[2]); + } + else { + if (info[0] != null && info[0].Trim().Length > 0) { + // fall back to contact name, if company name is unavailable. // we shouldn't have a licensed version without company name, // but let's account for it anyway - version.iTextVersion += "; licensed version)"; + version.AddLicensedPostfix(info[0]); } else { - version.iTextVersion += "; " + version.key + ")"; + version.AddAGPLPostfix(null); } } - else { - throw new Exception(); - } } } + else { + version.AddAGPLPostfix(null); + } } catch (ArgumentException exc) { throw; } catch (Exception e) { - version.iTextVersion += AGPL; - if (e.InnerException != null && e.InnerException.Message != null && e.InnerException.Message.Contains("expired" - )) { - expired = true; - } + version.AddAGPLPostfix(e.InnerException); } } } @@ -180,7 +169,7 @@ public static bool IsAGPLVersion() { /// Is the license expired? /// true if expired public static bool IsExpired() { - return expired; + return GetInstance().expired; } /// Gets the product name. @@ -222,5 +211,22 @@ public String GetVersion() { public String GetKey() { return key; } + + private void AddLicensedPostfix(String ownerName) { + iTextVersion += " (" + ownerName; + if (!key.ToLower(System.Globalization.CultureInfo.InvariantCulture).StartsWith("trial")) { + iTextVersion += "; licensed version)"; + } + else { + iTextVersion += "; " + key + ")"; + } + } + + private void AddAGPLPostfix(Exception cause) { + iTextVersion += AGPL; + if (cause != null && cause.Message != null && cause.Message.Contains("expired")) { + expired = true; + } + } } } diff --git a/itext/itext.kernel/itext/kernel/colors/Color.cs b/itext/itext.kernel/itext/kernel/colors/Color.cs index b046b6295b..47a09788d3 100644 --- a/itext/itext.kernel/itext/kernel/colors/Color.cs +++ b/itext/itext.kernel/itext/kernel/colors/Color.cs @@ -46,37 +46,60 @@ source product. using iText.Kernel.Pdf.Colorspace; namespace iText.Kernel.Colors { + /// Represents a color public class Color { + /// Predefined black DeviceRgb color public static readonly iText.Kernel.Colors.Color BLACK = new DeviceRgb(0, 0, 0); + /// Predefined blue DeviceRgb color public static readonly iText.Kernel.Colors.Color BLUE = new DeviceRgb(0, 0, 255); + /// Predefined cyan DeviceRgb color public static readonly iText.Kernel.Colors.Color CYAN = new DeviceRgb(0, 255, 255); + /// Predefined dark gray DeviceRgb color public static readonly iText.Kernel.Colors.Color DARK_GRAY = new DeviceRgb(64, 64, 64); + /// Predefined gray DeviceRgb color public static readonly iText.Kernel.Colors.Color GRAY = new DeviceRgb(128, 128, 128); + /// Predefined green DeviceRgb color public static readonly iText.Kernel.Colors.Color GREEN = new DeviceRgb(0, 255, 0); + /// Predefined light gray DeviceRgb color public static readonly iText.Kernel.Colors.Color LIGHT_GRAY = new DeviceRgb(192, 192, 192); + /// Predefined magenta DeviceRgb color public static readonly iText.Kernel.Colors.Color MAGENTA = new DeviceRgb(255, 0, 255); + /// Predefined orange DeviceRgb color public static readonly iText.Kernel.Colors.Color ORANGE = new DeviceRgb(255, 200, 0); + /// Predefined pink DeviceRgb color public static readonly iText.Kernel.Colors.Color PINK = new DeviceRgb(255, 175, 175); + /// Predefined red DeviceRgb color public static readonly iText.Kernel.Colors.Color RED = new DeviceRgb(255, 0, 0); + /// Predefined white DeviceRgb color public static readonly iText.Kernel.Colors.Color WHITE = new DeviceRgb(255, 255, 255); + /// Predefined yellow DeviceRgb color public static readonly iText.Kernel.Colors.Color YELLOW = new DeviceRgb(255, 255, 0); + /// The color space of the color protected internal PdfColorSpace colorSpace; + /// The color value of the color protected internal float[] colorValue; + /// Creates a Color of certain color space and color value. + /// + /// Creates a Color of certain color space and color value. + /// If color value is set in null, all value components will be initialised with zeroes. + /// + /// the color space to which the created Color object relates + /// the color value of the created Color object protected internal Color(PdfColorSpace colorSpace, float[] colorValue) { this.colorSpace = colorSpace; if (colorValue == null) { @@ -87,10 +110,23 @@ protected internal Color(PdfColorSpace colorSpace, float[] colorValue) { } } + /// Makes a Color of certain color space. + /// + /// Makes a Color of certain color space. + /// All color value components will be initialised with zeroes. + /// + /// the color space to which the returned Color object relates public static iText.Kernel.Colors.Color MakeColor(PdfColorSpace colorSpace) { return MakeColor(colorSpace, null); } + /// Makes a Color of certain color space and color value. + /// + /// Makes a Color of certain color space and color value. + /// If color value is set in null, all value components will be initialised with zeroes. + /// + /// the color space to which the returned Color object relates + /// the color value of the returned Color object public static iText.Kernel.Colors.Color MakeColor(PdfColorSpace colorSpace, float[] colorValue) { iText.Kernel.Colors.Color c = null; bool unknownColorSpace = false; @@ -180,6 +216,15 @@ public static iText.Kernel.Colors.Color MakeColor(PdfColorSpace colorSpace, floa return c; } + /// + /// Converts + /// DeviceCmyk + /// color to + /// DeviceRgb + /// color + /// + /// the DeviceCmyk color which will be converted to DeviceRgb color + /// converted color public static DeviceRgb ConvertCmykToRgb(DeviceCmyk cmykColor) { float cyanComp = 1 - cmykColor.GetColorValue()[0]; float magentaComp = 1 - cmykColor.GetColorValue()[1]; @@ -191,6 +236,15 @@ public static DeviceRgb ConvertCmykToRgb(DeviceCmyk cmykColor) { return new DeviceRgb(r, g, b); } + /// + /// Converts + /// DeviceRgb + /// color to + /// DeviceCmyk + /// color + /// + /// the DeviceRgb color which will be converted to DeviceCmyk color + /// converted color public static DeviceCmyk ConvertRgbToCmyk(DeviceRgb rgbColor) { float redComp = rgbColor.GetColorValue()[0]; float greenComp = rgbColor.GetColorValue()[1]; @@ -202,18 +256,30 @@ public static DeviceCmyk ConvertRgbToCmyk(DeviceRgb rgbColor) { return new DeviceCmyk(c, m, y, k); } + /// Returns the number of color value components + /// the number of color value components public virtual int GetNumberOfComponents() { return colorValue.Length; } + /// + /// Returns the + /// color space + /// to which the color is related. + /// + /// the color space of the color public virtual PdfColorSpace GetColorSpace() { return colorSpace; } + /// Returns the color value of the color + /// the color value public virtual float[] GetColorValue() { return colorValue; } + /// Sets the color value of the color + /// new color value public virtual void SetColorValue(float[] value) { colorValue = value; if (colorValue.Length != value.Length) { @@ -221,6 +287,15 @@ public virtual void SetColorValue(float[] value) { } } + /// Indicates whether the color is equal to the given color. + /// + /// Indicates whether the color is equal to the given color. + /// The + /// color space + /// and + /// color value + /// are considered during the comparison. + /// public override bool Equals(Object o) { if (this == o) { return true; @@ -233,6 +308,7 @@ public override bool Equals(Object o) { == null) && iText.IO.Util.JavaUtil.ArraysEquals(colorValue, color.colorValue); } + /// public override int GetHashCode() { int result = colorSpace != null ? colorSpace.GetHashCode() : 0; result = 31 * result + (colorValue != null ? iText.IO.Util.JavaUtil.ArraysHashCode(colorValue) : 0); diff --git a/itext/itext.kernel/itext/kernel/colors/DeviceCmyk.cs b/itext/itext.kernel/itext/kernel/colors/DeviceCmyk.cs index 0695e46cd7..6ea47067c8 100644 --- a/itext/itext.kernel/itext/kernel/colors/DeviceCmyk.cs +++ b/itext/itext.kernel/itext/kernel/colors/DeviceCmyk.cs @@ -41,40 +41,89 @@ source product. For more information, please contact iText Software Corp. at this address: sales@itextpdf.com */ +using iText.IO; +using iText.IO.Log; using iText.Kernel.Pdf.Colorspace; namespace iText.Kernel.Colors { + /// Color space to specify colors according to CMYK color model. public class DeviceCmyk : Color { + /// Predefined cyan DeviceCmyk color public static readonly iText.Kernel.Colors.DeviceCmyk CYAN = new iText.Kernel.Colors.DeviceCmyk(100, 0, 0, 0); + /// Predefined magenta DeviceCmyk color public static readonly iText.Kernel.Colors.DeviceCmyk MAGENTA = new iText.Kernel.Colors.DeviceCmyk(0, 100, 0, 0); + /// Predefined yellow DeviceCmyk color public static readonly iText.Kernel.Colors.DeviceCmyk YELLOW = new iText.Kernel.Colors.DeviceCmyk(0, 0, 100 , 0); + /// Predefined black DeviceCmyk color public static readonly iText.Kernel.Colors.DeviceCmyk BLACK = new iText.Kernel.Colors.DeviceCmyk(0, 0, 0, 100); + /// Creates DeviceCmyk color with all colorants intensities initialised as zeroes. public DeviceCmyk() : this(0f, 0f, 0f, 1f) { } + /// Creates DeviceCmyk color by intensities of cyan, magenta, yellow and black colorants. + /// + /// Creates DeviceCmyk color by intensities of cyan, magenta, yellow and black colorants. + /// The intensities are considered to be in [0, 100] gap, if not, + /// the intensity will be considered as 100 (when colorant's value is bigger than 100) + /// or 0 (when colorant's value is less than 0). + /// + /// the intensity of cyan colorant + /// the intensity of magenta colorant + /// the intensity of yellow colorant + /// the intensity of black colorant public DeviceCmyk(int c, int m, int y, int k) : this(c / 100f, m / 100f, y / 100f, k / 100f) { } + /// Creates DeviceCmyk color by intensities of cyan, magenta, yellow and black colorants. + /// + /// Creates DeviceCmyk color by intensities of cyan, magenta, yellow and black colorants. + /// The intensities are considered to be in [0, 1] interval, if not, + /// the intensity will be considered as 1 (when colorant's value is bigger than 1) + /// or 0 (when colorant's value is less than 0). + /// + /// the intensity of cyan colorant + /// the intensity of magenta colorant + /// the intensity of yellow colorant + /// the intensity of black colorant public DeviceCmyk(float c, float m, float y, float k) - : base(new PdfDeviceCs.Cmyk(), new float[] { c, m, y, k }) { + : base(new PdfDeviceCs.Cmyk(), new float[] { c > 1 ? 1 : (c > 0 ? c : 0), m > 1 ? 1 : (m > 0 ? m : 0), y > + 1 ? 1 : (y > 0 ? y : 0), k > 1 ? 1 : (k > 0 ? k : 0) }) { + if (c > 1 || c < 0 || m > 1 || m < 0 || y > 1 || y < 0 || k > 1 || k < 0) { + ILogger LOGGER = LoggerFactory.GetLogger(typeof(iText.Kernel.Colors.DeviceCmyk)); + LOGGER.Warn(LogMessageConstant.COLORANT_INTENSITIES_INVALID); + } } + /// + /// Returns + /// DeviceCmyk + /// color which is lighter than given one + /// + /// the DeviceCmyk color to be made lighter + /// lighter color public static iText.Kernel.Colors.DeviceCmyk MakeLighter(iText.Kernel.Colors.DeviceCmyk cmykColor) { DeviceRgb rgbEquivalent = ConvertCmykToRgb(cmykColor); DeviceRgb lighterRgb = DeviceRgb.MakeLighter((rgbEquivalent)); return ConvertRgbToCmyk(lighterRgb); } + /// + /// Returns + /// DeviceCmyk + /// color which is darker than given one + /// + /// the DeviceCmyk color to be made darker + /// darker color public static iText.Kernel.Colors.DeviceCmyk MakeDarker(iText.Kernel.Colors.DeviceCmyk cmykColor) { DeviceRgb rgbEquivalent = ConvertCmykToRgb(cmykColor); DeviceRgb darkerRgb = DeviceRgb.MakeDarker(rgbEquivalent); diff --git a/itext/itext.kernel/itext/kernel/colors/DeviceGray.cs b/itext/itext.kernel/itext/kernel/colors/DeviceGray.cs index bfc3c157ff..512f297027 100644 --- a/itext/itext.kernel/itext/kernel/colors/DeviceGray.cs +++ b/itext/itext.kernel/itext/kernel/colors/DeviceGray.cs @@ -42,24 +42,50 @@ source product. address: sales@itextpdf.com */ using System; +using iText.IO; +using iText.IO.Log; using iText.Kernel.Pdf.Colorspace; namespace iText.Kernel.Colors { + /// Color space to specify shades of gray color. public class DeviceGray : Color { + /// Predefined white DeviceGray color. public static readonly iText.Kernel.Colors.DeviceGray WHITE = new iText.Kernel.Colors.DeviceGray(1f); + /// Predefined gray DeviceGray color. public static readonly iText.Kernel.Colors.DeviceGray GRAY = new iText.Kernel.Colors.DeviceGray(.5f); + /// Predefined black DeviceGray color. public static readonly iText.Kernel.Colors.DeviceGray BLACK = new iText.Kernel.Colors.DeviceGray(); + /// Creates DeviceGray color by given grayscale. + /// + /// Creates DeviceGray color by given grayscale. + /// The grayscale is considered to be in [0, 1] interval, if not, + /// the grayscale will be considered as 1 (when grayscale's value is bigger than 1) + /// or 0 (when grayscale's value is less than 0). + /// + /// the grayscale value public DeviceGray(float value) - : base(new PdfDeviceCs.Gray(), new float[] { value }) { + : base(new PdfDeviceCs.Gray(), new float[] { value > 1 ? 1 : (value > 0 ? value : 0) }) { + if (value > 1 || value < 0) { + ILogger LOGGER = LoggerFactory.GetLogger(typeof(iText.Kernel.Colors.DeviceGray)); + LOGGER.Warn(LogMessageConstant.COLORANT_INTENSITIES_INVALID); + } } + /// Creates DeviceGray color with grayscale value initialised as zero. public DeviceGray() : this(0f) { } + /// + /// Returns + /// DeviceGray + /// color which is lighter than given one + /// + /// the DeviceGray color to be made lighter + /// lighter color public static iText.Kernel.Colors.DeviceGray MakeLighter(iText.Kernel.Colors.DeviceGray grayColor) { float v = grayColor.GetColorValue()[0]; if (v == 0f) { @@ -69,6 +95,13 @@ public static iText.Kernel.Colors.DeviceGray MakeLighter(iText.Kernel.Colors.Dev return new iText.Kernel.Colors.DeviceGray(v * multiplier); } + /// + /// Returns + /// DeviceGray + /// color which is darker than given one + /// + /// the DeviceGray color to be made darker + /// darker color public static iText.Kernel.Colors.DeviceGray MakeDarker(iText.Kernel.Colors.DeviceGray grayColor) { float v = grayColor.GetColorValue()[0]; float multiplier = Math.Max(0f, (v - 0.33f) / v); diff --git a/itext/itext.kernel/itext/kernel/colors/DeviceRgb.cs b/itext/itext.kernel/itext/kernel/colors/DeviceRgb.cs index c0ef69f05c..6441e8ab4a 100644 --- a/itext/itext.kernel/itext/kernel/colors/DeviceRgb.cs +++ b/itext/itext.kernel/itext/kernel/colors/DeviceRgb.cs @@ -42,22 +42,58 @@ source product. address: sales@itextpdf.com */ using System; +using iText.IO; +using iText.IO.Log; using iText.Kernel.Pdf.Colorspace; namespace iText.Kernel.Colors { + /// Color space to specify colors according to RGB color model. public class DeviceRgb : Color { + /// Creates DeviceRgb color by intensities of red, green and blue colorants. + /// + /// Creates DeviceRgb color by intensities of red, green and blue colorants. + /// The intensities are considered to be in [0, 255] gap, if not, + /// the intensity will be considered as 255 (when colorant's value is bigger than 255) + /// or 0 (when colorant's value is less than 0). + /// + /// the intensity of red colorant + /// the intensity of green colorant + /// the intensity of blue colorant public DeviceRgb(int r, int g, int b) : this(r / 255f, g / 255f, b / 255f) { } + /// Creates DeviceRgb color by intensities of red, green and blue colorants. + /// + /// Creates DeviceRgb color by intensities of red, green and blue colorants. + /// The intensities are considered to be in [0, 1] interval, if not, + /// the intensity will be considered as 1 (when colorant's value is bigger than 1) + /// or 0 (when colorant's value is less than 0). + /// + /// the intensity of red colorant + /// the intensity of green colorant + /// the intensity of blue colorant public DeviceRgb(float r, float g, float b) - : base(new PdfDeviceCs.Rgb(), new float[] { r, g, b }) { + : base(new PdfDeviceCs.Rgb(), new float[] { r > 1 ? 1 : (r > 0 ? r : 0), g > 1 ? 1 : (g > 0 ? g : 0), b > + 1 ? 1 : (b > 0 ? b : 0) }) { + if (r > 1 || r < 0 || g > 1 || g < 0 || b > 1 || b < 0) { + ILogger LOGGER = LoggerFactory.GetLogger(typeof(iText.Kernel.Colors.DeviceRgb)); + LOGGER.Warn(LogMessageConstant.COLORANT_INTENSITIES_INVALID); + } } + /// Creates DeviceRgb color with all colorants intensities initialised as zeroes. public DeviceRgb() : this(0f, 0f, 0f) { } + /// + /// Returns + /// DeviceRgb + /// color which is lighter than given one + /// + /// the DeviceRgb color to be made lighter + /// lighter color public static iText.Kernel.Colors.DeviceRgb MakeLighter(iText.Kernel.Colors.DeviceRgb rgbColor) { float r = rgbColor.GetColorValue()[0]; float g = rgbColor.GetColorValue()[1]; @@ -73,6 +109,13 @@ public static iText.Kernel.Colors.DeviceRgb MakeLighter(iText.Kernel.Colors.Devi return new iText.Kernel.Colors.DeviceRgb(r, g, b); } + /// + /// Returns + /// DeviceRgb + /// color which is darker than given one + /// + /// the DeviceRgb color to be made darker + /// darker color public static iText.Kernel.Colors.DeviceRgb MakeDarker(iText.Kernel.Colors.DeviceRgb rgbColor) { float r = rgbColor.GetColorValue()[0]; float g = rgbColor.GetColorValue()[1]; diff --git a/itext/itext.kernel/itext/kernel/colors/IccBased.cs b/itext/itext.kernel/itext/kernel/colors/IccBased.cs index 1b05656349..9b6dd3821a 100644 --- a/itext/itext.kernel/itext/kernel/colors/IccBased.cs +++ b/itext/itext.kernel/itext/kernel/colors/IccBased.cs @@ -57,7 +57,6 @@ public IccBased(PdfCieBasedCs.IccBased cs, float[] value) /// Creates IccBased color. /// ICC profile stream. User is responsible for closing the stream. - /// public IccBased(Stream iccStream) : this(new PdfCieBasedCs.IccBased(iccStream), null) { // TODO if zero if outside of the Range, default value should be the nearest to the zero valid value @@ -70,7 +69,6 @@ public IccBased(Stream iccStream) /// Creates IccBased color. /// ICC profile stream. User is responsible for closing the stream. /// color value. - /// public IccBased(Stream iccStream, float[] value) : this(new PdfCieBasedCs.IccBased(iccStream), value) { } diff --git a/itext/itext.kernel/itext/kernel/crypto/BadPasswordException.cs b/itext/itext.kernel/itext/kernel/crypto/BadPasswordException.cs index 765416bfc0..8a47afe83b 100644 --- a/itext/itext.kernel/itext/kernel/crypto/BadPasswordException.cs +++ b/itext/itext.kernel/itext/kernel/crypto/BadPasswordException.cs @@ -45,13 +45,23 @@ source product. using iText.Kernel; namespace iText.Kernel.Crypto { + /// Bad password exception. public class BadPasswordException : PdfException { public const String PdfReaderNotOpenedWithOwnerPassword = "PdfReader is not opened with owner password"; + /// Creates a new BadPasswordException. + /// the detail message. + /// + /// the cause (which is saved for later retrieval by + /// + /// method). + /// public BadPasswordException(String message, Exception cause) : base(message, cause) { } + /// Creates a new BadPasswordException. + /// the detail message. public BadPasswordException(String message) : base(message) { } diff --git a/itext/itext.kernel/itext/kernel/crypto/CryptoUtil.cs b/itext/itext.kernel/itext/kernel/crypto/CryptoUtil.cs new file mode 100644 index 0000000000..33c766faca --- /dev/null +++ b/itext/itext.kernel/itext/kernel/crypto/CryptoUtil.cs @@ -0,0 +1,68 @@ +/* + This file is part of the iText (R) project. + Copyright (c) 1998-2016 iText Group NV + Authors: Bruno Lowagie, Paulo Soares, et al. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License version 3 + as published by the Free Software Foundation with the addition of the + following permission added to Section 15 as permitted in Section 7(a): + FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY + ITEXT GROUP. ITEXT GROUP DISCLAIMS THE WARRANTY OF NON INFRINGEMENT + OF THIRD PARTY RIGHTS + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Affero General Public License for more details. + You should have received a copy of the GNU Affero General Public License + along with this program; if not, see http://www.gnu.org/licenses or write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA, 02110-1301 USA, or download the license from the following URL: + http://itextpdf.com/terms-of-use/ + + The interactive user interfaces in modified source and object code versions + of this program must display Appropriate Legal Notices, as required under + Section 5 of the GNU Affero General Public License. + + In accordance with Section 7(b) of the GNU Affero General Public License, + a covered work must retain the producer line in every PDF that is created + or manipulated using iText. + + You can be released from the requirements of the license by purchasing + a commercial license. Buying such a license is mandatory as soon as you + develop commercial activities involving the iText software without + disclosing the source code of your own applications. + These activities include: offering paid services to customers as an ASP, + serving PDFs on the fly in a web application, shipping iText with a closed + source product. + + For more information, please contact iText Software Corp. at this + address: sales@itextpdf.com + */ + +using System; +using System.IO; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Pkcs; +using Org.BouncyCastle.X509; + +namespace iText.Kernel.Crypto { + /// + /// This file is a helper class for internal usage only. + /// Be aware that it's API and functionality may be changed in future. + /// + public static class CryptoUtil { + + public static X509Certificate ReadPublicCertificate(Stream s) { + return new X509CertificateParser().ReadCertificate(s); + } + + /// + /// + public static ICipherParameters ReadPrivateKeyFromPkcs12KeyStore(Stream keyStore, String pkAlias, char[] pkPassword) { + return new Pkcs12Store(keyStore, pkPassword).GetKey(pkAlias).Key; + } + + } +} \ No newline at end of file diff --git a/itext/itext.kernel/itext/kernel/crypto/IVGenerator.cs b/itext/itext.kernel/itext/kernel/crypto/IVGenerator.cs index 0489cd0315..95f39d0594 100644 --- a/itext/itext.kernel/itext/kernel/crypto/IVGenerator.cs +++ b/itext/itext.kernel/itext/kernel/crypto/IVGenerator.cs @@ -57,7 +57,7 @@ static IVGenerator() { long time = SystemUtil.GetSystemTimeTicks(); long mem = SystemUtil.GetFreeMemory(); String s = time + "+" + mem; - arcfour.PrepareARCFOURKey(s.GetBytes()); + arcfour.PrepareARCFOURKey(s.GetBytes(iText.IO.Util.EncodingUtil.ISO_8859_1)); } /// Creates a new instance of IVGenerator diff --git a/itext/itext.kernel/itext/kernel/crypto/securityhandler/EncryptionUtils.cs b/itext/itext.kernel/itext/kernel/crypto/securityhandler/EncryptionUtils.cs index 3b782da485..07eb505a10 100644 --- a/itext/itext.kernel/itext/kernel/crypto/securityhandler/EncryptionUtils.cs +++ b/itext/itext.kernel/itext/kernel/crypto/securityhandler/EncryptionUtils.cs @@ -63,14 +63,18 @@ internal static byte[] FetchEnvelopedData(ICipherParameters certificateKey, X509 bool foundRecipient = false; byte[] envelopedData = null; for (int i = 0; i < recipients.Size(); i++) { - PdfString recipient = recipients.GetAsString(i); - CmsEnvelopedData data = new CmsEnvelopedData(recipient.GetValueBytes()); - - foreach (RecipientInformation recipientInfo in data.GetRecipientInfos().GetRecipients()) { - if (recipientInfo.RecipientID.Match(certificate) && !foundRecipient) { - envelopedData = recipientInfo.GetContent(certificateKey); - foundRecipient = true; + try { + PdfString recipient = recipients.GetAsString(i); + CmsEnvelopedData data = new CmsEnvelopedData(recipient.GetValueBytes()); + + foreach (RecipientInformation recipientInfo in data.GetRecipientInfos().GetRecipients()) { + if (recipientInfo.RecipientID.Match(certificate) && !foundRecipient) { + envelopedData = recipientInfo.GetContent(certificateKey); + foundRecipient = true; + } } + } catch (Exception f) { + throw new PdfException(PdfException.PdfDecryption, f); } } if (!foundRecipient || envelopedData == null) { diff --git a/itext/itext.kernel/itext/kernel/crypto/securityhandler/PubSecHandlerUsingAes128.cs b/itext/itext.kernel/itext/kernel/crypto/securityhandler/PubSecHandlerUsingAes128.cs index 4c5fd69bfa..adf7e73daa 100644 --- a/itext/itext.kernel/itext/kernel/crypto/securityhandler/PubSecHandlerUsingAes128.cs +++ b/itext/itext.kernel/itext/kernel/crypto/securityhandler/PubSecHandlerUsingAes128.cs @@ -50,6 +50,8 @@ source product. namespace iText.Kernel.Crypto.Securityhandler { public class PubSecHandlerUsingAes128 : PubKeySecurityHandler { + private static readonly byte[] salt = new byte[] { (byte)0x73, (byte)0x41, (byte)0x6c, (byte)0x54 }; + public PubSecHandlerUsingAes128(PdfDictionary encryptionDictionary, X509Certificate[] certs, int[] permissions , bool encryptMetadata, bool embeddedFilesOnly) { InitKeyAndFillDictionary(encryptionDictionary, certs, permissions, encryptMetadata, embeddedFilesOnly); @@ -68,6 +70,24 @@ public override IDecryptor GetDecryptor() { return new AesDecryptor(nextObjectKey, 0, nextObjectKeySize); } + public override void SetHashKeyForNextObject(int objNumber, int objGeneration) { + md5.Reset(); + // added by ujihara + extra[0] = (byte)objNumber; + extra[1] = (byte)(objNumber >> 8); + extra[2] = (byte)(objNumber >> 16); + extra[3] = (byte)objGeneration; + extra[4] = (byte)(objGeneration >> 8); + md5.Update(mkey); + md5.Update(extra); + md5.Update(salt); + nextObjectKey = md5.Digest(); + nextObjectKeySize = mkey.Length + 5; + if (nextObjectKeySize > 16) { + nextObjectKeySize = 16; + } + } + protected internal override String GetDigestAlgorithm() { return "SHA-1"; } @@ -90,6 +110,7 @@ protected internal override void SetPubSecSpecificHandlerDicEntries(PdfDictionar stdcf.Put(PdfName.EncryptMetadata, PdfBoolean.FALSE); } stdcf.Put(PdfName.CFM, PdfName.AESV2); + stdcf.Put(PdfName.Length, new PdfNumber(128)); PdfDictionary cf = new PdfDictionary(); cf.Put(PdfName.DefaultCryptFilter, stdcf); encryptionDictionary.Put(PdfName.CF, cf); diff --git a/itext/itext.kernel/itext/kernel/crypto/securityhandler/PubSecHandlerUsingAes256.cs b/itext/itext.kernel/itext/kernel/crypto/securityhandler/PubSecHandlerUsingAes256.cs index d7a8277a63..6b8295ae9a 100644 --- a/itext/itext.kernel/itext/kernel/crypto/securityhandler/PubSecHandlerUsingAes256.cs +++ b/itext/itext.kernel/itext/kernel/crypto/securityhandler/PubSecHandlerUsingAes256.cs @@ -58,6 +58,10 @@ public PubSecHandlerUsingAes256(PdfDictionary encryptionDictionary, ICipherParam : base(encryptionDictionary, certificateKey, certificate, encryptMetadata) { } + public override void SetHashKeyForNextObject(int objNumber, int objGeneration) { + } + + // in AES256 we don't recalculate nextObjectKey protected internal override String GetDigestAlgorithm() { return "SHA-256"; } @@ -80,6 +84,7 @@ protected internal override void SetPubSecSpecificHandlerDicEntries(PdfDictionar stdcf.Put(PdfName.EncryptMetadata, PdfBoolean.FALSE); } stdcf.Put(PdfName.CFM, PdfName.AESV3); + stdcf.Put(PdfName.Length, new PdfNumber(256)); PdfDictionary cf = new PdfDictionary(); cf.Put(PdfName.DefaultCryptFilter, stdcf); encryptionDictionary.Put(PdfName.CF, cf); diff --git a/itext/itext.kernel/itext/kernel/font/DocFontEncoding.cs b/itext/itext.kernel/itext/kernel/font/DocFontEncoding.cs index 2319f8e387..c7f72abedf 100644 --- a/itext/itext.kernel/itext/kernel/font/DocFontEncoding.cs +++ b/itext/itext.kernel/itext/kernel/font/DocFontEncoding.cs @@ -53,7 +53,7 @@ internal class DocFontEncoding : FontEncoding { protected internal DocFontEncoding() { } - public static FontEncoding CreateDocFontEncoding(PdfObject encoding, CMapToUnicode toUnicode, bool fillBaseEncoding + public static FontEncoding CreateDocFontEncoding(PdfObject encoding, CMapToUnicode toUnicode, bool fillStandardEncoding ) { if (encoding != null) { if (encoding.IsName()) { @@ -63,9 +63,8 @@ public static FontEncoding CreateDocFontEncoding(PdfObject encoding, CMapToUnico if (encoding.IsDictionary()) { iText.Kernel.Font.DocFontEncoding fontEncoding = new iText.Kernel.Font.DocFontEncoding(); fontEncoding.differences = new String[256]; - if (fillBaseEncoding) { - FillBaseEncoding(fontEncoding, ((PdfDictionary)encoding).GetAsName(PdfName.BaseEncoding)); - } + FillBaseEncoding(fontEncoding, ((PdfDictionary)encoding).GetAsName(PdfName.BaseEncoding), fillStandardEncoding + ); FillDifferences(fontEncoding, ((PdfDictionary)encoding).GetAsArray(PdfName.Differences), toUnicode); return fontEncoding; } @@ -82,12 +81,8 @@ public static FontEncoding CreateDocFontEncoding(PdfObject encoding, CMapToUnico } } - public static FontEncoding CreateDocFontEncoding(PdfObject encoding, CMapToUnicode toUnicode) { - return CreateDocFontEncoding(encoding, toUnicode, true); - } - private static void FillBaseEncoding(iText.Kernel.Font.DocFontEncoding fontEncoding, PdfName baseEncodingName - ) { + , bool fillStandardEncoding) { if (baseEncodingName != null) { fontEncoding.baseEncoding = baseEncodingName.GetValue(); } @@ -111,7 +106,9 @@ private static void FillBaseEncoding(iText.Kernel.Font.DocFontEncoding fontEncod fontEncoding.FillNamedEncoding(); } else { - fontEncoding.FillStandardEncoding(); + if (fillStandardEncoding) { + fontEncoding.FillStandardEncoding(); + } } } @@ -127,7 +124,7 @@ private static void FillDifferences(iText.Kernel.Font.DocFontEncoding fontEncodi } else { String glyphName = ((PdfName)obj).GetValue(); - int unicode = (int)AdobeGlyphList.NameToUnicode(glyphName); + int unicode = AdobeGlyphList.NameToUnicode(glyphName); if (unicode != -1) { fontEncoding.codeToUnicode[currentNumber] = (int)unicode; fontEncoding.unicodeToCode.Put((int)unicode, currentNumber); diff --git a/itext/itext.kernel/itext/kernel/font/DocTrueTypeFont.cs b/itext/itext.kernel/itext/kernel/font/DocTrueTypeFont.cs index fcf813c43e..90d954967e 100644 --- a/itext/itext.kernel/itext/kernel/font/DocTrueTypeFont.cs +++ b/itext/itext.kernel/itext/kernel/font/DocTrueTypeFont.cs @@ -56,6 +56,8 @@ internal class DocTrueTypeFont : TrueTypeFont, IDocFontProgram { private PdfName subtype; + private int missingWidth = 0; + private DocTrueTypeFont(PdfDictionary fontDictionary) : base() { PdfName baseFontName = fontDictionary.GetAsName(PdfName.BaseFont); @@ -73,13 +75,15 @@ internal static TrueTypeFont CreateFontProgram(PdfDictionary fontDictionary, Fon FillFontDescriptor(fontProgram, fontDictionary.GetAsDictionary(PdfName.FontDescriptor)); PdfNumber firstCharNumber = fontDictionary.GetAsNumber(PdfName.FirstChar); int firstChar = firstCharNumber != null ? Math.Max(firstCharNumber.IntValue(), 0) : 0; - int[] widths = FontUtil.ConvertSimpleWidthsArray(fontDictionary.GetAsArray(PdfName.Widths), firstChar); + int[] widths = FontUtil.ConvertSimpleWidthsArray(fontDictionary.GetAsArray(PdfName.Widths), firstChar, fontProgram + .GetMissingWidth()); fontProgram.avgWidth = 0; int glyphsWithWidths = 0; for (int i = 0; i < 256; i++) { Glyph glyph = new Glyph(i, widths[i], fontEncoding.GetUnicode(i)); fontProgram.codeToGlyph[i] = glyph; - if (glyph.HasValidUnicode()) { + //FontEncoding.codeToUnicode table has higher priority + if (glyph.HasValidUnicode() && fontEncoding.ConvertToByte(glyph.GetUnicode()) == i) { fontProgram.unicodeToGlyph[glyph.GetUnicode()] = glyph; } if (widths[i] > 0) { @@ -133,6 +137,10 @@ public virtual PdfName GetSubtype() { return subtype; } + public virtual int GetMissingWidth() { + return missingWidth; + } + internal static void FillFontDescriptor(iText.Kernel.Font.DocTrueTypeFont font, PdfDictionary fontDesc) { if (fontDesc == null) { return; @@ -169,6 +177,10 @@ internal static void FillFontDescriptor(iText.Kernel.Font.DocTrueTypeFont font, if (v != null) { font.SetFontWeight(v.IntValue()); } + v = fontDesc.GetAsNumber(PdfName.MissingWidth); + if (v != null) { + font.missingWidth = v.IntValue(); + } PdfName fontStretch = fontDesc.GetAsName(PdfName.FontStretch); if (fontStretch != null) { font.SetFontWidth(fontStretch.GetValue()); diff --git a/itext/itext.kernel/itext/kernel/font/DocType1Font.cs b/itext/itext.kernel/itext/kernel/font/DocType1Font.cs index 1ab0fbf4bc..babe609c22 100644 --- a/itext/itext.kernel/itext/kernel/font/DocType1Font.cs +++ b/itext/itext.kernel/itext/kernel/font/DocType1Font.cs @@ -55,6 +55,8 @@ internal class DocType1Font : Type1Font, IDocFontProgram { private PdfName subtype; + private int missingWidth = 0; + private DocType1Font(String fontName) : base(fontName) { } @@ -89,15 +91,16 @@ internal static Type1Font CreateFontProgram(PdfDictionary fontDictionary, FontEn FillFontDescriptor(fontProgram, fontDesc); PdfNumber firstCharNumber = fontDictionary.GetAsNumber(PdfName.FirstChar); int firstChar = firstCharNumber != null ? Math.Max(firstCharNumber.IntValue(), 0) : 0; - int[] widths = FontUtil.ConvertSimpleWidthsArray(fontDictionary.GetAsArray(PdfName.Widths), firstChar); + int[] widths = FontUtil.ConvertSimpleWidthsArray(fontDictionary.GetAsArray(PdfName.Widths), firstChar, fontProgram + .GetMissingWidth()); fontProgram.avgWidth = 0; int glyphsWithWidths = 0; for (int i = 0; i < 256; i++) { Glyph glyph = new Glyph(i, widths[i], fontEncoding.GetUnicode(i)); fontProgram.codeToGlyph[i] = glyph; if (glyph.HasValidUnicode()) { - // Workaround for fonts for embedded Document fonts with differences without base encoding - if (!fontProgram.unicodeToGlyph.ContainsKey(glyph.GetUnicode()) || glyph.GetWidth() != 0) { + //FontEncoding.codeToUnicode table has higher priority + if (fontEncoding.ConvertToByte(glyph.GetUnicode()) == i) { fontProgram.unicodeToGlyph[glyph.GetUnicode()] = glyph; } } @@ -129,6 +132,10 @@ public virtual PdfName GetSubtype() { return subtype; } + public virtual int GetMissingWidth() { + return missingWidth; + } + internal static void FillFontDescriptor(iText.Kernel.Font.DocType1Font font, PdfDictionary fontDesc) { if (fontDesc == null) { return; @@ -165,6 +172,10 @@ internal static void FillFontDescriptor(iText.Kernel.Font.DocType1Font font, Pdf if (v != null) { font.SetFontWeight(v.IntValue()); } + v = fontDesc.GetAsNumber(PdfName.MissingWidth); + if (v != null) { + font.missingWidth = v.IntValue(); + } PdfName fontStretch = fontDesc.GetAsName(PdfName.FontStretch); if (fontStretch != null) { font.SetFontWidth(fontStretch.GetValue()); diff --git a/itext/itext.kernel/itext/kernel/font/FontUtil.cs b/itext/itext.kernel/itext/kernel/font/FontUtil.cs index 50f9cd3d6a..43b1535524 100644 --- a/itext/itext.kernel/itext/kernel/font/FontUtil.cs +++ b/itext/itext.kernel/itext/kernel/font/FontUtil.cs @@ -111,14 +111,17 @@ internal static String CreateRandomFontName() { return s.ToString(); } - internal static int[] ConvertSimpleWidthsArray(PdfArray widthsArray, int first) { + internal static int[] ConvertSimpleWidthsArray(PdfArray widthsArray, int first, int missingWidth) { int[] res = new int[256]; + for (int i = 0; i < res.Length; i++) { + res[i] = missingWidth; + } if (widthsArray == null) { return res; } - for (int i = 0; i < widthsArray.Size() && first + i < 256; i++) { - PdfNumber number = widthsArray.GetAsNumber(i); - res[first + i] = number != null ? number.IntValue() : 0; + for (int i_1 = 0; i_1 < widthsArray.Size() && first + i_1 < 256; i_1++) { + PdfNumber number = widthsArray.GetAsNumber(i_1); + res[first + i_1] = number != null ? number.IntValue() : missingWidth; } return res; } diff --git a/itext/itext.kernel/itext/kernel/font/PdfFont.cs b/itext/itext.kernel/itext/kernel/font/PdfFont.cs index 948ad54619..d0f7a1d5a1 100644 --- a/itext/itext.kernel/itext/kernel/font/PdfFont.cs +++ b/itext/itext.kernel/itext/kernel/font/PdfFont.cs @@ -77,13 +77,38 @@ protected internal PdfFont(PdfDictionary fontDictionary) protected internal PdfFont() : base(new PdfDictionary()) { - MarkObjectAsIndirect(GetPdfObject()); GetPdfObject().Put(PdfName.Type, PdfName.Font); } + /// Get glyph by unicode + /// a unicode code point + /// + /// + /// Glyph + /// if it exists or .NOTDEF if supported, otherwise + /// + /// . + /// public abstract Glyph GetGlyph(int unicode); + /// Check whether font contains glyph with specified unicode. + /// a unicode code point + /// + /// true if font contains glyph, represented with the unicode code point, + /// otherwise false. + /// + [System.ObsoleteAttribute(@"Use ContainsGlyph(int) instead.")] public virtual bool ContainsGlyph(char unicode) { + return ContainsGlyph((int)unicode); + } + + /// Check whether font contains glyph with specified unicode. + /// a unicode code point + /// + /// true if font contains glyph, represented with the unicode code point, + /// otherwise false. + /// + public virtual bool ContainsGlyph(int unicode) { Glyph glyph = GetGlyph(unicode); if (glyph != null) { if (GetFontProgram() != null && GetFontProgram().IsFontSpecific()) { @@ -352,7 +377,12 @@ public virtual void AddSubsetRange(int[] range) { subsetRanges.Add(range); } + [System.ObsoleteAttribute(@"Will be removed in 7.1. Use SplitString(System.String, float, float) instead")] public virtual IList SplitString(String text, int fontSize, float maxWidth) { + return SplitString(text, (float)fontSize, maxWidth); + } + + public virtual IList SplitString(String text, float fontSize, float maxWidth) { IList resultString = new List(); int lastWhiteSpace = 0; int startPos = 0; @@ -382,6 +412,21 @@ public virtual IList SplitString(String text, int fontSize, float maxWid return resultString; } + /// + /// To manually flush a + /// PdfObject + /// behind this wrapper, you have to ensure + /// that this object is added to the document, i.e. it has an indirect reference. + /// Basically this means that before flushing you need to explicitly call + /// + /// . + /// For example: wrapperInstance.makeIndirect(document).flush(); + /// Note that not every wrapper require this, only those that have such warning in documentation. + /// + public override void Flush() { + base.Flush(); + } + protected internal abstract PdfDictionary GetFontDescriptor(String fontName); protected internal override bool IsWrappedObjectMustBeIndirect() { @@ -400,7 +445,7 @@ protected internal virtual bool CheckTrueTypeFontDictionary(PdfDictionary fontDi if (fontDic == null || fontDic.Get(PdfName.Subtype) == null || !(fontDic.Get(PdfName.Subtype).Equals(PdfName .TrueType) || fontDic.Get(PdfName.Subtype).Equals(PdfName.Type1))) { if (isException) { - throw new PdfException(PdfException.DictionaryNotContainFontData).SetMessageParams(PdfName.TrueType.GetValue + throw new PdfException(PdfException.DictionaryDoesntHave1FontData).SetMessageParams(PdfName.TrueType.GetValue ()); } return false; @@ -437,8 +482,7 @@ protected internal static String CreateSubsetPrefix() { /// /// , if there is an error reading the font. /// - /// - /// PdfException + /// /// Method will throw exception if /// /// is @@ -450,6 +494,7 @@ protected internal virtual PdfStream GetPdfFontStream(byte[] fontStreamBytes, in throw new PdfException(PdfException.FontEmbeddingIssue); } PdfStream fontStream = new PdfStream(fontStreamBytes); + MakeObjectIndirect(fontStream); for (int k = 0; k < fontStreamLengths.Length; ++k) { fontStream.Put(new PdfName("Length" + (k + 1)), new PdfNumber(fontStreamLengths[k])); } @@ -484,5 +529,31 @@ protected internal static int[] CompactRanges(IList ranges) { } return s; } + + /// Helper method for making an object indirect, if the object already is indirect. + /// + /// Helper method for making an object indirect, if the object already is indirect. + /// Useful for FontDescriptor and FontFile to make possible immediate flushing. + /// If there is no PdfDocument, mark the object as + /// MUST_BE_INDIRECT + /// . + /// + /// an object to make indirect. + /// + /// if current object isn't indirect, returns + /// + /// , otherwise + /// tree + /// + internal virtual bool MakeObjectIndirect(PdfObject obj) { + if (GetPdfObject().GetIndirectReference() != null) { + obj.MakeIndirect(GetPdfObject().GetIndirectReference().GetDocument()); + return true; + } + else { + MarkObjectAsIndirect(obj); + return false; + } + } } } diff --git a/itext/itext.kernel/itext/kernel/font/PdfFontFactory.cs b/itext/itext.kernel/itext/kernel/font/PdfFontFactory.cs index 2bdacc0148..510e05829d 100644 --- a/itext/itext.kernel/itext/kernel/font/PdfFontFactory.cs +++ b/itext/itext.kernel/itext/kernel/font/PdfFontFactory.cs @@ -48,6 +48,10 @@ source product. using iText.Kernel.Pdf; namespace iText.Kernel.Font { + /// + /// This class provides helpful methods for creating fonts ready to be used in a + /// + /// public sealed class PdfFontFactory { /// This is the default encoding to use. private static String DEFAULT_ENCODING = ""; @@ -55,14 +59,34 @@ public sealed class PdfFontFactory { /// This is the default value of the embedded variable. private static bool DEFAULT_EMBEDDING = false; - /// This is the default value of the embedded variable. - private static bool DEFAULT_CACHED = false; - - /// + /// This is the default value of the cached variable. + private static bool DEFAULT_CACHED = true; + + /// + /// Creates a default font, namely + /// + /// standard font with + /// + /// encoding. + /// + /// created font + /// if error occurred while creating the font, e.g. metrics loading failure + /// public static PdfFont CreateFont() { return CreateFont(FontConstants.HELVETICA, PdfEncodings.WINANSI); } + /// + /// Creates a + /// + /// by existing font dictionary. + /// + /// the font dictionary to create the font from + /// + /// created + /// + /// instance + /// public static PdfFont CreateFont(PdfDictionary fontDictionary) { if (CheckFontDictionary(fontDictionary, PdfName.Type1, false)) { return new PdfType1Font(fontDictionary); @@ -80,53 +104,191 @@ public static PdfFont CreateFont(PdfDictionary fontDictionary) { return new PdfType3Font(fontDictionary); } else { - throw new PdfException(PdfException.DictionaryNotContainFontData); + throw new PdfException(PdfException.DictionaryDoesntHaveSupportedFontData); } } } } } - /// - public static PdfFont CreateFont(String path) { - return CreateFont(path, DEFAULT_ENCODING); + /// + /// Creates a + /// + /// instance by the path of the font program file + /// + /// the path of the font program file + /// + /// created + /// + /// instance + /// + /// exception is thrown in case an I/O error occurs when reading the file + /// + public static PdfFont CreateFont(String fontProgram) { + return CreateFont(fontProgram, DEFAULT_ENCODING); } - /// - public static PdfFont CreateFont(String path, String encoding) { - return CreateFont(path, encoding, DEFAULT_EMBEDDING); + /// + /// Creates a + /// + /// instance by the path of the font program file and given encoding. + /// + /// the path of the font program file + /// + /// the font encoding. See + /// + /// + /// + /// created + /// + /// instance + /// + /// exception is thrown in case an I/O error occurs when reading the file + /// + public static PdfFont CreateFont(String fontProgram, String encoding) { + return CreateFont(fontProgram, encoding, DEFAULT_EMBEDDING); } - /// + /// + /// Creates a + /// + /// instance from the TrueTypeCollection represented by its byte contents. + /// + /// the byte contents of the TrueTypeCollection + /// the index of the font in the collection, zero-based + /// + /// the encoding of the font to be created. See + /// + /// + /// indicates whether the font is to be embedded into the target document + /// indicates whether the font will be cached + /// + /// created + /// + /// instance + /// + /// in case the contents of the TrueTypeCollection is mal-formed or an error occurred during reading the font + /// public static PdfFont CreateTtcFont(byte[] ttc, int ttcIndex, String encoding, bool embedded, bool cached) { FontProgram fontProgram = FontProgramFactory.CreateFont(ttc, ttcIndex, cached); return CreateFont(fontProgram, encoding, embedded); } - /// - public static PdfFont CreateTtcFont(String ttcPath, int ttcIndex, String encoding, bool embedded, bool cached - ) { - FontProgram fontProgram = FontProgramFactory.CreateFont(ttcPath, ttcIndex, cached); - return CreateFont(fontProgram, encoding, embedded); - } - - /// - public static PdfFont CreateFont(String path, bool embedded) { - return CreateFont(path, DEFAULT_ENCODING, embedded); - } - - /// - public static PdfFont CreateFont(String path, String encoding, bool embedded) { - return CreateFont(path, encoding, embedded, DEFAULT_CACHED); - } - - /// - public static PdfFont CreateFont(String path, String encoding, bool embedded, bool cached) { - FontProgram fontProgram = FontProgramFactory.CreateFont(path, cached); + /// + /// Creates a + /// + /// instance from the TrueTypeCollection given by the path to the .ttc file. + /// + /// the path of the .ttc file + /// the index of the font in the collection, zero-based + /// + /// the encoding of the font to be created. See + /// + /// + /// indicates whether the font is to be embedded into the target document + /// indicates whether the font will be cached + /// + /// created + /// + /// instance + /// + /// + /// in case the file is not found, contents of the TrueTypeCollection is mal-formed + /// or an error occurred during reading the font + /// + public static PdfFont CreateTtcFont(String ttc, int ttcIndex, String encoding, bool embedded, bool cached) { + FontProgram fontProgram = FontProgramFactory.CreateFont(ttc, ttcIndex, cached); return CreateFont(fontProgram, encoding, embedded); } - /// + /// + /// Created a + /// + /// instance given the path to the font file. + /// + /// the font program file + /// indicates whether the font is to be embedded into the target document + /// + /// created + /// + /// instance + /// + /// in case the file is not found or the contents of the font file is mal-formed + /// + public static PdfFont CreateFont(String fontProgram, bool embedded) { + return CreateFont(fontProgram, DEFAULT_ENCODING, embedded); + } + + /// + /// Created a + /// + /// instance given the path to the font file. + /// + /// the font program file + /// + /// the encoding of the font to be created. See + /// + /// + /// indicates whether the font is to be embedded into the target document + /// + /// created + /// + /// instance + /// + /// in case the file is not found or the contents of the font file is mal-formed + /// + public static PdfFont CreateFont(String fontProgram, String encoding, bool embedded) { + return CreateFont(fontProgram, encoding, embedded, DEFAULT_CACHED); + } + + /// + /// Created a + /// + /// instance given the path to the font file. + /// + /// the font program file + /// + /// the encoding of the font to be created. See + /// + /// + /// indicates whether the font is to be embedded into the target document + /// indicates whether the font will be cached + /// + /// created + /// + /// instance + /// + /// in case the file is not found or the contents of the font file is mal-formed + /// + public static PdfFont CreateFont(String fontProgram, String encoding, bool embedded, bool cached) { + FontProgram fp = FontProgramFactory.CreateFont(fontProgram, cached); + return CreateFont(fp, encoding, embedded); + } + + /// + /// Created a + /// + /// instance given the given underlying + /// + /// instance. + /// + /// + /// the font program of the + /// + /// instance to be created + /// + /// + /// the encoding of the font to be created. See + /// + /// + /// indicates whether the font is to be embedded into the target document + /// + /// created + /// + /// instance + /// + /// this exception is actually never thrown and will be removed in 7.1. + /// public static PdfFont CreateFont(FontProgram fontProgram, String encoding, bool embedded) { if (fontProgram == null) { return null; @@ -161,69 +323,257 @@ public static PdfFont CreateFont(FontProgram fontProgram, String encoding, bool } } - /// + /// + /// Created a + /// + /// instance given the given underlying + /// + /// instance. + /// + /// + /// the font program of the + /// + /// instance to be created + /// + /// + /// the encoding of the font to be created. See + /// + /// + /// + /// created + /// + /// instance + /// + /// this exception is actually never thrown and will be removed in 7.1. + /// public static PdfFont CreateFont(FontProgram fontProgram, String encoding) { return CreateFont(fontProgram, encoding, DEFAULT_EMBEDDING); } - /// + /// + /// Created a + /// + /// instance given the given underlying + /// + /// instance. + /// + /// + /// the font program of the + /// + /// instance to be created + /// + /// + /// created + /// + /// instance + /// + /// this exception is actually never thrown and will be removed in 7.1. + /// public static PdfFont CreateFont(FontProgram fontProgram) { return CreateFont(fontProgram, DEFAULT_ENCODING); } - /// - public static PdfFont CreateFont(byte[] font, String encoding) { - return CreateFont(font, encoding, DEFAULT_EMBEDDING); - } - - /// - public static PdfFont CreateFont(byte[] font, bool embedded) { - return CreateFont(font, null, embedded); - } - - /// - public static PdfFont CreateFont(byte[] font, String encoding, bool embedded) { - return CreateFont(font, encoding, embedded, DEFAULT_CACHED); - } - - /// - public static PdfFont CreateFont(byte[] font, String encoding, bool embedded, bool cached) { - FontProgram fontProgram = FontProgramFactory.CreateFont(null, font, cached); - return CreateFont(fontProgram, encoding, embedded); + /// + /// Created a + /// + /// instance by the bytes of the underlying font program. + /// + /// the bytes of the underlying font program + /// + /// created + /// + /// instance + /// + /// this exception is actually never thrown. Will be removed in 7.1. + public static PdfFont CreateFont(byte[] fontProgram, String encoding) { + return CreateFont(fontProgram, encoding, DEFAULT_EMBEDDING); } - /// + /// + /// Created a + /// + /// instance by the bytes of the underlying font program. + /// + /// the bytes of the underlying font program + /// indicates whether the font is to be embedded into the target document + /// + /// created + /// + /// instance + /// + /// this exception is actually never thrown. Will be removed in 7.1. + public static PdfFont CreateFont(byte[] fontProgram, bool embedded) { + return CreateFont(fontProgram, null, embedded); + } + + /// + /// Created a + /// + /// instance by the bytes of the underlying font program. + /// + /// the bytes of the underlying font program + /// + /// the encoding of the font to be created. See + /// + /// + /// indicates whether the font is to be embedded into the target document + /// + /// created + /// + /// instance + /// + /// this exception is actually never thrown. Will be removed in 7.1. + public static PdfFont CreateFont(byte[] fontProgram, String encoding, bool embedded) { + return CreateFont(fontProgram, encoding, embedded, DEFAULT_CACHED); + } + + /// + /// Created a + /// + /// instance by the bytes of the underlying font program. + /// + /// the bytes of the underlying font program + /// + /// the encoding of the font to be created. See + /// + /// + /// indicates whether the font is to be embedded into the target document + /// indicates whether the font will be cached + /// + /// created + /// + /// instance + /// + /// this exception is actually never thrown. Will be removed in 7.1. + public static PdfFont CreateFont(byte[] fontProgram, String encoding, bool embedded, bool cached) { + FontProgram fp = FontProgramFactory.CreateFont(null, fontProgram, cached); + return CreateFont(fp, encoding, embedded); + } + + /// + /// Creates a new instance of + /// + /// + /// the target document of the new font + /// indicates whether the font will be colorized + /// created font + /// actually this exception is never thrown. This will be removed in 7.1. + /// public static PdfType3Font CreateType3Font(PdfDocument document, bool colorized) { return new PdfType3Font(document, colorized); } + /// + /// Creates + /// + /// based on registered + /// + /// 's. + /// + /// + /// + /// + /// + /// + /// + /// /// - public static PdfFont CreateRegisteredFont(String font, String encoding, bool embedded, int style, bool cached - ) { - FontProgram fontProgram = FontProgramFactory.CreateRegisteredFont(font, style, cached); - return CreateFont(fontProgram, encoding, embedded); - } - + public static PdfFont CreateRegisteredFont(String fontName, String encoding, bool embedded, int style, bool + cached) { + FontProgram fp = FontProgramFactory.CreateRegisteredFont(fontName, style, cached); + return CreateFont(fp, encoding, embedded); + } + + /// + /// Creates + /// + /// based on registered + /// + /// 's. + /// + /// + /// + /// + /// + /// + /// + /// /// - public static PdfFont CreateRegisteredFont(String font, String encoding, bool embedded, bool cached) { - return CreateRegisteredFont(font, encoding, embedded, FontConstants.UNDEFINED, cached); - } - + public static PdfFont CreateRegisteredFont(String fontName, String encoding, bool embedded, bool cached) { + return CreateRegisteredFont(fontName, encoding, embedded, FontConstants.UNDEFINED, cached); + } + + /// + /// Creates + /// + /// based on registered + /// + /// 's. + /// + /// + /// + /// + /// + /// + /// + /// /// - public static PdfFont CreateRegisteredFont(String font, String encoding, bool embedded) { - return CreateRegisteredFont(font, encoding, embedded, FontConstants.UNDEFINED); - } - + public static PdfFont CreateRegisteredFont(String fontName, String encoding, bool embedded) { + return CreateRegisteredFont(fontName, encoding, embedded, FontConstants.UNDEFINED); + } + + /// + /// Creates + /// + /// based on registered + /// + /// 's. + /// + /// + /// + /// + /// + /// + /// + /// /// - public static PdfFont CreateRegisteredFont(String font, String encoding, bool embedded, int style) { - return CreateRegisteredFont(font, encoding, embedded, style, DEFAULT_CACHED); - } - + public static PdfFont CreateRegisteredFont(String fontName, String encoding, bool embedded, int style) { + return CreateRegisteredFont(fontName, encoding, embedded, style, DEFAULT_CACHED); + } + + /// + /// Creates + /// + /// based on registered + /// + /// 's. + /// + /// + /// + /// + /// + /// + /// + /// /// - public static PdfFont CreateRegisteredFont(String font, String encoding) { - return CreateRegisteredFont(font, encoding, false, FontConstants.UNDEFINED); - } - + public static PdfFont CreateRegisteredFont(String fontName, String encoding) { + return CreateRegisteredFont(fontName, encoding, false, FontConstants.UNDEFINED); + } + + /// + /// Creates + /// + /// based on registered + /// + /// 's. + /// + /// + /// + /// + /// + /// + /// + /// /// public static PdfFont CreateRegisteredFont(String fontName) { return CreateRegisteredFont(fontName, null, false, FontConstants.UNDEFINED); @@ -237,8 +587,13 @@ public static void RegisterFamily(String familyName, String fullName, String pat FontProgramFactory.RegisterFontFamily(familyName, fullName, path); } - /// Register a ttf- or a ttc-file. - /// the path to a ttf- or ttc-file + /// Registers a .ttf, .otf, .afm, .pfm, or a .ttc font file. + /// + /// Registers a .ttf, .otf, .afm, .pfm, or a .ttc font file. + /// In case if TrueTypeCollection (.ttc), an additional parameter may be specified defining the index of the font + /// to be registered, e.g. "path/to/font/collection.ttc,0". The index is zero-based. + /// + /// the path to a font file public static void Register(String path) { Register(path, null); } @@ -250,11 +605,11 @@ public static void Register(String path, String alias) { FontProgramFactory.RegisterFont(path, alias); } - /// Register all the fonts in a directory. - /// the directory + /// Registers all the fonts in a directory. + /// the directory path to be registered as a font directory path /// the number of fonts registered - public static int RegisterDirectory(String dir) { - return FontProgramFactory.RegisterFontDirectory(dir); + public static int RegisterDirectory(String dirPath) { + return FontProgramFactory.RegisterFontDirectory(dirPath); } /// Register fonts in some probable directories. @@ -273,25 +628,28 @@ public static ICollection GetRegisteredFonts() { return FontProgramFactory.GetRegisteredFonts(); } - /// Gets a set of registered font names. + /// Gets a set of registered font families. /// a set of registered font families public static ICollection GetRegisteredFamilies() { return FontProgramFactory.GetRegisteredFontFamilies(); } /// Checks if a certain font is registered. - /// the name of the font that has to be checked. - /// true if the font is found - public static bool IsRegistered(String fontname) { - return FontProgramFactory.IsRegisteredFont(fontname); + /// the name of the font that has to be checked. + /// true if the font is found, false otherwise + public static bool IsRegistered(String fontName) { + return FontProgramFactory.IsRegisteredFont(fontName); } + /// Checks if the provided dictionary is a valid font dictionary of the provided font type. + /// true if the passed dictionary is a valid dictionary, false otherwise + [System.ObsoleteAttribute(@"this method will become private in 7.1. Do not use this method")] protected internal static bool CheckFontDictionary(PdfDictionary fontDic, PdfName fontType, bool isException ) { if (fontDic == null || fontDic.Get(PdfName.Subtype) == null || !fontDic.Get(PdfName.Subtype).Equals(fontType )) { if (isException) { - throw new PdfException(PdfException.DictionaryNotContainFontData).SetMessageParams(fontType.GetValue()); + throw new PdfException(PdfException.DictionaryDoesntHave1FontData).SetMessageParams(fontType.GetValue()); } return false; } diff --git a/itext/itext.kernel/itext/kernel/font/PdfSimpleFont.cs b/itext/itext.kernel/itext/kernel/font/PdfSimpleFont.cs index 9cfe87d88e..ba2807e3b6 100644 --- a/itext/itext.kernel/itext/kernel/font/PdfSimpleFont.cs +++ b/itext/itext.kernel/itext/kernel/font/PdfSimpleFont.cs @@ -181,9 +181,11 @@ public override String Decode(PdfString content) { builder.Append((char)(int)uni); } else { - Glyph glyph = fontProgram.GetGlyphByCode(b & 0xff); - if (glyph != null && glyph.GetChars() != null) { - builder.Append(glyph.GetChars()); + if (fontEncoding.GetBaseEncoding() == null) { + Glyph glyph = fontProgram.GetGlyphByCode(b & 0xff); + if (glyph != null && glyph.GetChars() != null) { + builder.Append(glyph.GetChars()); + } } } } @@ -194,7 +196,16 @@ public override float GetContentWidth(PdfString content) { float width = 0; byte[] contentBytes = content.GetValueBytes(); foreach (byte b in contentBytes) { - Glyph glyph = fontProgram.GetGlyphByCode(b & 0xff); + Glyph glyph = null; + int uni = fontEncoding.GetUnicode(b & 0xff); + if (uni > -1) { + glyph = GetGlyph(uni); + } + else { + if (fontEncoding.GetBaseEncoding() == null) { + glyph = fontProgram.GetGlyphByCode(b & 0xff); + } + } width += glyph != null ? glyph.GetWidth() : 0; } return width; @@ -319,7 +330,9 @@ protected internal virtual void FlushFontData(String fontName, PdfName subtype) PdfDictionary fontDescriptor = !IsBuiltInFont() ? GetFontDescriptor(fontName) : null; if (fontDescriptor != null) { GetPdfObject().Put(PdfName.FontDescriptor, fontDescriptor); - fontDescriptor.Flush(); + if (fontDescriptor.GetIndirectReference() != null) { + fontDescriptor.Flush(); + } } } @@ -341,7 +354,7 @@ protected internal override PdfDictionary GetFontDescriptor(String fontName) { FontMetrics fontMetrics = fontProgram.GetFontMetrics(); FontNames fontNames = fontProgram.GetFontNames(); PdfDictionary fontDescriptor = new PdfDictionary(); - MarkObjectAsIndirect(fontDescriptor); + MakeObjectIndirect(fontDescriptor); fontDescriptor.Put(PdfName.Type, PdfName.FontDescriptor); fontDescriptor.Put(PdfName.FontName, new PdfName(fontName)); fontDescriptor.Put(PdfName.Ascent, new PdfNumber(fontMetrics.GetTypoAscender())); @@ -363,11 +376,15 @@ protected internal override PdfDictionary GetFontDescriptor(String fontName) { [0].Length >= 4) { fontDescriptor.Put(PdfName.FontFamily, new PdfString(fontNames.GetFamilyName()[0][3])); } + //add font stream and flush it immediately AddFontStream(fontDescriptor); int flags = fontProgram.GetPdfFontFlags(); - if (!fontEncoding.IsFontSpecific()) { - flags &= ~64; + if (fontProgram.IsFontSpecific() != fontEncoding.IsFontSpecific()) { + flags &= ~(4 | 32); + // reset both flags + flags |= fontEncoding.IsFontSpecific() ? 4 : 32; } + // set based on font encoding fontDescriptor.Put(PdfName.Flags, new PdfNumber(flags)); return fontDescriptor; } diff --git a/itext/itext.kernel/itext/kernel/font/PdfTrueTypeFont.cs b/itext/itext.kernel/itext/kernel/font/PdfTrueTypeFont.cs index a5192a3016..46134606bf 100644 --- a/itext/itext.kernel/itext/kernel/font/PdfTrueTypeFont.cs +++ b/itext/itext.kernel/itext/kernel/font/PdfTrueTypeFont.cs @@ -81,7 +81,7 @@ internal PdfTrueTypeFont(PdfDictionary fontDictionary) newFont = false; CheckFontDictionary(fontDictionary, PdfName.TrueType); CMapToUnicode toUni = FontUtil.ProcessToUnicode(fontDictionary.Get(PdfName.ToUnicode)); - fontEncoding = DocFontEncoding.CreateDocFontEncoding(fontDictionary.Get(PdfName.Encoding), toUni); + fontEncoding = DocFontEncoding.CreateDocFontEncoding(fontDictionary.Get(PdfName.Encoding), toUni, false); fontProgram = DocTrueTypeFont.CreateFontProgram(fontDictionary, fontEncoding); embedded = ((IDocFontProgram)fontProgram).GetFontFile() != null; subset = false; @@ -103,8 +103,8 @@ public override Glyph GetGlyph(int unicode) { return null; } - //TODO make subtype class member and simplify this method public override void Flush() { + //TODO make subtype class member and simplify this method if (newFont) { PdfName subtype; String fontName; @@ -204,6 +204,9 @@ protected internal override void AddFontStream(PdfDictionary fontDescriptor) { } if (fontStream != null) { fontDescriptor.Put(fontFileName, fontStream); + if (fontStream.GetIndirectReference() != null) { + fontStream.Flush(); + } } } } diff --git a/itext/itext.kernel/itext/kernel/font/PdfType0Font.cs b/itext/itext.kernel/itext/kernel/font/PdfType0Font.cs index 17ced64b27..222496cb9f 100644 --- a/itext/itext.kernel/itext/kernel/font/PdfType0Font.cs +++ b/itext/itext.kernel/itext/kernel/font/PdfType0Font.cs @@ -388,7 +388,7 @@ public override float GetContentWidth(PdfString content) { protected internal override PdfDictionary GetFontDescriptor(String fontName) { PdfDictionary fontDescriptor = new PdfDictionary(); - MarkObjectAsIndirect(fontDescriptor); + MakeObjectIndirect(fontDescriptor); fontDescriptor.Put(PdfName.Type, PdfName.FontDescriptor); fontDescriptor.Put(PdfName.FontName, new PdfName(fontName)); fontDescriptor.Put(PdfName.FontBBox, new PdfArray(GetFontProgram().GetFontMetrics().GetBbox())); @@ -436,8 +436,11 @@ private void FlushFontData() { PdfDictionary cidFont = GetCidFontType2(null, fontDescriptor, fontProgram.GetFontNames().GetFontName(), metrics ); GetPdfObject().Put(PdfName.DescendantFonts, new PdfArray(cidFont)); - fontDescriptor.Flush(); - cidFont.Flush(); + if (GetPdfObject().GetIndirectReference() != null) { + //this means, that fontDescriptor and cidFont already are indirects + fontDescriptor.Flush(); + cidFont.Flush(); + } } else { if (cidFontType == CID_FONT_TYPE_2) { @@ -495,10 +498,16 @@ private void FlushFontData() { PdfStream toUnicode = GetToUnicode(metrics); if (toUnicode != null) { GetPdfObject().Put(PdfName.ToUnicode, toUnicode); - toUnicode.Flush(); + if (toUnicode.GetIndirectReference() != null) { + toUnicode.Flush(); + } + } + if (GetPdfObject().GetIndirectReference() != null) { + //this means, that fontDescriptor, cidFont and fontStream already are indirects + fontDescriptor.Flush(); + cidFont.Flush(); + fontStream.Flush(); } - fontDescriptor.Flush(); - cidFont.Flush(); } else { throw new InvalidOperationException("Unsupported CID Font"); @@ -514,7 +523,7 @@ private void FlushFontData() { protected internal virtual PdfDictionary GetCidFontType2(TrueTypeFont ttf, PdfDictionary fontDescriptor, String fontName, int[][] metrics) { PdfDictionary cidFont = new PdfDictionary(); - MarkObjectAsIndirect(cidFont); + MakeObjectIndirect(cidFont); cidFont.Put(PdfName.Type, PdfName.Font); // sivan; cff cidFont.Put(PdfName.FontDescriptor, fontDescriptor); @@ -606,7 +615,9 @@ public virtual PdfStream GetToUnicode(Object[] metrics) { } } buf.Append("endbfrange\n" + "endcmap\n" + "CMapName currentdict /CMap defineresource pop\n" + "end end\n"); - return new PdfStream(PdfEncodings.ConvertToBytes(buf.ToString(), null)); + PdfStream toUnicode = new PdfStream(PdfEncodings.ConvertToBytes(buf.ToString(), null)); + MakeObjectIndirect(toUnicode); + return toUnicode; } //TODO optimize memory ussage diff --git a/itext/itext.kernel/itext/kernel/font/PdfType1Font.cs b/itext/itext.kernel/itext/kernel/font/PdfType1Font.cs index e3b7ddccbf..b697f18a42 100644 --- a/itext/itext.kernel/itext/kernel/font/PdfType1Font.cs +++ b/itext/itext.kernel/itext/kernel/font/PdfType1Font.cs @@ -74,7 +74,10 @@ internal PdfType1Font(PdfDictionary fontDictionary) newFont = false; CheckFontDictionary(fontDictionary, PdfName.Type1); CMapToUnicode toUni = FontUtil.ProcessToUnicode(fontDictionary.Get(PdfName.ToUnicode)); - fontEncoding = DocFontEncoding.CreateDocFontEncoding(fontDictionary.Get(PdfName.Encoding), toUni); + //if there is no FontDescriptor, it is most likely one of the Standard Font with StandardEncoding as base encoding. + bool fillStandardEncoding = !fontDictionary.ContainsKey(PdfName.FontDescriptor); + fontEncoding = DocFontEncoding.CreateDocFontEncoding(fontDictionary.Get(PdfName.Encoding), toUni, fillStandardEncoding + ); fontProgram = DocType1Font.CreateFontProgram(fontDictionary, fontEncoding, toUni); if (fontProgram is IDocFontProgram) { embedded = ((IDocFontProgram)fontProgram).GetFontFile() != null; @@ -134,6 +137,7 @@ protected internal override void AddFontStream(PdfDictionary fontDescriptor) { if (fontProgram is IDocFontProgram) { IDocFontProgram docType1Font = (IDocFontProgram)fontProgram; fontDescriptor.Put(docType1Font.GetFontFileName(), docType1Font.GetFontFile()); + docType1Font.GetFontFile().Flush(); if (docType1Font.GetSubtype() != null) { fontDescriptor.Put(PdfName.Subtype, docType1Font.GetSubtype()); } @@ -147,6 +151,9 @@ protected internal override void AddFontStream(PdfDictionary fontDescriptor) { fontStream.Put(new PdfName("Length" + (k + 1)), new PdfNumber(fontStreamLengths[k])); } fontDescriptor.Put(PdfName.FontFile, fontStream); + if (MakeObjectIndirect(fontStream)) { + fontStream.Flush(); + } } } } diff --git a/itext/itext.kernel/itext/kernel/font/PdfType3Font.cs b/itext/itext.kernel/itext/kernel/font/PdfType3Font.cs index 4e5299112d..0816ca1b74 100644 --- a/itext/itext.kernel/itext/kernel/font/PdfType3Font.cs +++ b/itext/itext.kernel/itext/kernel/font/PdfType3Font.cs @@ -99,14 +99,14 @@ internal PdfType3Font(PdfDictionary fontDictionary) } PdfNumber firstCharNumber = fontDictionary.GetAsNumber(PdfName.FirstChar); int firstChar = firstCharNumber != null ? Math.Max(firstCharNumber.IntValue(), 0) : 0; - int[] widths = FontUtil.ConvertSimpleWidthsArray(fontDictionary.GetAsArray(PdfName.Widths), firstChar); + int[] widths = FontUtil.ConvertSimpleWidthsArray(fontDictionary.GetAsArray(PdfName.Widths), firstChar, 0); double[] fontMatrix = new double[6]; for (int i = 0; i < fontMatrixArray.Size(); i++) { fontMatrix[i] = ((PdfNumber)fontMatrixArray.Get(i)).GetValue(); } SetFontMatrix(fontMatrix); foreach (PdfName glyphName in charProcsDic.KeySet()) { - int unicode = (int)AdobeGlyphList.NameToUnicode(glyphName.GetValue()); + int unicode = AdobeGlyphList.NameToUnicode(glyphName.GetValue()); if (unicode != -1 && fontEncoding.CanEncode(unicode)) { int code = fontEncoding.ConvertToByte(unicode); ((Type3FontProgram)GetFontProgram()).AddGlyph(code, unicode, widths[code], null, new Type3Glyph(charProcsDic @@ -216,6 +216,7 @@ public override void Flush() { if (fontEncoding.CanDecode(i)) { Type3Glyph glyph = GetType3Glyph(fontEncoding.GetUnicode(i)); charProcs.Put(new PdfName(fontEncoding.GetDifference(i)), glyph.GetContentStream()); + glyph.GetContentStream().Flush(); } } GetPdfObject().Put(PdfName.CharProcs, charProcs); diff --git a/itext/itext.kernel/itext/kernel/geom/AffineTransform.cs b/itext/itext.kernel/itext/kernel/geom/AffineTransform.cs index f44d86e58c..66f6e0b005 100644 --- a/itext/itext.kernel/itext/kernel/geom/AffineTransform.cs +++ b/itext/itext.kernel/itext/kernel/geom/AffineTransform.cs @@ -45,27 +45,87 @@ source product. namespace iText.Kernel.Geom { public class AffineTransform { + /// The type of affine transformation. + /// + /// The type of affine transformation. See + /// + /// . + /// public const int TYPE_IDENTITY = 0; + /// The type of affine transformation. + /// + /// The type of affine transformation. See + /// + /// . + /// public const int TYPE_TRANSLATION = 1; + /// The type of affine transformation. + /// + /// The type of affine transformation. See + /// + /// . + /// public const int TYPE_UNIFORM_SCALE = 2; + /// The type of affine transformation. + /// + /// The type of affine transformation. See + /// + /// . + /// public const int TYPE_GENERAL_SCALE = 4; + /// The type of affine transformation. + /// + /// The type of affine transformation. See + /// + /// . + /// public const int TYPE_QUADRANT_ROTATION = 8; + /// The type of affine transformation. + /// + /// The type of affine transformation. See + /// + /// . + /// public const int TYPE_GENERAL_ROTATION = 16; + /// The type of affine transformation. + /// + /// The type of affine transformation. See + /// + /// . + /// public const int TYPE_GENERAL_TRANSFORM = 32; + /// The type of affine transformation. + /// + /// The type of affine transformation. See + /// + /// . + /// public const int TYPE_FLIP = 64; + /// The type of affine transformation. + /// + /// The type of affine transformation. See + /// + /// . + /// public const int TYPE_MASK_SCALE = TYPE_UNIFORM_SCALE | TYPE_GENERAL_SCALE; + /// The type of affine transformation. + /// + /// The type of affine transformation. See + /// + /// . + /// public const int TYPE_MASK_ROTATION = TYPE_QUADRANT_ROTATION | TYPE_GENERAL_ROTATION; - /// The TYPE_UNKNOWN is an initial type value + /// The TYPE_UNKNOWN is an initial type value. internal const int TYPE_UNKNOWN = -1; /// The min value equivalent to zero. @@ -139,25 +199,42 @@ public AffineTransform(double[] matrix) { } } - /* - * Method returns type of affine transformation. - * - * Transform matrix is - * m00 m01 m02 - * m10 m11 m12 - * - * According analytic geometry new basis vectors are (m00, m01) and (m10, m11), - * translation vector is (m02, m12). Original basis vectors are (1, 0) and (0, 1). - * Type transformations classification: - * TYPE_IDENTITY - new basis equals original one and zero translation - * TYPE_TRANSLATION - translation vector isn't zero - * TYPE_UNIFORM_SCALE - vectors length of new basis equals - * TYPE_GENERAL_SCALE - vectors length of new basis doesn't equal - * TYPE_FLIP - new basis vector orientation differ from original one - * TYPE_QUADRANT_ROTATION - new basis is rotated by 90, 180, 270, or 360 degrees - * TYPE_GENERAL_ROTATION - new basis is rotated by arbitrary angle - * TYPE_GENERAL_TRANSFORM - transformation can't be inversed - */ + /// Method returns type of affine transformation. + /// + /// Method returns type of affine transformation. + /// Transform matrix is + /// m00 m01 m02 + /// m10 m11 m12 + /// According analytic geometry new basis vectors are (m00, m01) and (m10, m11), + /// translation vector is (m02, m12). Original basis vectors are (1, 0) and (0, 1). + /// Type transformations classification: + ///
    + ///
  • + /// + /// - new basis equals original one and zero translation
  • + ///
  • + /// + /// - translation vector isn't zero
  • + ///
  • + /// + /// - vectors length of new basis equals
  • + ///
  • + /// + /// - vectors length of new basis doesn't equal
  • + ///
  • + /// + /// - new basis vector orientation differ from original one
  • + ///
  • + /// + /// - new basis is rotated by 90, 180, 270, or 360 degrees
  • + ///
  • + /// + /// - new basis is rotated by arbitrary angle
  • + ///
  • + /// + /// - transformation can't be inversed
  • + ///
+ ///
public virtual int GetTransformType() { if (this.type != TYPE_UNKNOWN) { return this.type; diff --git a/itext/itext.kernel/itext/kernel/geom/LineSegment.cs b/itext/itext.kernel/itext/kernel/geom/LineSegment.cs index 1d319af607..f0ce2df7e1 100644 --- a/itext/itext.kernel/itext/kernel/geom/LineSegment.cs +++ b/itext/itext.kernel/itext/kernel/geom/LineSegment.cs @@ -84,7 +84,20 @@ public virtual float GetLength() { /// origin of the lower left hand end point of the segment, with width = 4 and height = 3. ///
/// the bounding rectangle + [System.ObsoleteAttribute(@"Use getBoundingRectangle(). Will be removed in 7.1")] public virtual Rectangle GetBoundingRectange() { + return GetBoundingRectangle(); + } + + /// Computes the bounding rectangle for this line segment. + /// + /// Computes the bounding rectangle for this line segment. The rectangle has a rotation 0 degrees + /// with respect to the coordinate system that the line system is in. For example, if a line segment + /// is 5 unit long and sits at a 37 degree angle from horizontal, the bounding rectangle will have + /// origin of the lower left hand end point of the segment, with width = 4 and height = 3. + /// + /// the bounding rectangle + public virtual Rectangle GetBoundingRectangle() { float x1 = GetStartPoint().Get(Vector.I1); float y1 = GetStartPoint().Get(Vector.I2); float x2 = GetEndPoint().Get(Vector.I1); diff --git a/itext/itext.kernel/itext/kernel/geom/NoninvertibleTransformException.cs b/itext/itext.kernel/itext/kernel/geom/NoninvertibleTransformException.cs index 84d2d4f5b4..9a00567bee 100644 --- a/itext/itext.kernel/itext/kernel/geom/NoninvertibleTransformException.cs +++ b/itext/itext.kernel/itext/kernel/geom/NoninvertibleTransformException.cs @@ -21,9 +21,13 @@ using System; namespace iText.Kernel.Geom { + /// NoninvertibleTransformException + /// Denis M. Kishenko public class NoninvertibleTransformException : Exception { - public NoninvertibleTransformException(String s) - : base(s) { + /// Creates a new NoninvertibleTransformException. + /// the detail message. + public NoninvertibleTransformException(String message) + : base(message) { } } } diff --git a/itext/itext.kernel/itext/kernel/geom/PageSize.cs b/itext/itext.kernel/itext/kernel/geom/PageSize.cs index cd1400a80b..7700d37094 100644 --- a/itext/itext.kernel/itext/kernel/geom/PageSize.cs +++ b/itext/itext.kernel/itext/kernel/geom/PageSize.cs @@ -61,6 +61,42 @@ public class PageSize : Rectangle { public static iText.Kernel.Geom.PageSize A8 = new iText.Kernel.Geom.PageSize(148, 210); + public static iText.Kernel.Geom.PageSize A9 = new iText.Kernel.Geom.PageSize(105, 547); + + public static iText.Kernel.Geom.PageSize A10 = new iText.Kernel.Geom.PageSize(74, 105); + + public static iText.Kernel.Geom.PageSize B0 = new iText.Kernel.Geom.PageSize(2834, 4008); + + public static iText.Kernel.Geom.PageSize B1 = new iText.Kernel.Geom.PageSize(2004, 2834); + + public static iText.Kernel.Geom.PageSize B2 = new iText.Kernel.Geom.PageSize(1417, 2004); + + public static iText.Kernel.Geom.PageSize B3 = new iText.Kernel.Geom.PageSize(1000, 1417); + + public static iText.Kernel.Geom.PageSize B4 = new iText.Kernel.Geom.PageSize(708, 1000); + + public static iText.Kernel.Geom.PageSize B5 = new iText.Kernel.Geom.PageSize(498, 708); + + public static iText.Kernel.Geom.PageSize B6 = new iText.Kernel.Geom.PageSize(354, 498); + + public static iText.Kernel.Geom.PageSize B7 = new iText.Kernel.Geom.PageSize(249, 354); + + public static iText.Kernel.Geom.PageSize B8 = new iText.Kernel.Geom.PageSize(175, 249); + + public static iText.Kernel.Geom.PageSize B9 = new iText.Kernel.Geom.PageSize(124, 175); + + public static iText.Kernel.Geom.PageSize B10 = new iText.Kernel.Geom.PageSize(88, 124); + + public static iText.Kernel.Geom.PageSize LETTER = new iText.Kernel.Geom.PageSize(612, 792); + + public static iText.Kernel.Geom.PageSize LEGAL = new iText.Kernel.Geom.PageSize(612, 1008); + + public static iText.Kernel.Geom.PageSize TABLOID = new iText.Kernel.Geom.PageSize(792, 1224); + + public static iText.Kernel.Geom.PageSize LEDGER = new iText.Kernel.Geom.PageSize(1224, 792); + + public static iText.Kernel.Geom.PageSize EXECUTIVE = new iText.Kernel.Geom.PageSize(522, 756); + public static iText.Kernel.Geom.PageSize Default = A4; public PageSize(float width, float height) diff --git a/itext/itext.kernel/itext/kernel/geom/Rectangle.cs b/itext/itext.kernel/itext/kernel/geom/Rectangle.cs index 839498302b..10a74a8d2e 100644 --- a/itext/itext.kernel/itext/kernel/geom/Rectangle.cs +++ b/itext/itext.kernel/itext/kernel/geom/Rectangle.cs @@ -100,6 +100,23 @@ public static iText.Kernel.Geom.Rectangle GetCommonRectangle(params iText.Kernel return new iText.Kernel.Geom.Rectangle(llx, lly, urx - llx, ury - lly); } + /// Sets the rectangle by the coordinates, specifying its lower left and upper right points. + /// + /// Sets the rectangle by the coordinates, specifying its lower left and upper right points. May be used in chain. + ///
+ ///
+ /// Note: this method will normalize coordinates, so the rectangle will have non negative width and height, + /// and its x and y coordinates specified lower left point. + ///
+ /// the X coordinate of lower left point + /// the Y coordinate of lower left point + /// the X coordinate of upper right point + /// the Y coordinate of upper right point + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Geom.Rectangle SetBbox(float llx, float lly, float urx, float ury) { // If llx is greater than urx, swap them (normalize) if (llx > urx) { @@ -120,84 +137,148 @@ public virtual iText.Kernel.Geom.Rectangle SetBbox(float llx, float lly, float u return this; } + /// Gets the X coordinate of lower left point. + /// the X coordinate of lower left point. public virtual float GetX() { return x; } + /// Sets the X coordinate of lower left point. + /// Sets the X coordinate of lower left point. May be used in chain. + /// the X coordinate of lower left point to be set. + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Geom.Rectangle SetX(float x) { this.x = x; return this; } + /// Gets the Y coordinate of lower left point. + /// the Y coordinate of lower left point. public virtual float GetY() { return y; } + /// Sets the Y coordinate of lower left point. + /// Sets the Y coordinate of lower left point. May be used in chain. + /// the Y coordinate of lower left point to be set. + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Geom.Rectangle SetY(float y) { this.y = y; return this; } + /// Gets the width of rectangle. + /// the width of rectangle. public virtual float GetWidth() { return width; } + /// Sets the width of rectangle. + /// Sets the width of rectangle. May be used in chain. + /// the the width of rectangle to be set. + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Geom.Rectangle SetWidth(float width) { this.width = width; return this; } + /// Gets the height of rectangle. + /// the height of rectangle. public virtual float GetHeight() { return height; } + /// Sets the height of rectangle. + /// Sets the height of rectangle. May be used in chain. + /// the the width of rectangle to be set. + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Geom.Rectangle SetHeight(float height) { this.height = height; return this; } + /// Increases the height of rectangle by the given value. + /// Increases the height of rectangle by the given value. May be used in chain. + /// the value of the extra height to be added. + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Geom.Rectangle IncreaseHeight(float extra) { this.height += extra; return this; } + /// Decreases the height of rectangle by the given value. + /// Decreases the height of rectangle by the given value. May be used in chain. + /// the value of the extra height to be subtracted. + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Geom.Rectangle DecreaseHeight(float extra) { this.height -= extra; return this; } - /// - /// Gets llx, the same: + /// Gets the X coordinate of the left edge of the rectangle. + /// + /// Gets the X coordinate of the left edge of the rectangle. Same as: /// getX() /// . - /// + ///
+ /// the X coordinate of the left edge of the rectangle. public virtual float GetLeft() { return x; } - /// - /// Gets urx, the same to + /// Gets the X coordinate of the right edge of the rectangle. + /// + /// Gets the X coordinate of the right edge of the rectangle. Same as: /// getX() + getWidth() /// . - /// + /// + /// the X coordinate of the right edge of the rectangle. public virtual float GetRight() { return x + width; } - /// - /// Gets ury, the same to + /// Gets the Y coordinate of the upper edge of the rectangle. + /// + /// Gets the Y coordinate of the upper edge of the rectangle. Same as: /// getY() + getHeight() /// . - /// + /// + /// the Y coordinate of the upper edge of the rectangle. public virtual float GetTop() { return y + height; } - /// - /// Gets lly, the same to + /// Gets the Y coordinate of the lower edge of the rectangle. + /// + /// Gets the Y coordinate of the lower edge of the rectangle. Same as: /// getY() /// . - /// + /// + /// the Y coordinate of the lower edge of the rectangle. public virtual float GetBottom() { return y; } @@ -246,6 +327,8 @@ public override String ToString() { return "Rectangle: " + GetWidth() + 'x' + GetHeight(); } + /// Gets the copy of this rectangle. + /// the copied rectangle. public virtual iText.Kernel.Geom.Rectangle Clone() { return new iText.Kernel.Geom.Rectangle(x, y, width, height); } diff --git a/itext/itext.kernel/itext/kernel/pdf/ByteBufferOutputStream.cs b/itext/itext.kernel/itext/kernel/pdf/ByteBufferOutputStream.cs index 19f44fed2b..e3319509e1 100644 --- a/itext/itext.kernel/itext/kernel/pdf/ByteBufferOutputStream.cs +++ b/itext/itext.kernel/itext/kernel/pdf/ByteBufferOutputStream.cs @@ -269,7 +269,7 @@ public virtual iText.Kernel.Pdf.ByteBufferOutputStream Append(String str) { if (str != null) { - return Append(str.GetBytes()); + return Append(str.GetBytes(EncodingUtil.ISO_8859_1)); } return this; } diff --git a/itext/itext.kernel/itext/kernel/pdf/CompressionConstants.cs b/itext/itext.kernel/itext/kernel/pdf/CompressionConstants.cs index 3125cb2092..a6386a1854 100644 --- a/itext/itext.kernel/itext/kernel/pdf/CompressionConstants.cs +++ b/itext/itext.kernel/itext/kernel/pdf/CompressionConstants.cs @@ -42,23 +42,24 @@ source product. address: sales@itextpdf.com */ -namespace iText.Kernel.Pdf -{ - public class CompressionConstants - { - /// A possible compression level. - public const int UNDEFINED_COMPRESSION = int.MinValue; +namespace iText.Kernel.Pdf { + /// + /// Compression constants for . + /// + public class CompressionConstants { + /// A possible compression level. + public const int UNDEFINED_COMPRESSION = int.MinValue; - /// A possible compression level. - public const int DEFAULT_COMPRESSION = -1; + /// A possible compression level. + public const int DEFAULT_COMPRESSION = -1; - /// A possible compression level. - public const int NO_COMPRESSION = 0; + /// A possible compression level. + public const int NO_COMPRESSION = 0; - /// A possible compression level. - public const int BEST_SPEED = 1; + /// A possible compression level. + public const int BEST_SPEED = 1; - /// A possible compression level. - public const int BEST_COMPRESSION = 9; - } + /// A possible compression level. + public const int BEST_COMPRESSION = 9; + } } diff --git a/itext/itext.kernel/itext/kernel/pdf/EncryptionConstants.cs b/itext/itext.kernel/itext/kernel/pdf/EncryptionConstants.cs index 0ed9019eea..826b245cf2 100644 --- a/itext/itext.kernel/itext/kernel/pdf/EncryptionConstants.cs +++ b/itext/itext.kernel/itext/kernel/pdf/EncryptionConstants.cs @@ -42,6 +42,11 @@ source product. address: sales@itextpdf.com */ namespace iText.Kernel.Pdf { + /// + /// Encryption constants for + /// + /// . + /// public class EncryptionConstants { /// Type of encryption. public const int STANDARD_ENCRYPTION_40 = 0; diff --git a/itext/itext.kernel/itext/kernel/pdf/IsoKey.cs b/itext/itext.kernel/itext/kernel/pdf/IsoKey.cs index 6277eacb80..61bc43e6fa 100644 --- a/itext/itext.kernel/itext/kernel/pdf/IsoKey.cs +++ b/itext/itext.kernel/itext/kernel/pdf/IsoKey.cs @@ -42,6 +42,7 @@ source product. address: sales@itextpdf.com */ namespace iText.Kernel.Pdf { + /// Type of object to conform. public enum IsoKey { CANVAS_STACK, DRAWMODE_FILL, @@ -51,6 +52,7 @@ public enum IsoKey { INLINE_IMAGE, PAGE, PDF_OBJECT, - RENDERING_INTENT + RENDERING_INTENT, + TAG_STRUCTURE_ELEMENT } } diff --git a/itext/itext.kernel/itext/kernel/pdf/PdfArray.cs b/itext/itext.kernel/itext/kernel/pdf/PdfArray.cs index f10942a315..964658b0e1 100644 --- a/itext/itext.kernel/itext/kernel/pdf/PdfArray.cs +++ b/itext/itext.kernel/itext/kernel/pdf/PdfArray.cs @@ -209,16 +209,35 @@ public virtual bool IsEmpty() public virtual bool Contains(PdfObject o) { - return list.Contains(o); - } + if (list.Contains(o)) + return true; + if (o == null) + return false; + foreach (PdfObject pdfObject in this) + if (PdfObject.EqualContent(o, pdfObject)) + return true; + return false; + } + /// + /// Returns an iterator over an array of PdfObject elements. + ///
+ /// NOTE: since 7.0.1 it returns collection of direct objects. + /// If you want to get {@link PdfIndirectReference} instances for the indirect objects value, + /// you shall use {@link #get(int, boolean)} method. + ///
+ /// an enumerator. public IEnumerator GetEnumerator() { - return list.GetEnumerator(); + return new PdfArrayDirectIterator(list.GetEnumerator()); } + /// + /// Returns an iterator over an array of PdfObject elements. + /// + [Obsolete("Use {@link #iterator()} instead")] public IEnumerator GetDirectEnumerator() { - return new PdfArrayDirectEnumerator(list.GetEnumerator()); + return new PdfArrayDirectIterator(list.GetEnumerator()); } public virtual void Add(PdfObject pdfObject) @@ -228,8 +247,20 @@ public virtual void Add(PdfObject pdfObject) public virtual void Remove(PdfObject o) { - list.Remove(o); - } + if (list.Remove(o)) + return; + if (o == null) + return; + PdfObject toDelete = null; + foreach (PdfObject pdfObject in list) + if (PdfObject.EqualContent(o, pdfObject)) + { + toDelete = pdfObject; + break; + } + if (toDelete != null) + list.Remove(toDelete); + } /// Adds the Collection of PdfObjects. /// the Collection of PdfObjects to be added @@ -283,8 +314,8 @@ public virtual PdfObject Set(int index, PdfObject element) return list[index] = element; } - /// Adds the specified PdfObject qt the specified index. - /// Adds the specified PdfObject qt the specified index. All objects after this index will be shifted by 1. + /// Adds the specified PdfObject at the specified index. + /// Adds the specified PdfObject at the specified index. All objects after this index will be shifted by 1. /// /// position to insert the PdfObject /// PdfObject to be added @@ -309,8 +340,17 @@ public virtual void Remove(int index) /// public virtual int IndexOf(PdfObject o) { - return list.IndexOf(o); - } + if (o == null) + return list.IndexOf(null); + int index = 0; + foreach (PdfObject pdfObject in this) + { + if (PdfObject.EqualContent(o, pdfObject)) + return index; + index++; + } + return -1; + } /// Returns a sublist of this PdfArray, starting at fromIndex (inclusive) and ending at toIndex (exclusive). /// @@ -394,7 +434,6 @@ IEnumerator IEnumerable.GetEnumerator() { } /// true is to extract direct object always. - /// public virtual PdfObject Get(int index, bool asDirect) { if (!asDirect) @@ -565,47 +604,5 @@ protected internal virtual void ReleaseContent() { list = null; } - - private class PdfArrayDirectEnumerator : IEnumerator - { - private IEnumerator parentEnumerator; - - public PdfArrayDirectEnumerator(IEnumerator parentEnumerator) - { - this.parentEnumerator = parentEnumerator; - } - - public void Dispose() - { - parentEnumerator.Dispose(); - } - - public bool MoveNext() - { - if (parentEnumerator.MoveNext()) - { - PdfObject obj = parentEnumerator.Current; - if (obj.IsIndirectReference()) - { - obj = ((PdfIndirectReference)obj).GetRefersTo(true); - } - Current = obj; - return true; - } - return false; - } - - public void Reset() - { - parentEnumerator.Reset(); - } - - public PdfObject Current { get; private set; } - - object IEnumerator.Current - { - get { return Current; } - } - } } } diff --git a/itext/itext.kernel/itext/kernel/pdf/PdfArrayDirectIterator.cs b/itext/itext.kernel/itext/kernel/pdf/PdfArrayDirectIterator.cs new file mode 100644 index 0000000000..1cf12161c5 --- /dev/null +++ b/itext/itext.kernel/itext/kernel/pdf/PdfArrayDirectIterator.cs @@ -0,0 +1,89 @@ +/* + +This file is part of the iText (R) project. +Copyright (c) 1998-2016 iText Group NV +Authors: Bruno Lowagie, Paulo Soares, et al. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License version 3 +as published by the Free Software Foundation with the addition of the +following permission added to Section 15 as permitted in Section 7(a): +FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY +ITEXT GROUP. ITEXT GROUP DISCLAIMS THE WARRANTY OF NON INFRINGEMENT +OF THIRD PARTY RIGHTS + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. +See the GNU Affero General Public License for more details. +You should have received a copy of the GNU Affero General Public License +along with this program; if not, see http://www.gnu.org/licenses or write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +Boston, MA, 02110-1301 USA, or download the license from the following URL: +http://itextpdf.com/terms-of-use/ + +The interactive user interfaces in modified source and object code versions +of this program must display Appropriate Legal Notices, as required under +Section 5 of the GNU Affero General Public License. + +In accordance with Section 7(b) of the GNU Affero General Public License, +a covered work must retain the producer line in every PDF that is created +or manipulated using iText. + +You can be released from the requirements of the license by purchasing +a commercial license. Buying such a license is mandatory as soon as you +develop commercial activities involving the iText software without +disclosing the source code of your own applications. +These activities include: offering paid services to customers as an ASP, +serving PDFs on the fly in a web application, shipping iText with a closed +source product. + +For more information, please contact iText Software Corp. at this +address: sales@itextpdf.com +*/ +using System.Collections; +using System.Collections.Generic; + +namespace iText.Kernel.Pdf { + internal class PdfArrayDirectIterator : IEnumerator + { + private IEnumerator parentEnumerator; + + internal PdfArrayDirectIterator(IEnumerator parentEnumerator) + { + this.parentEnumerator = parentEnumerator; + } + + public void Dispose() + { + parentEnumerator.Dispose(); + } + + public bool MoveNext() + { + if (parentEnumerator.MoveNext()) + { + PdfObject obj = parentEnumerator.Current; + if (obj.IsIndirectReference()) + { + obj = ((PdfIndirectReference)obj).GetRefersTo(true); + } + Current = obj; + return true; + } + return false; + } + + public void Reset() + { + parentEnumerator.Reset(); + } + + public PdfObject Current { get; private set; } + + object IEnumerator.Current + { + get { return Current; } + } + } +} diff --git a/itext/itext.kernel/itext/kernel/pdf/PdfBoolean.cs b/itext/itext.kernel/itext/kernel/pdf/PdfBoolean.cs index 2bb6c349cd..e02886c6a0 100644 --- a/itext/itext.kernel/itext/kernel/pdf/PdfBoolean.cs +++ b/itext/itext.kernel/itext/kernel/pdf/PdfBoolean.cs @@ -135,5 +135,14 @@ protected internal override void CopyContent(PdfObject from, PdfDocument documen iText.Kernel.Pdf.PdfBoolean @bool = (iText.Kernel.Pdf.PdfBoolean)from; value = @bool.value; } + + public override bool Equals(Object obj) { + return this == obj || obj != null && GetType() == obj.GetType() && value == ((iText.Kernel.Pdf.PdfBoolean) + obj).value; + } + + public override int GetHashCode() { + return (value ? 1 : 0); + } } } diff --git a/itext/itext.kernel/itext/kernel/pdf/PdfCatalog.cs b/itext/itext.kernel/itext/kernel/pdf/PdfCatalog.cs index 051328f372..6a18fd811f 100644 --- a/itext/itext.kernel/itext/kernel/pdf/PdfCatalog.cs +++ b/itext/itext.kernel/itext/kernel/pdf/PdfCatalog.cs @@ -43,6 +43,7 @@ source product. */ using System; using System.Collections.Generic; +using iText.IO.Log; using iText.Kernel; using iText.Kernel.Pdf.Action; using iText.Kernel.Pdf.Collection; @@ -73,7 +74,7 @@ protected internal PdfCatalog(PdfDictionary pdfObject) //This HashMap contents all pages of the document and outlines associated to them //This flag determines if Outline tree of the document has been built via calling getOutlines method. If this flag is false all outline operations will be ignored if (pdfObject == null) { - throw new PdfException(PdfException.DocumentHasNoCatalogObject); + throw new PdfException(PdfException.DocumentHasNoPdfCatalogObject); } EnsureObjectIsAddedToDocument(pdfObject); GetPdfObject().Put(PdfName.Type, PdfName.Catalog); @@ -134,7 +135,8 @@ public virtual PdfDocument GetDocument() { /// PdfCatalog will be flushed in PdfDocument.close(). /// PdfCatalog will be flushed in PdfDocument.close(). User mustn't flush PdfCatalog! public override void Flush() { - throw new PdfException(PdfException.YouCannotFlushPdfCatalogManually); + ILogger logger = LoggerFactory.GetLogger(typeof(PdfDocument)); + logger.Warn("PdfCatalog cannot be flushed manually"); } public virtual iText.Kernel.Pdf.PdfCatalog SetOpenAction(PdfDestination destination) { @@ -330,9 +332,8 @@ internal virtual IDictionary> GetPagesWithOutlines( /// Name of the destination. /// /// An object destination refers to. Must be an array or a dictionary with key /D and array. - /// See PdfSpec 12.3.2.3 for more info. + /// See ISO 32000-1 12.3.2.3 for more info. /// - /// internal virtual void AddNamedDestination(String key, PdfObject value) { AddNameToNameTree(key, value, PdfName.Dests); } @@ -349,11 +350,14 @@ internal virtual void AddNameToNameTree(String key, PdfObject value, PdfName tre /// This method returns a complete outline tree of the whole document. /// - /// - if this flag is true, the method read the whole document and creates outline tree. + /// if the flag is true, the method read the whole document and creates outline tree. /// If false the method gets cached outline tree (if it was cached via calling getOutlines method before). /// - /// - /// + /// + /// fully initialized + /// + /// object. + /// internal virtual PdfOutline GetOutlines(bool updateOutlines) { if (outlines != null && !updateOutlines) { return outlines; @@ -401,7 +405,6 @@ internal virtual bool IsOutlineMode() { /// This method removes all outlines associated with a given page /// - /// internal virtual void RemoveOutlines(PdfPage page) { if (GetDocument().GetWriter() == null) { return; @@ -409,8 +412,10 @@ internal virtual void RemoveOutlines(PdfPage page) { if (HasOutlines()) { GetOutlines(false); if (pagesWithOutlines.Count > 0) { - foreach (PdfOutline outline in pagesWithOutlines.Get(page.GetPdfObject())) { - outline.RemoveOutline(); + if (pagesWithOutlines.Get(page.GetPdfObject()) != null) { + foreach (PdfOutline outline in pagesWithOutlines.Get(page.GetPdfObject())) { + outline.RemoveOutline(); + } } } } @@ -418,7 +423,6 @@ internal virtual void RemoveOutlines(PdfPage page) { /// This method sets the root outline element in the catalog. /// - /// internal virtual void AddRootOutline(PdfOutline outline) { if (!outlineMode) { return; diff --git a/itext/itext.kernel/itext/kernel/pdf/PdfDictionary.cs b/itext/itext.kernel/itext/kernel/pdf/PdfDictionary.cs index d1f0533a8c..2eb131ab72 100644 --- a/itext/itext.kernel/itext/kernel/pdf/PdfDictionary.cs +++ b/itext/itext.kernel/itext/kernel/pdf/PdfDictionary.cs @@ -314,11 +314,48 @@ public virtual ICollection KeySet() { } /// Returns all the values of this map in a Collection. + /// + /// if false, collection will contain + /// + /// instances + /// for the indirect objects in dictionary, otherwise it will contain collection of direct objects. + /// + /// a Collection holding all the values + public virtual ICollection Values(bool asDirects) { + if (asDirects) { + return Values(); + } + else { + return map.Values; + } + } + + /// Returns all the values of this map in a Collection. + /// + /// Returns all the values of this map in a Collection. + ///
+ /// NOTE: since 7.0.1 it returns collection of direct objects. + /// If you want to get + /// + /// instances for the indirect objects value, + /// you shall use + /// + /// method. + ///
/// a Collection holding all the values public virtual ICollection Values() { - return map.Values; + return new PdfDictionaryValues(map.Values); } + /// Returns all the values of this map in a Collection. + /// + /// Returns all the values of this map in a Collection. In opposite to + /// + /// method, + /// this method will resolve all indirect references in the dictionary and return actual objects in collection. + /// + /// a Collection holding all the values + [System.ObsoleteAttribute(@"Use Values() instead.")] public virtual ICollection DirectValues() { ICollection directValues = new List(); foreach (PdfObject value in map.Values) { @@ -333,13 +370,33 @@ public virtual ICollection DirectValues() { } /// Returns a Set holding the key-value pairs as Map#Entry objects. + /// + /// Returns a Set holding the key-value pairs as Map#Entry objects. + ///
+ /// NOTE: since 7.0.1 it returns collection of direct objects. + /// If you want to get + /// + /// instances for the indirect objects value, + /// you shall use + /// + /// method. + ///
/// a Set of Map.Entry objects public virtual ICollection> EntrySet() { - return map; + return new PdfDictionaryEntrySet(map); } + /// Returns a Set holding the key-value pairs as Map#Entry objects. + /// + /// Returns a Set holding the key-value pairs as Map#Entry objects. In opposite to + /// + /// method, this method will resolve all indirect references in the dictionary and return actual objects as values of + /// entries in the collection. + /// + /// a Set of Map.Entry objects + [System.ObsoleteAttribute(@"Use EntrySet() instead.")] public virtual ICollection> DirectEntrySet() { - IDictionary directMap = new Dictionary(); + IDictionary directMap = new SortedDictionary(); foreach (KeyValuePair entry in map) { PdfObject value = entry.Value; if (value.IsIndirectReference()) { @@ -359,7 +416,7 @@ public override byte GetObjectType() { public override String ToString() { if (!IsFlushed()) { String @string = "<<"; - foreach (KeyValuePair entry in EntrySet()) { + foreach (KeyValuePair entry in map) { PdfIndirectReference indirectReference = entry.Value.GetIndirectReference(); @string = @string + entry.Key.ToString() + " " + (indirectReference == null ? entry.Value.ToString() : indirectReference .ToString()) + " "; @@ -379,7 +436,6 @@ public override String ToString() { ///
/// list of objects to exclude when cloning dictionary. /// cloned dictionary. - /// public virtual iText.Kernel.Pdf.PdfDictionary Clone(IList excludeKeys) { IDictionary excluded = new SortedDictionary(); foreach (PdfName key in excludeKeys) { @@ -446,7 +502,6 @@ public override PdfObject CopyTo(PdfDocument document, bool allowDuplicating) { /// /// /// copied dictionary. - /// public virtual iText.Kernel.Pdf.PdfDictionary CopyTo(PdfDocument document, IList excludeKeys, bool allowDuplicating) { IDictionary excluded = new SortedDictionary(); @@ -463,7 +518,6 @@ public virtual iText.Kernel.Pdf.PdfDictionary CopyTo(PdfDocument document, IList } /// true is to extract direct object always. - /// public virtual PdfObject Get(PdfName key, bool asDirect) { if (!asDirect) { return map.Get(key); @@ -496,7 +550,7 @@ protected internal override PdfObject NewInstance() { protected internal override void CopyContent(PdfObject from, PdfDocument document) { base.CopyContent(from, document); iText.Kernel.Pdf.PdfDictionary dictionary = (iText.Kernel.Pdf.PdfDictionary)from; - foreach (KeyValuePair entry in dictionary.EntrySet()) { + foreach (KeyValuePair entry in dictionary.map) { map[entry.Key] = entry.Value.ProcessCopying(document, false); } } diff --git a/itext/itext.kernel/itext/kernel/pdf/PdfDictionaryEntrySet.cs b/itext/itext.kernel/itext/kernel/pdf/PdfDictionaryEntrySet.cs new file mode 100644 index 0000000000..8149cf8637 --- /dev/null +++ b/itext/itext.kernel/itext/kernel/pdf/PdfDictionaryEntrySet.cs @@ -0,0 +1,178 @@ +/* + This file is part of the iText (R) project. + Copyright (c) 1998-2016 iText Group NV + Authors: Bruno Lowagie, Paulo Soares, et al. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License version 3 + as published by the Free Software Foundation with the addition of the + following permission added to Section 15 as permitted in Section 7(a): + FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY + ITEXT GROUP. ITEXT GROUP DISCLAIMS THE WARRANTY OF NON INFRINGEMENT + OF THIRD PARTY RIGHTS + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Affero General Public License for more details. + You should have received a copy of the GNU Affero General Public License + along with this program; if not, see http://www.gnu.org/licenses or write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA, 02110-1301 USA, or download the license from the following URL: + http://itextpdf.com/terms-of-use/ + + The interactive user interfaces in modified source and object code versions + of this program must display Appropriate Legal Notices, as required under + Section 5 of the GNU Affero General Public License. + + In accordance with Section 7(b) of the GNU Affero General Public License, + a covered work must retain the producer line in every PDF that is created + or manipulated using iText. + + You can be released from the requirements of the license by purchasing + a commercial license. Buying such a license is mandatory as soon as you + develop commercial activities involving the iText software without + disclosing the source code of your own applications. + These activities include: offering paid services to customers as an ASP, + serving PDFs on the fly in a web application, shipping iText with a closed + source product. + + For more information, please contact iText Software Corp. at this + address: sales@itextpdf.com + */ +using System; +using System.Collections; +using System.Collections.Generic; + +namespace iText.Kernel.Pdf { + internal class PdfDictionaryEntrySet : ICollection> + { + private readonly ICollection> collection; + + internal PdfDictionaryEntrySet(ICollection> collection) { + this.collection = collection; + } + + public IEnumerator> GetEnumerator() + { + return new DirectEnumerator(collection.GetEnumerator()); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + public void Add(KeyValuePair item) + { + collection.Add(item); + } + + public void Clear() + { + collection.Clear(); + } + + public bool Contains(KeyValuePair item) + { + if (collection.Contains(item)) + return true; + if (item.Value == null) + return false; + foreach (KeyValuePair entry in this) + if (item.Key.Equals(entry.Key) && item.Value.Equals(entry.Value)) + return true; + return false; + } + + public void CopyTo(KeyValuePair[] array, int arrayIndex) + { + int count = collection.Count; + if (count == 0) + return; + if (array == null) + throw new ArgumentNullException("array"); + if (arrayIndex < 0) + throw new ArgumentOutOfRangeException("arrayIndex", arrayIndex, "arrayIndex mut not be negtive"); + if (arrayIndex >= array.Length || count > array.Length - arrayIndex) + throw new ArgumentException("arrayIndex", "array too small"); + + int index = arrayIndex; + foreach (KeyValuePair item in this) + { + if (--count < 0) + break; + array[index++] = item; + } + } + + public bool Remove(KeyValuePair item) + { + if (collection.Remove(item)) + return true; + if (item.Value == null) + return false; + KeyValuePair toDelete = new KeyValuePair(null, null); + foreach (KeyValuePair entry in collection) + if (item.Key.Equals(entry.Key) && PdfObject.EqualContent(item.Value, entry.Value)) + { + toDelete = entry; + break; + } + + return toDelete.Key != null && collection.Remove(toDelete); + } + + public int Count + { + get { return collection.Count; } + } + + public bool IsReadOnly + { + get { return collection.IsReadOnly; } + } + + private class DirectEnumerator : IEnumerator> + { + private IEnumerator> parentEnumerator; + + public DirectEnumerator(IEnumerator> parentEnumerator) + { + this.parentEnumerator = parentEnumerator; + } + + public void Dispose() + { + parentEnumerator.Dispose(); + } + + public bool MoveNext() + { + if (parentEnumerator.MoveNext()) + { + KeyValuePair current = parentEnumerator.Current; + if (current.Value != null && current.Value.IsIndirectReference()) + { + current = new KeyValuePair(current.Key, ((PdfIndirectReference)current.Value).GetRefersTo(true)); + } + Current = current; + return true; + } + return false; + } + + public void Reset() + { + parentEnumerator.Reset(); + } + + public KeyValuePair Current { get; private set; } + + object IEnumerator.Current + { + get { return Current; } + } + } + } +} diff --git a/itext/itext.kernel/itext/kernel/pdf/PdfDictionaryValues.cs b/itext/itext.kernel/itext/kernel/pdf/PdfDictionaryValues.cs new file mode 100644 index 0000000000..8d73abb39c --- /dev/null +++ b/itext/itext.kernel/itext/kernel/pdf/PdfDictionaryValues.cs @@ -0,0 +1,173 @@ +/* + This file is part of the iText (R) project. + Copyright (c) 1998-2016 iText Group NV + Authors: Bruno Lowagie, Paulo Soares, et al. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License version 3 + as published by the Free Software Foundation with the addition of the + following permission added to Section 15 as permitted in Section 7(a): + FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY + ITEXT GROUP. ITEXT GROUP DISCLAIMS THE WARRANTY OF NON INFRINGEMENT + OF THIRD PARTY RIGHTS + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Affero General Public License for more details. + You should have received a copy of the GNU Affero General Public License + along with this program; if not, see http://www.gnu.org/licenses or write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA, 02110-1301 USA, or download the license from the following URL: + http://itextpdf.com/terms-of-use/ + + The interactive user interfaces in modified source and object code versions + of this program must display Appropriate Legal Notices, as required under + Section 5 of the GNU Affero General Public License. + + In accordance with Section 7(b) of the GNU Affero General Public License, + a covered work must retain the producer line in every PDF that is created + or manipulated using iText. + + You can be released from the requirements of the license by purchasing + a commercial license. Buying such a license is mandatory as soon as you + develop commercial activities involving the iText software without + disclosing the source code of your own applications. + These activities include: offering paid services to customers as an ASP, + serving PDFs on the fly in a web application, shipping iText with a closed + source product. + + For more information, please contact iText Software Corp. at this + address: sales@itextpdf.com + */ +using System; +using System.Collections; +using System.Collections.Generic; + +namespace iText.Kernel.Pdf { + + internal class PdfDictionaryValues : ICollection { + private readonly ICollection collection; + + internal PdfDictionaryValues(ICollection collection) { + this.collection = collection; + } + + public void Add(PdfObject item) + { + collection.Add(item); + } + + public void Clear() + { + collection.Clear(); + } + + public bool Contains(PdfObject item) + { + if (collection.Contains(item)) + return true; + if (item == null) + return false; + foreach (PdfObject pdfObject in this) + { + if (PdfObject.EqualContent(item, pdfObject)) + { + return true; + } + } + return false; + } + + public void CopyTo(PdfObject[] array, int arrayIndex) + { + int count = collection.Count; + if (count == 0) + return; + if (array == null) + throw new ArgumentNullException("array"); + if (arrayIndex < 0) + throw new ArgumentOutOfRangeException("arrayIndex", arrayIndex, "arrayIndex mut not be negtive"); + if (arrayIndex >= array.Length || count > array.Length - arrayIndex) + throw new ArgumentException("arrayIndex", "array too small"); + + int index = arrayIndex; + foreach (PdfObject item in this) + { + if (--count < 0) + break; + array[index++] = item; + } + } + + public bool Remove(PdfObject item) + { + //Actually we will get exception: + // System.NotSupportedException : Mutating a value collection derived from a dictionary is not allowed. + return collection.Remove(item); + } + + public int Count + { + get { return collection.Count; } + } + + public bool IsReadOnly + { + get { return collection.IsReadOnly; } + } + + + public IEnumerator GetEnumerator() + { + return new DirectEnumerator(collection.GetEnumerator()); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + private class DirectEnumerator : IEnumerator + { + private IEnumerator parentEnumerator; + + public DirectEnumerator(IEnumerator parentEnumerator) + { + this.parentEnumerator = parentEnumerator; + } + + public void Dispose() + { + parentEnumerator.Dispose(); + } + + public bool MoveNext() + { + if (parentEnumerator.MoveNext()) + { + PdfObject obj = parentEnumerator.Current; + if (obj != null && obj.IsIndirectReference()) + { + obj = ((PdfIndirectReference)obj).GetRefersTo(true); + } + Current = obj; + return true; + } + return false; + } + + public void Reset() + { + parentEnumerator.Reset(); + } + + public PdfObject Current { get; private set; } + + object IEnumerator.Current + { + get { return Current; } + } + } + } +} diff --git a/itext/itext.kernel/itext/kernel/pdf/PdfDocument.cs b/itext/itext.kernel/itext/kernel/pdf/PdfDocument.cs index 5f7dbaa3e5..4ca4acc3ee 100644 --- a/itext/itext.kernel/itext/kernel/pdf/PdfDocument.cs +++ b/itext/itext.kernel/itext/kernel/pdf/PdfDocument.cs @@ -64,6 +64,7 @@ source product. using iText.Kernel.XMP.Options; namespace iText.Kernel.Pdf { + /// Main enter point to work with PDF document. public class PdfDocument : IEventDispatcher, IDisposable { /// Currently active page. protected internal PdfPage currentPage = null; @@ -238,6 +239,7 @@ public virtual byte[] GetXmpMetadata(bool createNew) { XMPMeta xmpMeta = XMPMetaFactory.Create(); xmpMeta.SetObjectName(XMPConst.TAG_XMPMETA); xmpMeta.SetObjectName(""); + AddCustomMetadataExtensions(xmpMeta); try { xmpMeta.SetProperty(XMPConst.NS_DC, PdfConst.Format, "application/pdf"); xmpMeta.SetProperty(XMPConst.NS_PDF, PdfConst.Producer, Version.GetInstance().GetVersion()); @@ -249,6 +251,15 @@ public virtual byte[] GetXmpMetadata(bool createNew) { return xmpMetadata; } + /// Gets PdfObject by object number. + /// object number. + /// + /// + /// + /// or + /// + /// , if object not found. + /// public virtual PdfObject GetPdfObject(int objNum) { CheckClosingStatus(); PdfIndirectReference reference = xref.Get(objNum); @@ -260,6 +271,8 @@ public virtual PdfObject GetPdfObject(int objNum) { } } + /// Get number of indirect objects in the document. + /// number of indirect objects. public virtual int GetNumberOfPdfObjects() { return xref.Size(); } @@ -480,26 +493,32 @@ public virtual void SetDefaultPageSize(PageSize pageSize) { defaultPageSize = pageSize; } + /// public virtual void AddEventHandler(String type, IEventHandler handler) { eventDispatcher.AddEventHandler(type, handler); } + /// public virtual void DispatchEvent(Event @event) { eventDispatcher.DispatchEvent(@event); } + /// public virtual void DispatchEvent(Event @event, bool delayed) { eventDispatcher.DispatchEvent(@event, delayed); } + /// public virtual bool HasEventHandler(String type) { return eventDispatcher.HasEventHandler(type); } + /// public virtual void RemoveEventHandler(String type, IEventHandler handler) { eventDispatcher.RemoveEventHandler(type, handler); } + /// public virtual void RemoveAllHandlers() { eventDispatcher.RemoveAllHandlers(); } @@ -594,8 +613,7 @@ public virtual void Close() { PdfObject crypto_1 = null; if (properties.appendMode) { if (structTreeRoot != null && structTreeRoot.GetPdfObject().IsModified()) { - GetTagStructureContext().RemoveAllConnectionsToTags(); - structTreeRoot.Flush(); + TryFlushTagStructure(); } if (catalog.IsOCPropertiesMayHaveChanged() && catalog.GetOCProperties(false).GetPdfObject().IsModified()) { catalog.GetOCProperties(false).Flush(); @@ -627,8 +645,7 @@ public virtual void Close() { } else { if (structTreeRoot != null) { - GetTagStructureContext().RemoveAllConnectionsToTags(); - structTreeRoot.Flush(); + TryFlushTagStructure(); } if (catalog.IsOCPropertiesMayHaveChanged()) { catalog.GetPdfObject().Put(PdfName.OCProperties, catalog.GetOCProperties(false).GetPdfObject()); @@ -693,9 +710,6 @@ public virtual void Close() { trailer.Put(PdfName.Info, info.GetPdfObject()); xref.WriteXrefTableAndTrailer(this, fileId, crypto_1); writer.Flush(); - if (IsCloseWriter()) { - writer.Close(); - } Counter counter = GetCounter(); if (counter != null) { counter.OnDocumentWritten(writer.GetCurrentPos()); @@ -703,20 +717,41 @@ public virtual void Close() { } catalog.GetPageTree().ClearPageRefs(); RemoveAllHandlers(); - if (reader != null && IsCloseReader()) { - reader.Close(); - } } catch (System.IO.IOException e) { throw new PdfException(PdfException.CannotCloseDocument, e, this); } + finally { + if (writer != null && IsCloseWriter()) { + try { + writer.Close(); + } + catch (Exception e) { + ILogger logger = LoggerFactory.GetLogger(typeof(iText.Kernel.Pdf.PdfDocument)); + logger.Error(LogMessageConstant.PDF_WRITER_CLOSING_FAILED, e); + } + } + if (reader != null && IsCloseReader()) { + try { + reader.Close(); + } + catch (Exception e) { + ILogger logger = LoggerFactory.GetLogger(typeof(iText.Kernel.Pdf.PdfDocument)); + logger.Error(LogMessageConstant.PDF_READER_CLOSING_FAILED, e); + } + } + } closed = true; } + /// Gets close status of the document. + /// true, if the document has already been closed, otherwise false. public virtual bool IsClosed() { return closed; } + /// Gets tagged status of the document. + /// true, if the document has tag structure, otherwise false. public virtual bool IsTagged() { return structTreeRoot != null; } @@ -736,11 +771,27 @@ public virtual void SetTagged() { } } + /// + /// Gets + /// + /// of tagged document. + /// + /// + /// + /// + /// in case tagged document, otherwise false. + /// + /// + /// public virtual PdfStructTreeRoot GetStructTreeRoot() { return structTreeRoot; } - public virtual int? GetNextStructParentIndex() { + /// Gets next parent index of tagged document. + /// -1 if document is not tagged, or >= 0 if tagged. + /// + /// + public virtual int GetNextStructParentIndex() { return structParentIndex++; } @@ -778,7 +829,6 @@ public virtual TagStructureContext GetTagStructureContext() { /// a document to copy pages to. /// a position where to insert copied pages. /// list of copied pages - /// public virtual IList CopyPagesTo(int pageFrom, int pageTo, iText.Kernel.Pdf.PdfDocument toDocument , int insertBeforePage) { return CopyPagesTo(pageFrom, pageTo, toDocument, insertBeforePage, null); @@ -791,13 +841,12 @@ public virtual IList CopyPagesTo(int pageFrom, int pageTo, iText.Kernel /// Use this method if you want to copy pages across tagged documents. /// This will keep resultant PDF structure consistent. /// - /// start of the range of pages to be copied. - /// end of the range of pages to be copied. + /// 1-based start of the range of pages to be copied. + /// 1-based end of the range of pages to be copied. /// a document to copy pages to. /// a position where to insert copied pages. /// a copier which bears a special copy logic. May be NULL - /// list of copied pages - /// + /// list of new copied pages public virtual IList CopyPagesTo(int pageFrom, int pageTo, iText.Kernel.Pdf.PdfDocument toDocument , int insertBeforePage, IPdfPageExtraCopier copier) { IList pages = new List(); @@ -814,11 +863,10 @@ public virtual IList CopyPagesTo(int pageFrom, int pageTo, iText.Kernel /// Use this method if you want to copy pages across tagged documents. /// This will keep resultant PDF structure consistent. /// - /// - /// - /// - /// list of copied pages - /// + /// 1-based start of the range of pages to be copied. + /// 1-based end of the range of pages to be copied. + /// a document to copy pages to. + /// list of new copied pages public virtual IList CopyPagesTo(int pageFrom, int pageTo, iText.Kernel.Pdf.PdfDocument toDocument ) { return CopyPagesTo(pageFrom, pageTo, toDocument, null); @@ -831,12 +879,11 @@ public virtual IList CopyPagesTo(int pageFrom, int pageTo, iText.Kernel /// Use this method if you want to copy pages across tagged documents. /// This will keep resultant PDF structure consistent. /// - /// - /// - /// - /// a copier which bears a special copy logic. May be NULL - /// list of copied pages - /// + /// 1-based start of the range of pages to be copied. + /// 1-based end of the range of pages to be copied. + /// a document to copy pages to. + /// a copier which bears a special copy logic. May be null. + /// list of new copied pages. public virtual IList CopyPagesTo(int pageFrom, int pageTo, iText.Kernel.Pdf.PdfDocument toDocument , IPdfPageExtraCopier copier) { return CopyPagesTo(pageFrom, pageTo, toDocument, toDocument.GetNumberOfPages() + 1, copier); @@ -852,8 +899,7 @@ public virtual IList CopyPagesTo(int pageFrom, int pageTo, iText.Kernel /// list of pages to be copied. TreeSet for the order of the pages to be natural. /// a document to copy pages to. /// a position where to insert copied pages. - /// list of copied pages - /// + /// list of new copied pages public virtual IList CopyPagesTo(IList pagesToCopy, iText.Kernel.Pdf.PdfDocument toDocument, int insertBeforePage) { return CopyPagesTo(pagesToCopy, toDocument, insertBeforePage, null); @@ -870,8 +916,7 @@ public virtual IList CopyPagesTo(IList pagesToCopy, iText.Kernel.P /// a document to copy pages to. /// a position where to insert copied pages. /// a copier which bears a special copy logic. May be NULL - /// list of copied pages - /// + /// list of new copied pages public virtual IList CopyPagesTo(IList pagesToCopy, iText.Kernel.Pdf.PdfDocument toDocument, int insertBeforePage, IPdfPageExtraCopier copier) { if (pagesToCopy.IsEmpty()) { @@ -917,19 +962,30 @@ public virtual IList CopyPagesTo(IList pagesToCopy, iText.Kernel.P // It's important to copy tag structure after link annotations were copied, because object content items in tag // structure are not copied in case if their's OBJ key is annotation and doesn't contain /P entry. if (toDocument.IsTagged()) { - if (tagStructureContext != null) { - tagStructureContext.ActualizeTagsProperties(); - } - foreach (IDictionary increasingPagesRange in rangesOfPagesWithIncreasingNumbers) { - if (insertInBetween) { - GetStructTreeRoot().CopyTo(toDocument, insertBeforePage, increasingPagesRange); + if (IsTagged()) { + if (tagStructureContext != null) { + tagStructureContext.ActualizeTagsProperties(); } - else { - GetStructTreeRoot().CopyTo(toDocument, increasingPagesRange); + try { + foreach (IDictionary increasingPagesRange in rangesOfPagesWithIncreasingNumbers) { + if (insertInBetween) { + GetStructTreeRoot().CopyTo(toDocument, insertBeforePage, increasingPagesRange); + } + else { + GetStructTreeRoot().CopyTo(toDocument, increasingPagesRange); + } + insertBeforePage += increasingPagesRange.Count; + } + toDocument.GetTagStructureContext().NormalizeDocumentRootTag(); + } + catch (Exception ex) { + throw new PdfException(PdfException.TagStructureCopyingFailedItMightBeCorruptedInOneOfTheDocuments, ex); } - insertBeforePage += increasingPagesRange.Count; } - toDocument.GetTagStructureContext().NormalizeDocumentRootTag(); + else { + ILogger logger = LoggerFactory.GetLogger(typeof(iText.Kernel.Pdf.PdfDocument)); + logger.Warn(LogMessageConstant.NOT_TAGGED_PAGES_IN_TAGGED_DOCUMENT); + } } if (catalog.IsOutlineMode()) { CopyOutlines(outlinesToCopy, toDocument, page2page); @@ -947,7 +1003,6 @@ public virtual IList CopyPagesTo(IList pagesToCopy, iText.Kernel.P /// list of pages to be copied. TreeSet for the order of the pages to be natural. /// a document to copy pages to. /// list of copied pages - /// public virtual IList CopyPagesTo(IList pagesToCopy, iText.Kernel.Pdf.PdfDocument toDocument) { return CopyPagesTo(pagesToCopy, toDocument, null); } @@ -963,37 +1018,110 @@ public virtual IList CopyPagesTo(IList pagesToCopy, iText.Kernel.P /// a document to copy pages to. /// a copier which bears a special copy logic /// list of copied pages - /// public virtual IList CopyPagesTo(IList pagesToCopy, iText.Kernel.Pdf.PdfDocument toDocument, IPdfPageExtraCopier copier) { return CopyPagesTo(pagesToCopy, toDocument, toDocument.GetNumberOfPages() + 1, copier); } + /// + /// Checks, whether + /// + /// method will close associated PdfReader. + /// + /// + /// true, + /// + /// method is going to close associated PdfReader, otherwise false. + /// public virtual bool IsCloseReader() { return closeReader; } + /// + /// Sets, whether + /// + /// method shall close associated PdfReader. + /// + /// + /// true, + /// + /// method shall close associated PdfReader, otherwise false. + /// public virtual void SetCloseReader(bool closeReader) { + CheckClosingStatus(); this.closeReader = closeReader; } + /// + /// Checks, whether + /// + /// method will close associated PdfWriter. + /// + /// + /// true, + /// + /// method is going to close associated PdfWriter, otherwise false. + /// public virtual bool IsCloseWriter() { return closeWriter; } + /// + /// Sets, whether + /// + /// method shall close associated PdfWriter. + /// + /// + /// true, + /// + /// method shall close associated PdfWriter, otherwise false. + /// public virtual void SetCloseWriter(bool closeWriter) { + CheckClosingStatus(); this.closeWriter = closeWriter; } + /// + /// Checks, whether + /// + /// will flush unused objects, + /// e.g. unreachable from PDF Catalog. By default - false. + /// + /// + /// false, if + /// + /// shall not flush unused objects, otherwise true. + /// public virtual bool IsFlushUnusedObjects() { return flushUnusedObjects; } + /// + /// Sets, whether + /// + /// shall flush unused objects, + /// e.g. unreachable from PDF Catalog. + /// + /// + /// false, if + /// + /// shall not flush unused objects, otherwise true. + /// public virtual void SetFlushUnusedObjects(bool flushUnusedObjects) { CheckClosingStatus(); this.flushUnusedObjects = flushUnusedObjects; } + /// This method returns a complete outline tree of the whole document. + /// + /// if the flag is true, the method read the whole document and creates outline tree. + /// If false the method gets cached outline tree (if it was cached via calling getOutlines method before). + /// + /// + /// fully initialize + /// + /// object. + /// public virtual PdfOutline GetOutlines(bool updateOutlines) { CheckClosingStatus(); return catalog.GetOutlines(updateOutlines); @@ -1011,14 +1139,14 @@ public virtual void InitializeOutlines() { /// Name of the destination. /// /// An object destination refers to. Must be an array or a dictionary with key /D and array. - /// See PdfSpec 12.3.2.3 for more info. + /// See ISO 32000-1 12.3.2.3 for more info. /// - /// public virtual void AddNamedDestination(String key, PdfObject value) { CheckClosingStatus(); catalog.AddNamedDestination(key, value); } + /// Gets static copy of cross reference table. public virtual IList ListIndirectReferences() { CheckClosingStatus(); IList indRefs = new List(xref.Size()); @@ -1038,6 +1166,18 @@ public virtual PdfDictionary GetTrailer() { return trailer; } + /// + /// Adds + /// + /// that shall specify the colour characteristics of output devices + /// on which the document might be rendered. + /// + /// + /// + /// + /// to add. + /// + /// public virtual void AddOutputIntent(PdfOutputIntent outputIntent) { CheckClosingStatus(); if (outputIntent == null) { @@ -1051,21 +1191,100 @@ public virtual void AddOutputIntent(PdfOutputIntent outputIntent) { outputIntents.Add(outputIntent.GetPdfObject()); } + /// Checks whether PDF document conforms a specific standard. + /// + /// Checks whether PDF document conforms a specific standard. + /// Shall be override. + /// + /// An object to conform. + /// type of object to conform. public virtual void CheckIsoConformance(Object obj, IsoKey key) { } + /// Checks whether PDF document conforms a specific standard. + /// + /// Checks whether PDF document conforms a specific standard. + /// Shall be override. + /// + /// an object to conform. + /// type of object to conform. + /// + /// + /// + /// associated with an object to check. + /// public virtual void CheckIsoConformance(Object obj, IsoKey key, PdfResources resources) { } + /// Checks whether PDF document conforms a specific standard. + /// + /// Checks whether PDF document conforms a specific standard. + /// Shall be override. + /// + /// + /// a + /// + /// object to conform. + /// + /// + /// + /// + /// associated with an object to check. + /// public virtual void CheckShowTextIsoConformance(Object gState, PdfResources resources) { } + /// Adds file attachment at document level. + /// the file description + /// an array with the file. + /// the actual file name stored in the pdf + /// mime type of the file + /// the optional extra file parameters such as the creation or modification date + /// + /// if + /// + /// , + /// + /// will be added. Shall be one of: + /// + /// , + /// + /// , + /// + /// , + /// + /// or + /// + /// . + /// public virtual void AddFileAttachment(String description, byte[] fileStore, String fileDisplay, PdfName mimeType , PdfDictionary fileParameter, PdfName afRelationshipValue) { AddFileAttachment(description, PdfFileSpec.CreateEmbeddedFileSpec(this, fileStore, description, fileDisplay , mimeType, fileParameter, afRelationshipValue, true)); } + /// Adds file attachment at document level. + /// the file description + /// the path to the file. + /// the actual file name stored in the pdf + /// mime type of the file + /// + /// if + /// + /// , + /// + /// will be added. Shall be one of: + /// + /// , + /// + /// , + /// + /// , + /// + /// or + /// + /// . + /// /// public virtual void AddFileAttachment(String description, String file, String fileDisplay, PdfName mimeType , PdfName afRelationshipValue) { @@ -1073,6 +1292,13 @@ public virtual void AddFileAttachment(String description, String file, String fi , afRelationshipValue, true)); } + /// Adds file attachment at document level. + /// the file description + /// + /// + /// + /// object. + /// public virtual void AddFileAttachment(String description, PdfFileSpec fs) { CheckClosingStatus(); catalog.AddNameToNameTree(description, fs.GetPdfObject(), PdfName.EmbeddedFiles); @@ -1190,10 +1416,26 @@ internal virtual PdfXrefTable GetXref() { return xref; } + /// + /// Initialize + /// + /// . + /// protected internal virtual void InitTagStructureContext() { tagStructureContext = new TagStructureContext(this); } + /// Save the link annotation in a temporary storage for further copying. + /// + /// just copied + /// + /// link annotation belongs to. + /// + /// + /// + /// + /// itself. + /// protected internal virtual void StoreLinkAnnotation(PdfPage page, PdfLinkAnnotation annotation) { IList pageAnnotations = linkAnnotations.Get(page); if (pageAnnotations == null) { @@ -1203,16 +1445,30 @@ protected internal virtual void StoreLinkAnnotation(PdfPage page, PdfLinkAnnotat pageAnnotations.Add(annotation); } + /// Checks whether PDF document conforms a specific standard. + /// + /// Checks whether PDF document conforms a specific standard. + /// Shall be override. + /// protected internal virtual void CheckIsoConformance() { } + /// + /// Mark an object with + /// + /// . + /// + /// an object to mark. protected internal virtual void MarkObjectAsMustBeFlushed(PdfObject pdfObject) { if (pdfObject.IsIndirect()) { pdfObject.GetIndirectReference().SetState(PdfObject.MUST_BE_FLUSHED); } } - /// + /// Flush an object. + /// object to flush. + /// indicates whether object can be placed into object stream. + /// on error. protected internal virtual void FlushObject(PdfObject pdfObject, bool canBeInObjStm) { writer.FlushObject(pdfObject, canBeInObjStm); } @@ -1224,7 +1480,6 @@ protected internal virtual void FlushObject(PdfObject pdfObject, bool canBeInObj /// /// otherwise /// - /// protected internal virtual void Open(PdfVersion newPdfVersion) { try { if (reader != null) { @@ -1260,8 +1515,7 @@ protected internal virtual void Open(PdfVersion newPdfVersion) { ); PdfDictionary str = catalog.GetPdfObject().GetAsDictionary(PdfName.StructTreeRoot); if (str != null) { - structTreeRoot = new PdfStructTreeRoot(str); - structParentIndex = GetStructTreeRoot().GetParentTreeNextKey(); + TryInitTagStructure(str); } if (properties.appendMode && (reader.HasRebuiltXref() || reader.HasFixedXref())) { throw new PdfException(PdfException.AppendModeRequiresADocumentWithoutErrorsEvenIfRecoveryWasPossible); @@ -1358,6 +1612,21 @@ protected internal virtual void Open(PdfVersion newPdfVersion) { } } + /// Adds custom XMP metadata extension. + /// Adds custom XMP metadata extension. Useful for PDF/UA, ZUGFeRD, etc. + /// + /// + /// + /// to add custom metadata to. + /// + protected internal virtual void AddCustomMetadataExtensions(XMPMeta xmpMeta) { + } + + /// Updates XMP metadata. + /// + /// Updates XMP metadata. + /// Shall be override. + /// protected internal virtual void UpdateXmpMetadata() { try { if (writer.properties.addXmpMetadata) { @@ -1370,6 +1639,11 @@ protected internal virtual void UpdateXmpMetadata() { } } + /// + /// Update XMP metadata values from + /// + /// . + /// /// protected internal virtual XMPMeta UpdateDefaultXmpMetadata() { XMPMeta xmpMeta = XMPMetaFactory.ParseFromBuffer(GetXmpMetadata(true)); @@ -1456,7 +1730,8 @@ protected internal virtual ICollection GetDocumentFonts() { protected internal virtual void FlushFonts() { if (properties.appendMode) { foreach (PdfFont font in GetDocumentFonts()) { - if (font.GetPdfObject().GetIndirectReference().CheckState(PdfObject.MODIFIED)) { + if (font.GetPdfObject().CheckState(PdfObject.MUST_BE_INDIRECT) || font.GetPdfObject().GetIndirectReference + ().CheckState(PdfObject.MODIFIED)) { font.Flush(); } } @@ -1468,6 +1743,13 @@ protected internal virtual void FlushFonts() { } } + /// Checks page before adding and add. + /// one-base index of the page. + /// + /// + /// + /// to add. + /// protected internal virtual void CheckAndAddPage(int index, PdfPage page) { if (page.IsFlushed()) { throw new PdfException(PdfException.FlushedPageCannotBeAddedOrInserted, page); @@ -1479,6 +1761,12 @@ protected internal virtual void CheckAndAddPage(int index, PdfPage page) { catalog.GetPageTree().AddPage(index, page); } + /// Checks page before adding. + /// + /// + /// + /// to add. + /// protected internal virtual void CheckAndAddPage(PdfPage page) { if (page.IsFlushed()) { throw new PdfException(PdfException.FlushedPageCannotBeAddedOrInserted, page); @@ -1491,19 +1779,51 @@ protected internal virtual void CheckAndAddPage(PdfPage page) { } /// checks whether a method is invoked at the closed document - /// protected internal virtual void CheckClosingStatus() { if (closed) { - throw new PdfException(PdfException.DocumentClosedImpossibleExecuteAction); + throw new PdfException(PdfException.DocumentClosedItIsImpossibleToExecuteAction); } } + /// + /// Gets + /// + /// instance. + /// + /// + /// + /// + /// instance. + /// protected internal virtual Counter GetCounter() { return CounterFactory.GetCounter(typeof(iText.Kernel.Pdf.PdfDocument)); } + private void TryInitTagStructure(PdfDictionary str) { + try { + structTreeRoot = new PdfStructTreeRoot(str); + structParentIndex = GetStructTreeRoot().GetParentTreeNextKey(); + } + catch (Exception ex) { + structTreeRoot = null; + structParentIndex = -1; + ILogger logger = LoggerFactory.GetLogger(typeof(iText.Kernel.Pdf.PdfDocument)); + logger.Error(LogMessageConstant.TAG_STRUCTURE_INIT_FAILED, ex); + } + } + + private void TryFlushTagStructure() { + try { + GetTagStructureContext().RemoveAllConnectionsToTags(); + structTreeRoot.Flush(); + } + catch (Exception ex) { + throw new PdfException(PdfException.TagStructureFlushingFailedItMightBeCorrupted, ex); + } + } + /// This method removes all annotation entries from form fields associated with a given page. - /// + /// to remove from. private void RemoveUnusedWidgetsFromFields(PdfPage page) { if (page.IsFlushed()) { return; @@ -1522,7 +1842,7 @@ private void CopyLinkAnnotations(iText.Kernel.Pdf.PdfDocument toDocument, IDicti excludedKeys.Add(PdfName.Dest); excludedKeys.Add(PdfName.A); foreach (KeyValuePair> entry in linkAnnotations) { - // We don't want to copy those link annotations, which reference to not copied pages. + // We don't want to copy those link annotations, which reference to pages which weren't copied. foreach (PdfLinkAnnotation annot in entry.Value) { bool toCopyAnnot = true; PdfDestination copiedDest = null; @@ -1558,14 +1878,14 @@ private void CopyLinkAnnotations(iText.Kernel.Pdf.PdfDocument toDocument, IDicti } if (toCopyAnnot) { PdfLinkAnnotation newAnnot = (PdfLinkAnnotation)PdfAnnotation.MakeAnnotation(annot.GetPdfObject().CopyTo(toDocument - , excludedKeys, false)); + , excludedKeys, true)); if (copiedDest != null) { newAnnot.SetDestination(copiedDest); } if (copiedAction != null) { newAnnot.SetAction(copiedAction); } - page2page.Get(entry.Key).AddAnnotation(-1, newAnnot, false); + entry.Key.AddAnnotation(-1, newAnnot, false); } } } @@ -1575,7 +1895,6 @@ private void CopyLinkAnnotations(iText.Kernel.Pdf.PdfDocument toDocument, IDicti /// This method copies all given outlines /// outlines to be copied /// document where outlines should be copied - /// private void CopyOutlines(ICollection outlines, iText.Kernel.Pdf.PdfDocument toDocument, IDictionary page2page) { ICollection outlinesToCopy = new HashSet(); @@ -1609,7 +1928,6 @@ private void GetAllOutlinesToCopy(PdfOutline outline, ICollection ou /// - Set of outlines to be copied /// - new parent outline /// - old parent outline - /// private void CloneOutlines(ICollection outlinesToCopy, PdfOutline newParent, PdfOutline oldParent , IDictionary page2page, iText.Kernel.Pdf.PdfDocument toDocument) { if (null == oldParent) { diff --git a/itext/itext.kernel/itext/kernel/pdf/PdfEncryption.cs b/itext/itext.kernel/itext/kernel/pdf/PdfEncryption.cs index dd24ccd041..f15785fa9f 100644 --- a/itext/itext.kernel/itext/kernel/pdf/PdfEncryption.cs +++ b/itext/itext.kernel/itext/kernel/pdf/PdfEncryption.cs @@ -261,7 +261,7 @@ public static byte[] GenerateNewDocumentId() { long time = SystemUtil.GetSystemTimeTicks(); long mem = SystemUtil.GetFreeMemory(); String s = time + "+" + mem + "+" + (seq++); - return md5.Digest(s.GetBytes()); + return md5.Digest(s.GetBytes(iText.IO.Util.EncodingUtil.ISO_8859_1)); } public static PdfObject CreateInfoId(byte[] id, bool modified) { @@ -371,6 +371,21 @@ public virtual byte[] ComputeUserPassword(byte[] ownerPassword) { return userPassword; } + /// + /// To manually flush a + /// PdfObject + /// behind this wrapper, you have to ensure + /// that this object is added to the document, i.e. it has an indirect reference. + /// Basically this means that before flushing you need to explicitly call + /// + /// . + /// For example: wrapperInstance.makeIndirect(document).flush(); + /// Note that not every wrapper require this, only those that have such warning in documentation. + /// + public override void Flush() { + base.Flush(); + } + protected internal override bool IsWrappedObjectMustBeIndirect() { return true; } diff --git a/itext/itext.kernel/itext/kernel/pdf/PdfIndirectReference.cs b/itext/itext.kernel/itext/kernel/pdf/PdfIndirectReference.cs index 525b2539d8..7cf6ce4d2e 100644 --- a/itext/itext.kernel/itext/kernel/pdf/PdfIndirectReference.cs +++ b/itext/itext.kernel/itext/kernel/pdf/PdfIndirectReference.cs @@ -231,8 +231,8 @@ public override String ToString() { if (CheckState(READ_ONLY)) { states.Append("ReadOnly; "); } - return String.Format("{0} {1} R{2}", GetObjNumber(), GetGenNumber(), states.JSubstring(0, states.Length - - 1)); + return String.Format("{0} {1} R{2}", iText.IO.Util.JavaUtil.IntegerToString(GetObjNumber()), iText.IO.Util.JavaUtil.IntegerToString + (GetGenNumber()), states.JSubstring(0, states.Length - 1)); } /// Gets a PdfWriter associated with the document object belongs to. diff --git a/itext/itext.kernel/itext/kernel/pdf/PdfLiteral.cs b/itext/itext.kernel/itext/kernel/pdf/PdfLiteral.cs index 1648cb13db..e22c364889 100644 --- a/itext/itext.kernel/itext/kernel/pdf/PdfLiteral.cs +++ b/itext/itext.kernel/itext/kernel/pdf/PdfLiteral.cs @@ -94,6 +94,15 @@ public virtual int GetBytesCount() { protected internal override void GenerateContent() { } + public override bool Equals(Object o) { + return this == o || o != null && GetType() == o.GetType() && iText.IO.Util.JavaUtil.ArraysEquals(content, + ((iText.Kernel.Pdf.PdfLiteral)o).content); + } + + public override int GetHashCode() { + return content == null ? 0 : iText.IO.Util.JavaUtil.ArraysHashCode(content); + } + protected internal override PdfObject NewInstance() { return new iText.Kernel.Pdf.PdfLiteral(); } diff --git a/itext/itext.kernel/itext/kernel/pdf/PdfName.cs b/itext/itext.kernel/itext/kernel/pdf/PdfName.cs index b8cf87f09e..fa79341fdc 100644 --- a/itext/itext.kernel/itext/kernel/pdf/PdfName.cs +++ b/itext/itext.kernel/itext/kernel/pdf/PdfName.cs @@ -271,6 +271,8 @@ public class PdfName : PdfPrimitiveObject, IComparable public static readonly iText.Kernel.Pdf.PdfName Btn = CreateDirectName("Btn"); + public static readonly iText.Kernel.Pdf.PdfName Butt = CreateDirectName("Butt"); + public static readonly iText.Kernel.Pdf.PdfName ByteRange = CreateDirectName("ByteRange"); public static readonly iText.Kernel.Pdf.PdfName C = CreateDirectName("C"); @@ -456,6 +458,8 @@ public class PdfName : PdfPrimitiveObject, IComparable public static readonly iText.Kernel.Pdf.PdfName DeviceRGBK = CreateDirectName("DeviceRGBK"); + public static readonly iText.Kernel.Pdf.PdfName Diamond = CreateDirectName("Diamond"); + public static readonly iText.Kernel.Pdf.PdfName Difference = CreateDirectName("Difference"); public static readonly iText.Kernel.Pdf.PdfName Differences = CreateDirectName("Differences"); @@ -619,6 +623,20 @@ public class PdfName : PdfPrimitiveObject, IComparable public static readonly iText.Kernel.Pdf.PdfName FixedPrint = CreateDirectName("FixedPrint"); + /// PdfName for the abbreviation of FlateDecode. + /// + /// PdfName for the abbreviation of FlateDecode. For the Flatness Tolerance PdfName use + /// + /// (Uppercase 'L') + /// + public static readonly iText.Kernel.Pdf.PdfName Fl = CreateDirectName("Fl"); + + /// PdfName for Flatness Tolerance. + /// + /// PdfName for Flatness Tolerance. For the PdfName with the FlateDecode abbreviation use + /// + /// (Lowercase 'L') + /// public static readonly iText.Kernel.Pdf.PdfName FL = CreateDirectName("FL"); public static readonly iText.Kernel.Pdf.PdfName Flags = CreateDirectName("Flags"); @@ -865,6 +883,8 @@ public class PdfName : PdfPrimitiveObject, IComparable public static readonly iText.Kernel.Pdf.PdfName LJ = CreateDirectName("LJ"); + public static readonly iText.Kernel.Pdf.PdfName LL = CreateDirectName("LL"); + public static readonly iText.Kernel.Pdf.PdfName LLE = CreateDirectName("LLE"); public static readonly iText.Kernel.Pdf.PdfName LLO = CreateDirectName("LLO"); @@ -897,6 +917,8 @@ public class PdfName : PdfPrimitiveObject, IComparable public static readonly iText.Kernel.Pdf.PdfName Markup = CreateDirectName("Markup"); + public static readonly iText.Kernel.Pdf.PdfName Markup3D = CreateDirectName("Markup3D"); + public static readonly iText.Kernel.Pdf.PdfName MarkStyle = CreateDirectName("MarkStyle"); public static readonly iText.Kernel.Pdf.PdfName Mask = CreateDirectName("Mask"); @@ -1098,10 +1120,14 @@ public class PdfName : PdfPrimitiveObject, IComparable public static readonly iText.Kernel.Pdf.PdfName PatternType = CreateDirectName("PatternType"); + public static readonly iText.Kernel.Pdf.PdfName Pause = CreateDirectName("Pause"); + public static readonly iText.Kernel.Pdf.PdfName Perceptual = CreateDirectName("Perceptual"); public static readonly iText.Kernel.Pdf.PdfName Perms = CreateDirectName("Perms"); + public static readonly iText.Kernel.Pdf.PdfName PC = CreateDirectName("PC"); + public static readonly iText.Kernel.Pdf.PdfName PCM = CreateDirectName("PCM"); public static readonly iText.Kernel.Pdf.PdfName Pdf_Version_1_2 = CreateDirectName("1.2"); @@ -1118,10 +1144,16 @@ public class PdfName : PdfPrimitiveObject, IComparable public static readonly iText.Kernel.Pdf.PdfName Pg = CreateDirectName("Pg"); + public static readonly iText.Kernel.Pdf.PdfName PI = CreateDirectName("PI"); + public static readonly iText.Kernel.Pdf.PdfName PickTrayByPDFSize = CreateDirectName("PickTrayByPDFSize"); public static readonly iText.Kernel.Pdf.PdfName Placement = CreateDirectName("Placement"); + public static readonly iText.Kernel.Pdf.PdfName Play = CreateDirectName("Play"); + + public static readonly iText.Kernel.Pdf.PdfName PO = CreateDirectName("PO"); + public static readonly iText.Kernel.Pdf.PdfName Polygon = CreateDirectName("Polygon"); public static readonly iText.Kernel.Pdf.PdfName PolyLine = CreateDirectName("PolyLine"); @@ -1168,6 +1200,8 @@ public class PdfName : PdfPrimitiveObject, IComparable public static readonly iText.Kernel.Pdf.PdfName Pushpin = CreateDirectName("PushPin"); + public static readonly iText.Kernel.Pdf.PdfName PV = CreateDirectName("PV"); + public static readonly iText.Kernel.Pdf.PdfName Q = CreateDirectName("Q"); public static readonly iText.Kernel.Pdf.PdfName Quote = CreateDirectName("Quote"); @@ -1190,6 +1224,8 @@ public class PdfName : PdfPrimitiveObject, IComparable public static readonly iText.Kernel.Pdf.PdfName RC = CreateDirectName("RC"); + public static readonly iText.Kernel.Pdf.PdfName RClosedArrow = CreateDirectName("RClosedArrow"); + public static readonly iText.Kernel.Pdf.PdfName RD = CreateDirectName("RD"); public static readonly iText.Kernel.Pdf.PdfName Reason = CreateDirectName("Reason"); @@ -1215,6 +1251,8 @@ public class PdfName : PdfPrimitiveObject, IComparable public static readonly iText.Kernel.Pdf.PdfName ResetForm = CreateDirectName("ResetForm"); + public static readonly iText.Kernel.Pdf.PdfName Resume = CreateDirectName("Resume"); + public static readonly iText.Kernel.Pdf.PdfName Requirements = CreateDirectName("Requirements"); public static readonly iText.Kernel.Pdf.PdfName Resources = CreateDirectName("Resources"); @@ -1231,6 +1269,8 @@ public class PdfName : PdfPrimitiveObject, IComparable public static readonly iText.Kernel.Pdf.PdfName RoleMap = CreateDirectName("RoleMap"); + public static readonly iText.Kernel.Pdf.PdfName ROpenArrow = CreateDirectName("ROpenArrow"); + public static readonly iText.Kernel.Pdf.PdfName Root = CreateDirectName("Root"); public static readonly iText.Kernel.Pdf.PdfName Rotate = CreateDirectName("Rotate"); @@ -1296,6 +1336,8 @@ public class PdfName : PdfPrimitiveObject, IComparable public static readonly iText.Kernel.Pdf.PdfName Size = CreateDirectName("Size"); + public static readonly iText.Kernel.Pdf.PdfName Slash = CreateDirectName("Slash"); + public static readonly iText.Kernel.Pdf.PdfName SM = CreateDirectName("SM"); public static readonly iText.Kernel.Pdf.PdfName SMask = CreateDirectName("SMask"); @@ -1344,6 +1386,8 @@ public class PdfName : PdfPrimitiveObject, IComparable public static readonly iText.Kernel.Pdf.PdfName StemH = CreateDirectName("StemH"); + public static readonly iText.Kernel.Pdf.PdfName Stop = CreateDirectName("Stop"); + public static readonly iText.Kernel.Pdf.PdfName Stm = CreateDirectName("Stm"); public static readonly iText.Kernel.Pdf.PdfName StmF = CreateDirectName("StmF"); @@ -1439,6 +1483,10 @@ public class PdfName : PdfPrimitiveObject, IComparable public static readonly iText.Kernel.Pdf.PdfName TOCI = CreateDirectName("TOCI"); + public static readonly iText.Kernel.Pdf.PdfName Toggle = CreateDirectName("Toggle"); + + public static readonly iText.Kernel.Pdf.PdfName Top = CreateDirectName("Top"); + public static readonly iText.Kernel.Pdf.PdfName TopSecret = CreateDirectName("TopSecret"); public static readonly iText.Kernel.Pdf.PdfName ToUnicode = CreateDirectName("ToUnicode"); @@ -1561,6 +1609,8 @@ public class PdfName : PdfPrimitiveObject, IComparable public static readonly iText.Kernel.Pdf.PdfName Watermark = CreateDirectName("Watermark"); + public static readonly iText.Kernel.Pdf.PdfName WC = CreateDirectName("WC"); + public static readonly iText.Kernel.Pdf.PdfName WhitePoint = CreateDirectName("WhitePoint"); public static readonly iText.Kernel.Pdf.PdfName Width = CreateDirectName("Width"); @@ -1577,6 +1627,8 @@ public class PdfName : PdfPrimitiveObject, IComparable public static readonly iText.Kernel.Pdf.PdfName WP = CreateDirectName("WP"); + public static readonly iText.Kernel.Pdf.PdfName WS = CreateDirectName("WS"); + public static readonly iText.Kernel.Pdf.PdfName WT = CreateDirectName("WT"); public static readonly iText.Kernel.Pdf.PdfName X = CreateDirectName("X"); diff --git a/itext/itext.kernel/itext/kernel/pdf/PdfNull.cs b/itext/itext.kernel/itext/kernel/pdf/PdfNull.cs index 859fd89f2e..b4a6d3c9ec 100644 --- a/itext/itext.kernel/itext/kernel/pdf/PdfNull.cs +++ b/itext/itext.kernel/itext/kernel/pdf/PdfNull.cs @@ -120,5 +120,13 @@ protected internal override PdfObject NewInstance() { protected internal override void CopyContent(PdfObject from, PdfDocument document) { } + + public override bool Equals(Object obj) { + return this == obj || obj != null && GetType() == obj.GetType(); + } + + public override int GetHashCode() { + return 0; + } } } diff --git a/itext/itext.kernel/itext/kernel/pdf/PdfNumber.cs b/itext/itext.kernel/itext/kernel/pdf/PdfNumber.cs index 9829ad17bc..b04d6b91fc 100644 --- a/itext/itext.kernel/itext/kernel/pdf/PdfNumber.cs +++ b/itext/itext.kernel/itext/kernel/pdf/PdfNumber.cs @@ -42,6 +42,8 @@ source product. address: sales@itextpdf.com */ using System; +using iText.IO; +using iText.IO.Log; using iText.IO.Source; namespace iText.Kernel.Pdf { @@ -50,6 +52,8 @@ public class PdfNumber : PdfPrimitiveObject { private bool isDouble; + private bool changed = false; + public PdfNumber(double value) : base() { SetValue(value); @@ -101,6 +105,7 @@ public virtual void SetValue(int value) { this.value = value; this.isDouble = false; this.content = null; + this.changed = true; } public virtual void SetValue(double value) { @@ -172,6 +177,22 @@ public override String ToString() { } } + public override bool Equals(Object o) { + return this == o || o != null && GetType() == o.GetType() && iText.IO.Util.JavaUtil.DoubleCompare(((iText.Kernel.Pdf.PdfNumber + )o).value, value) == 0; + } + + public override int GetHashCode() { + if (changed) { + //if the instance was modified, hashCode also will be changed, it may cause inconsistency. + ILogger logger = LoggerFactory.GetLogger(typeof(PdfReader)); + logger.Warn(LogMessageConstant.CALCULATE_HASHCODE_FOR_MODIFIED_PDFNUMBER); + changed = false; + } + long hash = iText.IO.Util.JavaUtil.DoubleToLongBits(value); + return (int)(hash ^ ((long)(((ulong)hash) >> 32))); + } + protected internal override PdfObject NewInstance() { return new iText.Kernel.Pdf.PdfNumber(); } diff --git a/itext/itext.kernel/itext/kernel/pdf/PdfObject.cs b/itext/itext.kernel/itext/kernel/pdf/PdfObject.cs index 011b32f380..235ac28d12 100644 --- a/itext/itext.kernel/itext/kernel/pdf/PdfObject.cs +++ b/itext/itext.kernel/itext/kernel/pdf/PdfObject.cs @@ -117,21 +117,24 @@ public abstract class PdfObject { public abstract byte GetObjectType(); /// Flushes the object to the document. - /// public void Flush() { Flush(true); } /// Flushes the object to the document. /// indicates whether object can be placed into object stream. - /// public void Flush(bool canBeInObjStm) { if (IsFlushed() || GetIndirectReference() == null) { + // TODO here we should take into account and log the case when object is MustBeIndirect, but has no indirect reference + // TODO DEVSIX-744 // Logger logger = LoggerFactory.getLogger(PdfObject.class); // if (isFlushed()) { // logger.warn("Meaningless call, the object has already flushed"); + // } else if (isIndirect()){ + // logger.warn("Meaningless call, the object will be transformed into indirect on closing, but at the moment it doesn't have an indirect reference and therefore couldn't be flushed. " + + // "To flush it now call makeIndirect(PdfDocument) method before calling flush() method."); // } else { - // logger.warn("Meaningless call, the object is direct object."); + // logger.warn("Meaningless call, the object is direct object. It will be flushed along with the indirect object that contains it."); // } return; } @@ -268,9 +271,10 @@ public virtual PdfObject CopyTo(PdfDocument document) { /// copied object. public virtual PdfObject CopyTo(PdfDocument document, bool allowDuplicating) { if (document == null) { - throw new PdfException(PdfException.DocumentToCopyToCannotBeNull); + throw new PdfException(PdfException.DocumentForCopyToCannotBeNull); } if (indirectReference != null) { + // TODO checkState(MUST_BE_INDIRECT) now is always false, because indirectReference != null. See also DEVSIX-602 if (indirectReference.GetWriter() != null || CheckState(MUST_BE_INDIRECT)) { throw new PdfException(PdfException.CannotCopyIndirectObjectFromTheDocumentThatIsBeingWritten); } @@ -448,6 +452,7 @@ protected internal virtual void CopyContent(PdfObject from, PdfDocument document ///
  • copying to the other document
  • ///
  • cloning inside of the current document
  • /// + ///

    /// This two cases are distinguished by the state of document parameter: /// the second case is processed if document is null. /// @@ -481,5 +486,13 @@ internal virtual PdfObject ProcessCopying(PdfDocument documentTo, bool allowDupl return obj.Clone(); } } + + internal static bool EqualContent(PdfObject obj1, PdfObject obj2) { + PdfObject direct1 = obj1 != null && obj1.IsIndirectReference() ? ((PdfIndirectReference)obj1).GetRefersTo( + true) : obj1; + PdfObject direct2 = obj2 != null && obj2.IsIndirectReference() ? ((PdfIndirectReference)obj2).GetRefersTo( + true) : obj2; + return direct1 != null && direct1.Equals(direct2); + } } } diff --git a/itext/itext.kernel/itext/kernel/pdf/PdfObjectStream.cs b/itext/itext.kernel/itext/kernel/pdf/PdfObjectStream.cs index 5512f37cf9..d3610f1444 100644 --- a/itext/itext.kernel/itext/kernel/pdf/PdfObjectStream.cs +++ b/itext/itext.kernel/itext/kernel/pdf/PdfObjectStream.cs @@ -57,7 +57,8 @@ internal class PdfObjectStream : PdfStream { public PdfObjectStream(PdfDocument doc) : base() { - MakeIndirect(doc); + //avoid reuse existed references + MakeIndirect(doc, doc.GetXref().CreateNewIndirectReference(doc)); GetOutputStream().document = doc; Put(PdfName.Type, PdfName.ObjStm); Put(PdfName.N, size); @@ -82,7 +83,6 @@ internal PdfObjectStream(iText.Kernel.Pdf.PdfObjectStream prev) ///

    Adds object to the object stream. /// object to add. - /// public virtual void AddObject(PdfObject @object) { if (size.IntValue() == MAX_OBJ_STREAM_SIZE) { throw new PdfException(PdfException.PdfObjectStreamReachMaxSize); diff --git a/itext/itext.kernel/itext/kernel/pdf/PdfOutline.cs b/itext/itext.kernel/itext/kernel/pdf/PdfOutline.cs index 7f53d13ec3..1b2ed57012 100644 --- a/itext/itext.kernel/itext/kernel/pdf/PdfOutline.cs +++ b/itext/itext.kernel/itext/kernel/pdf/PdfOutline.cs @@ -49,9 +49,15 @@ source product. using iText.Kernel.Pdf.Navigation; namespace iText.Kernel.Pdf { + /// + /// Document outline object + /// See ISO-320001, 12.3.3 Document Outline. + /// public class PdfOutline { + /// A flag for displaying the outline item’s text with italic font. public static int FLAG_ITALIC = 1; + /// A flag for displaying the outline item’s text with bold font. public static int FLAG_BOLD = 2; private IList children = new List(); @@ -66,12 +72,27 @@ public class PdfOutline { private PdfDocument pdfDoc; + /// Create instance of document outline. + /// the text that shall be displayed on the screen for this item. + /// Outline dictionary + /// + /// + /// + /// the outline belongs to. + /// + [System.ObsoleteAttribute(@"Use PdfCatalog.GetOutlines(bool) instead.")] public PdfOutline(String title, PdfDictionary content, PdfDocument pdfDocument) { this.title = title; this.content = content; this.pdfDoc = pdfDocument; } + /// Create instance of document outline. + /// the text that shall be displayed on the screen for this item. + /// Outline dictionary + /// parent outline. + [System.ObsoleteAttribute(@"Use PdfCatalog.GetNextItem(PdfDictionary, PdfOutline, System.Collections.Generic.IDictionary{K, V}) ,AddOutline(System.String, int) and AddOutline(System.String) instead." + )] public PdfOutline(String title, PdfDictionary content, iText.Kernel.Pdf.PdfOutline parent) { this.title = title; this.content = content; @@ -81,8 +102,11 @@ public PdfOutline(String title, PdfDictionary content, iText.Kernel.Pdf.PdfOutli } /// This constructor creates root outline in the document. - /// - /// + /// + /// + /// + /// + [System.ObsoleteAttribute(@"Use PdfCatalog.GetOutlines(bool) instead.")] protected internal PdfOutline(PdfDocument doc) { content = new PdfDictionary(); content.Put(PdfName.Type, PdfName.Outlines); @@ -91,74 +115,170 @@ protected internal PdfOutline(PdfDocument doc) { doc.GetCatalog().AddRootOutline(this); } + /// Gets title of the outline. + /// String value. public virtual String GetTitle() { return title; } + /// + /// Sets title of the outline with + /// + /// encoding, + /// Title + /// key. + /// + /// String value. public virtual void SetTitle(String title) { this.title = title; this.content.Put(PdfName.Title, new PdfString(title, PdfEncodings.UNICODE_BIG)); } + /// + /// Sets color for the outline entry’s text, + /// C + /// key. + /// + /// + /// + /// + /// public virtual void SetColor(Color color) { content.Put(PdfName.C, new PdfArray(color.GetColorValue())); } + /// + /// Sets text style for the outline entry’s text, + /// F + /// key. + /// + /// + /// Could be either + /// + /// or + /// + /// . Default value is + /// 0 + /// . + /// public virtual void SetStyle(int style) { if (style == FLAG_BOLD || style == FLAG_ITALIC) { content.Put(PdfName.F, new PdfNumber(style)); } } + /// Gets content dictionary. + /// + /// + /// + /// . + /// public virtual PdfDictionary GetContent() { return content; } + /// Gets list of children outlines. + /// + /// List of + /// + /// . + /// public virtual IList GetAllChildren() { return children; } + /// Gets parent outline. + /// + /// + /// + /// . + /// public virtual iText.Kernel.Pdf.PdfOutline GetParent() { return parent; } + /// + /// Gets + /// + /// . + /// + /// + /// + /// + /// . + /// public virtual PdfDestination GetDestination() { return destination; } + /// + /// Adds + /// + /// for the outline, + /// Dest + /// key. + /// + /// + /// instance of + /// + /// . + /// public virtual void AddDestination(PdfDestination destination) { SetDestination(destination); content.Put(PdfName.Dest, destination.GetPdfObject()); } + /// + /// Adds + /// + /// for the outline, + /// A + /// key. + /// + /// + /// instance of + /// + /// . + /// public virtual void AddAction(PdfAction action) { content.Put(PdfName.A, action.GetPdfObject()); } - /// - /// Adds an PdfOutline as a child to existing PdfOutline - /// and put it in the end of the existing PdfOutline children list - /// - /// an outline title - /// a created outline - /// - public virtual iText.Kernel.Pdf.PdfOutline AddOutline(String title) { - return AddOutline(title, -1); + /// Defines if the outline needs to be closed or not. + /// + /// Defines if the outline needs to be closed or not. + /// By default, outlines are open. + /// + /// if false, the outline will be closed by default + public virtual void SetOpen(bool open) { + if (!open) { + content.Put(PdfName.Count, new PdfNumber(-1)); + } + else { + if (children.Count > 0) { + content.Put(PdfName.Count, new PdfNumber(children.Count)); + } + else { + content.Remove(PdfName.Count); + } + } } /// - /// Adds an + /// Adds a new /// PdfOutline - /// as a child to existing PdfOutline - /// and put it to specified position in the existing PdfOutline children list + /// with specified parameters as a child to existing + /// PdfOutline + /// and put it to specified position in the existing + /// PdfOutline + /// children list. /// /// an outline title /// /// a position in the current outline child List where a new outline should be added. /// If the position equals -1, then the outline will be put in the end of children list. /// - /// created outline - /// + /// just created outline public virtual iText.Kernel.Pdf.PdfOutline AddOutline(String title, int position) { if (position == -1) { position = children.Count; @@ -185,32 +305,70 @@ public virtual iText.Kernel.Pdf.PdfOutline AddOutline(String title, int position if (position == children.Count) { content.Put(PdfName.Last, dictionary); } - if (children.Count > 0) { - int count = (int)this.content.GetAsInt(PdfName.Count); - if (count > 0) { - content.Put(PdfName.Count, new PdfNumber(count++)); - } - else { - content.Put(PdfName.Count, new PdfNumber(count--)); - } - } - else { - this.content.Put(PdfName.Count, new PdfNumber(-1)); + PdfNumber count = this.content.GetAsNumber(PdfName.Count); + if (count == null || count.GetValue() != -1) { + content.Put(PdfName.Count, new PdfNumber(children.Count + 1)); } children.Add(position, outline); return outline; } + /// + /// Adds an + /// PdfOutline + /// as a child to existing + /// PdfOutline + /// and put it in the end of the existing + /// PdfOutline + /// children list. + /// + /// an outline title + /// just created outline + public virtual iText.Kernel.Pdf.PdfOutline AddOutline(String title) { + return AddOutline(title, -1); + } + + /// + /// Adds an + /// PdfOutline + /// as a child to existing + /// PdfOutline + /// and put it to the end of the existing + /// PdfOutline + /// children list. + /// + /// an outline to add. + /// just created outline + public virtual iText.Kernel.Pdf.PdfOutline AddOutline(iText.Kernel.Pdf.PdfOutline outline) { + iText.Kernel.Pdf.PdfOutline newOutline = AddOutline(outline.GetTitle()); + newOutline.AddDestination(outline.GetDestination()); + IList children = outline.GetAllChildren(); + foreach (iText.Kernel.Pdf.PdfOutline child in children) { + newOutline.AddOutline(child); + } + return newOutline; + } + + /// Clear list of children. internal virtual void Clear() { children.Clear(); } + /// + /// Sets + /// + /// . + /// + /// + /// instance of + /// + /// . + /// internal virtual void SetDestination(PdfDestination destination) { this.destination = destination; } - /// remove this outline from the document. - /// + /// Remove this outline from the document. internal virtual void RemoveOutline() { PdfName type = content.GetAsName(PdfName.Type); if (type != null && type.Equals(PdfName.Outlines)) { @@ -246,15 +404,5 @@ internal virtual void RemoveOutline() { } } } - - public virtual iText.Kernel.Pdf.PdfOutline AddOutline(iText.Kernel.Pdf.PdfOutline outline) { - iText.Kernel.Pdf.PdfOutline newOutline = AddOutline(outline.GetTitle()); - newOutline.AddDestination(outline.GetDestination()); - IList children = outline.GetAllChildren(); - foreach (iText.Kernel.Pdf.PdfOutline child in children) { - newOutline.AddOutline(child); - } - return newOutline; - } } } diff --git a/itext/itext.kernel/itext/kernel/pdf/PdfOutputIntent.cs b/itext/itext.kernel/itext/kernel/pdf/PdfOutputIntent.cs index 146ce11e27..77ebb470ae 100644 --- a/itext/itext.kernel/itext/kernel/pdf/PdfOutputIntent.cs +++ b/itext/itext.kernel/itext/kernel/pdf/PdfOutputIntent.cs @@ -46,6 +46,10 @@ source product. using iText.Kernel.Pdf.Colorspace; namespace iText.Kernel.Pdf { + /// + /// Specify the colour characteristics of output devices on which the document might be rendered + /// See ISO 32000-1 14.11.5: Output Intents. + /// public class PdfOutputIntent : PdfObjectWrapper { /// Creates output intent dictionary. /// diff --git a/itext/itext.kernel/itext/kernel/pdf/PdfOutputStream.cs b/itext/itext.kernel/itext/kernel/pdf/PdfOutputStream.cs index c9dcca9564..1997cbe05f 100644 --- a/itext/itext.kernel/itext/kernel/pdf/PdfOutputStream.cs +++ b/itext/itext.kernel/itext/kernel/pdf/PdfOutputStream.cs @@ -42,7 +42,6 @@ source product. address: sales@itextpdf.com */ using System; -using System.Collections.Generic; using System.IO; using iText.IO; using iText.IO.Log; @@ -156,13 +155,13 @@ private void Write(PdfArray pdfArray) { private void Write(PdfDictionary pdfDictionary) { WriteBytes(openDict); - foreach (KeyValuePair entry in pdfDictionary.EntrySet()) { + foreach (PdfName key in pdfDictionary.KeySet()) { bool isAlreadyWriteSpace = false; - Write(entry.Key); - PdfObject value = entry.Value; + Write(key); + PdfObject value = pdfDictionary.Get(key, false); if (value == null) { ILogger logger = LoggerFactory.GetLogger(typeof(iText.Kernel.Pdf.PdfOutputStream)); - logger.Warn(String.Format(LogMessageConstant.INVALID_KEY_VALUE_KEY_0_HAS_NULL_VALUE, entry.Key)); + logger.Warn(String.Format(LogMessageConstant.INVALID_KEY_VALUE_KEY_0_HAS_NULL_VALUE, key)); value = PdfNull.PDF_NULL; } if ((value.GetObjectType() == PdfObject.NUMBER || value.GetObjectType() == PdfObject.LITERAL || value.GetObjectType @@ -187,7 +186,7 @@ private void Write(PdfDictionary pdfDictionary) { private void Write(PdfIndirectReference indirectReference) { if (document != null && !indirectReference.GetDocument().Equals(document)) { - throw new PdfException(PdfException.PdfInderectObjectBelongToOtherPdfDocument); + throw new PdfException(PdfException.PdfIndirectObjectBelongsToOtherPdfDocument); } if (indirectReference.GetRefersTo() == null) { Write(PdfNull.PDF_NULL); @@ -358,7 +357,7 @@ private void Write(PdfStream pdfStream) { } } catch (System.IO.IOException e) { - throw new PdfException(PdfException.CannotWritePdfStream, e, pdfStream); + throw new PdfException(PdfException.CannotWriteToPdfStream, e, pdfStream); } } diff --git a/itext/itext.kernel/itext/kernel/pdf/PdfPage.cs b/itext/itext.kernel/itext/kernel/pdf/PdfPage.cs index 8f48929dd5..c69e93908a 100644 --- a/itext/itext.kernel/itext/kernel/pdf/PdfPage.cs +++ b/itext/itext.kernel/itext/kernel/pdf/PdfPage.cs @@ -105,24 +105,24 @@ protected internal PdfPage(PdfDocument pdfDocument) : this(pdfDocument, pdfDocument.GetDefaultPageSize()) { } + /// Gets page size, defined by media box object. + /// Gets page size, defined by media box object. This method doesn't take page rotation into account. + /// + /// + /// + /// + /// that specify page size. + /// public virtual Rectangle GetPageSize() { - PdfArray box = GetPdfObject().GetAsArray(PdfName.MediaBox); - if (box == null || box.Size() != 4) { - throw new ArgumentException("MediaBox"); - } - PdfNumber llx = box.GetAsNumber(0); - PdfNumber lly = box.GetAsNumber(1); - PdfNumber urx = box.GetAsNumber(2); - PdfNumber ury = box.GetAsNumber(3); - if (llx == null || lly == null || urx == null || ury == null) { - throw new ArgumentException("MediaBox"); - } - return new Rectangle(Math.Min(llx.FloatValue(), urx.FloatValue()), Math.Min(lly.FloatValue(), ury.FloatValue - ()), Math.Abs(urx.FloatValue() - llx.FloatValue()), Math.Abs(ury.FloatValue() - lly.FloatValue())); + return GetMediaBox(); } - /// Gets the rotated page. - /// the rotated rectangle + /// Gets page size, considering page rotation. + /// + /// + /// + /// that specify size of rotated page. + /// public virtual Rectangle GetPageSizeWithRotation() { PageSize rect = new PageSize(GetPageSize()); int rotation = GetRotation(); @@ -133,6 +133,17 @@ public virtual Rectangle GetPageSizeWithRotation() { return rect; } + /// Gets the number of degrees by which the page shall be rotated clockwise when displayed or printed. + /// + /// + /// Gets the number of degrees by which the page shall be rotated clockwise when displayed or printed. + /// Shall be a multiple of 90. + /// + /// + /// + /// int + /// number of degrees. Default value: 0 + /// public virtual int GetRotation() { PdfNumber rotate = GetPdfObject().GetAsNumber(PdfName.Rotate); if (rotate == null) { @@ -145,11 +156,44 @@ public virtual int GetRotation() { } } + /// Sets the page rotation. + /// + /// the + /// int + /// number of degrees by which the page shall be rotated clockwise + /// when displayed or printed. Shall be a multiple of 90. + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.PdfPage SetRotation(int degAngle) { GetPdfObject().Put(PdfName.Rotate, new PdfNumber(degAngle)); return this; } + /// + /// Gets the content stream at specified 0-based index in the Contents object + /// + /// . + /// The situation when Contents object is a + /// + /// is treated like a one element array. + /// + /// + /// the + /// int + /// index of returned + /// + /// . + /// + /// + /// + /// + /// object at specified index. + /// + /// if the index is out of range public virtual PdfStream GetContentStream(int index) { int count = GetContentStreamCount(); if (index >= count) { @@ -170,6 +214,21 @@ public virtual PdfStream GetContentStream(int index) { } } + /// + /// Gets the size of Contents object + /// + /// . + /// The situation when Contents object is a + /// + /// is treated like a one element array. + /// + /// + /// the + /// int + /// size of Contents object, or 1 if Contents object is a + /// + /// . + /// public virtual int GetContentStreamCount() { PdfObject contents = GetPdfObject().Get(PdfName.Contents); if (contents is PdfStream) { @@ -185,6 +244,20 @@ public virtual int GetContentStreamCount() { } } + /// + /// Returns the Contents object if it is + /// + /// , or first stream in the array if it is + /// + /// . + /// + /// + /// first + /// + /// in Contents object, or + /// + /// if Contents is empty. + /// public virtual PdfStream GetFirstContentStream() { if (GetContentStreamCount() > 0) { return GetContentStream(0); @@ -192,6 +265,20 @@ public virtual PdfStream GetFirstContentStream() { return null; } + /// + /// Returns the Contents object if it is + /// + /// , or last stream in the array if it is + /// + /// . + /// + /// + /// first + /// + /// in Contents object, or + /// + /// if Contents is empty. + /// public virtual PdfStream GetLastContentStream() { int count = GetContentStreamCount(); if (count > 0) { @@ -200,14 +287,60 @@ public virtual PdfStream GetLastContentStream() { return null; } + /// + /// Creates new + /// + /// object and puts it at the beginning of Contents array + /// (if Contents object is + /// + /// it will be replaced with one-element array). + /// + /// + /// Created + /// + /// object. + /// public virtual PdfStream NewContentStreamBefore() { return NewContentStream(true); } + /// + /// Creates new + /// + /// object and puts it at the end of Contents array + /// (if Contents object is + /// + /// it will be replaced with one-element array). + /// + /// + /// Created + /// + /// object. + /// public virtual PdfStream NewContentStreamAfter() { return NewContentStream(false); } + /// + /// Gets the + /// + /// wrapper object for this page resources. + /// If page doesn't have resource object, then it will be inherited from page's parents. + /// If neither parents nor page has the resource object, then the new one is created and added to page dictionary. + ///

    + /// NOTE: If you'll try to modify the inherited resources, then the new resources object will be created, + /// so you won't change the parent's resources. + /// This new object under the wrapper will be added to page dictionary on + /// + /// , + /// or you can add it manually with this line, if needed:
    + /// getPdfObject().put(PdfName.Resources, getResources().getPdfObject()); + ///
    + /// + /// + /// + /// wrapper of the page. + /// public virtual PdfResources GetResources() { if (this.resources == null) { bool readOnly = false; @@ -229,15 +362,34 @@ public virtual PdfResources GetResources() { return this.resources; } + /// + /// Sets + /// + /// object. + /// + /// + /// + /// + /// to set. + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.PdfPage SetResources(PdfResources pdfResources) { GetPdfObject().Put(PdfName.Resources, pdfResources.GetPdfObject()); this.resources = pdfResources; return this; } - /// Use this method to set the XMP Metadata for each page. - /// The xmpMetadata to set. - /// + /// Sets the XMP Metadata. + /// + /// the + /// byte[] + /// of XMP Metadata to set. + /// + /// in case of writing error. public virtual void SetXmpMetadata(byte[] xmpMetadata) { PdfStream xmp = ((PdfStream)new PdfStream().MakeIndirect(GetDocument())); xmp.GetOutputStream().Write(xmpMetadata); @@ -246,20 +398,44 @@ public virtual void SetXmpMetadata(byte[] xmpMetadata) { GetPdfObject().Put(PdfName.Metadata, xmp); } - /// - /// + /// Serializes XMP Metadata to byte array and sets it. + /// + /// the + /// + /// object to set. + /// + /// + /// the + /// + /// used while serialization. + /// + /// in case of XMP Metadata serialization error. + /// in case of writing error. public virtual void SetXmpMetadata(XMPMeta xmpMeta, SerializeOptions serializeOptions) { SetXmpMetadata(XMPMetaFactory.SerializeToBuffer(xmpMeta, serializeOptions)); } - /// - /// + /// Serializes XMP Metadata to byte array and sets it. + /// Serializes XMP Metadata to byte array and sets it. Uses padding equals to 2000. + /// + /// the + /// + /// object to set. + /// + /// in case of XMP Metadata serialization error. + /// in case of writing error. public virtual void SetXmpMetadata(XMPMeta xmpMeta) { SerializeOptions serializeOptions = new SerializeOptions(); serializeOptions.SetPadding(2000); SetXmpMetadata(xmpMeta, serializeOptions); } + /// Gets the XMP Metadata object. + /// + /// + /// + /// object, that represent XMP Metadata. + /// /// public virtual PdfStream GetXmpMetadata() { return GetPdfObject().GetAsStream(PdfName.Metadata); @@ -272,7 +448,11 @@ public virtual PdfStream GetXmpMetadata() { /// NOTE: Works only for pages from the document opened in reading mode, otherwise an exception is thrown. ///
    /// a document to copy page to. - /// copied page. + /// + /// copied + /// + /// . + /// public virtual iText.Kernel.Pdf.PdfPage CopyTo(PdfDocument toDocument) { return CopyTo(toDocument, null); } @@ -284,19 +464,32 @@ public virtual iText.Kernel.Pdf.PdfPage CopyTo(PdfDocument toDocument) { /// NOTE: Works only for pages from the document opened in reading mode, otherwise an exception is thrown. /// /// a document to copy page to. - /// a copier which bears a specific copy logic. May be NULL - /// copied page. + /// + /// a copier which bears a specific copy logic. May be + /// + /// + /// + /// copied + /// + /// . + /// public virtual iText.Kernel.Pdf.PdfPage CopyTo(PdfDocument toDocument, IPdfPageExtraCopier copier) { PdfDictionary dictionary = GetPdfObject().CopyTo(toDocument, excludedKeys, true); iText.Kernel.Pdf.PdfPage page = new iText.Kernel.Pdf.PdfPage(dictionary); CopyInheritedProperties(page, toDocument); foreach (PdfAnnotation annot in GetAnnotations()) { if (annot.GetSubtype().Equals(PdfName.Link)) { - GetDocument().StoreLinkAnnotation(this, (PdfLinkAnnotation)annot); + GetDocument().StoreLinkAnnotation(page, (PdfLinkAnnotation)annot); } else { - page.AddAnnotation(-1, PdfAnnotation.MakeAnnotation(((PdfDictionary)annot.GetPdfObject().CopyTo(toDocument - , false))), false); + if (annot.GetSubtype().Equals(PdfName.Widget)) { + page.AddAnnotation(-1, PdfAnnotation.MakeAnnotation(((PdfDictionary)annot.GetPdfObject().CopyTo(toDocument + , false))), false); + } + else { + page.AddAnnotation(-1, PdfAnnotation.MakeAnnotation(((PdfDictionary)annot.GetPdfObject().CopyTo(toDocument + , true))), false); + } } } if (toDocument.IsTagged()) { @@ -319,7 +512,11 @@ public virtual iText.Kernel.Pdf.PdfPage CopyTo(PdfDocument toDocument, IPdfPageE /// Copies page as FormXObject to the specified document. /// a document to copy to. - /// resultant XObject. + /// + /// copied + /// + /// object. + /// /// public virtual PdfFormXObject CopyAsFormXObject(PdfDocument toDocument) { PdfFormXObject xObject = new PdfFormXObject(GetCropBox()); @@ -332,6 +529,20 @@ public virtual PdfFormXObject CopyAsFormXObject(PdfDocument toDocument) { return xObject; } + /// + /// Gets the + /// + /// that owns that page, or + /// + /// if such document isn't exist. + /// + /// + /// + /// + /// that owns that page, or + /// + /// if such document isn't exist. + /// public virtual PdfDocument GetDocument() { if (GetPdfObject().GetIndirectReference() != null) { return GetPdfObject().GetIndirectReference().GetDocument(); @@ -357,86 +568,160 @@ public override void Flush() { /// Flushes page and its content stream. /// - /// Flushes page and its content stream. If flushXObjects is true the images and FormXObjects - /// associated with this page will also be flushed. + /// Flushes page and its content stream. If flushContentStreams is true, all content streams that are + /// rendered on this page (like FormXObjects, annotation appearance streams, patterns) and also all images associated + /// with this page will also be flushed. ///
    /// For notes about tag structure flushing see /// PdfPage#flush() method /// . ///
    ///
    - /// If PdfADocument is used, flushing will be applied only if flushXObjects is true. + /// If PdfADocument is used, flushing will be applied only if flushContentStreams is true. ///
    - /// if true the images and FormXObjects associated with this page will also be flushed. - /// - public virtual void Flush(bool flushXObjects) { + /// + /// if true all content streams that are rendered on this page (like form xObjects, + /// annotation appearance streams, patterns) and also all images associated with this page + /// will be flushed. + /// + public virtual void Flush(bool flushContentStreams) { // TODO log warning in case of failed flush in pdfa document case if (IsFlushed()) { return; } + GetDocument().DispatchEvent(new PdfDocumentEvent(PdfDocumentEvent.END_PAGE, this)); if (GetDocument().IsTagged() && !GetDocument().GetStructTreeRoot().IsFlushed()) { - GetDocument().GetTagStructureContext().FlushPageTags(this); - GetDocument().GetStructTreeRoot().CreateParentTreeEntryForPage(this); + TryFlushPageTags(); } - GetDocument().DispatchEvent(new PdfDocumentEvent(PdfDocumentEvent.END_PAGE, this)); - if (flushXObjects) { + if (resources != null && resources.IsModified() && !resources.IsReadOnly()) { + GetPdfObject().Put(PdfName.Resources, resources.GetPdfObject()); + } + if (flushContentStreams) { GetDocument().CheckIsoConformance(this, IsoKey.PAGE); + FlushContentStreams(); } int contentStreamCount = GetContentStreamCount(); for (int i = 0; i < contentStreamCount; i++) { GetContentStream(i).Flush(false); } - ICollection xObjects = null; - if (resources != null) { - if (resources.IsReadOnly() && !resources.IsModified()) { - GetPdfObject().Remove(PdfName.Resources); - } - else { - if (flushXObjects) { - PdfDictionary xObjectsDict = GetPdfObject().GetAsDictionary(PdfName.Resources).GetAsDictionary(PdfName.XObject - ); - xObjects = xObjectsDict != null ? xObjectsDict.Values() : null; - } - } - } resources = null; base.Flush(); - if (flushXObjects && xObjects != null) { - FlushXObjects(xObjects); - } } + /// + /// Gets + /// + /// object specified by page's Media Box, that defines the boundaries of the physical medium + /// on which the page shall be displayed or printed + /// + /// + /// + /// + /// object specified by page Media Box, expressed in default user space units. + /// + /// in case of any error while reading MediaBox object. public virtual Rectangle GetMediaBox() { InitParentPages(); PdfArray mediaBox = GetPdfObject().GetAsArray(PdfName.MediaBox); if (mediaBox == null) { mediaBox = (PdfArray)GetParentValue(parentPages, PdfName.MediaBox); } - return mediaBox.ToRectangle(); + if (mediaBox == null) { + throw new PdfException(PdfException.CannotRetrieveMediaBoxAttribute); + } + if (mediaBox.Size() != 4) { + throw new PdfException(PdfException.WrongMediaBoxSize1).SetMessageParams(mediaBox.Size()); + } + PdfNumber llx = mediaBox.GetAsNumber(0); + PdfNumber lly = mediaBox.GetAsNumber(1); + PdfNumber urx = mediaBox.GetAsNumber(2); + PdfNumber ury = mediaBox.GetAsNumber(3); + if (llx == null || lly == null || urx == null || ury == null) { + throw new PdfException(PdfException.InvalidMediaBoxValue); + } + return new Rectangle(Math.Min(llx.FloatValue(), urx.FloatValue()), Math.Min(lly.FloatValue(), ury.FloatValue + ()), Math.Abs(urx.FloatValue() - llx.FloatValue()), Math.Abs(ury.FloatValue() - lly.FloatValue())); } + /// + /// Sets the Media Box object, that defines the boundaries of the physical medium + /// on which the page shall be displayed or printed. + /// + /// + /// the + /// + /// object to set, expressed in default user space units. + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.PdfPage SetMediaBox(Rectangle rectangle) { GetPdfObject().Put(PdfName.MediaBox, new PdfArray(rectangle)); return this; } + /// + /// Gets the + /// + /// specified by page's CropBox, that defines the visible region of default user space. + /// When the page is displayed or printed, its contents shall be clipped (cropped) to this rectangle + /// and then shall be imposed on the output medium in some implementation-defined manner. + /// + /// + /// the + /// + /// object specified by pages's CropBox, expressed in default user space units. + /// MediaBox by default. + /// public virtual Rectangle GetCropBox() { InitParentPages(); PdfArray cropBox = GetPdfObject().GetAsArray(PdfName.CropBox); if (cropBox == null) { cropBox = (PdfArray)GetParentValue(parentPages, PdfName.CropBox); if (cropBox == null) { - cropBox = new PdfArray(GetMediaBox()); + return GetMediaBox(); } } return cropBox.ToRectangle(); } + /// Sets the CropBox object, that defines the visible region of default user space. + /// + /// Sets the CropBox object, that defines the visible region of default user space. + /// When the page is displayed or printed, its contents shall be clipped (cropped) to this rectangle + /// and then shall be imposed on the output medium in some implementation-defined manner. + /// + /// + /// the + /// + /// object to set, expressed in default user space units. + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.PdfPage SetCropBox(Rectangle rectangle) { GetPdfObject().Put(PdfName.CropBox, new PdfArray(rectangle)); return this; } + /// + /// Sets the ArtBox object, that define the extent of the page’s meaningful content + /// (including potential white space) as intended by the page’s creator. + /// + /// + /// the + /// + /// object to set, expressed in default user space units. + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.PdfPage SetArtBox(Rectangle rectangle) { if (GetPdfObject().GetAsRectangle(PdfName.TrimBox) != null) { GetPdfObject().Remove(PdfName.TrimBox); @@ -447,10 +732,35 @@ public virtual iText.Kernel.Pdf.PdfPage SetArtBox(Rectangle rectangle) { return this; } + /// + /// Gets the + /// + /// object specified by page's ArtBox, that define the extent of the page’s + /// meaningful content (including potential white space) as intended by the page’s creator. + /// + /// + /// the + /// + /// object specified by page's ArtBox, expressed in default user space units. + /// CropBox by default. + /// public virtual Rectangle GetArtBox() { - return GetPdfObject().GetAsRectangle(PdfName.ArtBox); + Rectangle artBox = GetPdfObject().GetAsRectangle(PdfName.ArtBox); + return artBox == null ? GetCropBox() : artBox; } + /// Sets the TrimBox object, that define the intended dimensions of the finished page after trimming. + /// + /// + /// the + /// + /// object to set, expressed in default user space units. + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.PdfPage SetTrimBox(Rectangle rectangle) { if (GetPdfObject().GetAsRectangle(PdfName.ArtBox) != null) { GetPdfObject().Remove(PdfName.ArtBox); @@ -461,19 +771,40 @@ public virtual iText.Kernel.Pdf.PdfPage SetTrimBox(Rectangle rectangle) { return this; } + /// + /// Gets the + /// + /// object specified by page's TrimBox object, + /// that define the intended dimensions of the finished page after trimming. + /// + /// + /// the + /// + /// object specified by page's TrimBox, expressed in default user space units. + /// CropBox by default. + /// public virtual Rectangle GetTrimBox() { - return GetPdfObject().GetAsRectangle(PdfName.TrimBox); + Rectangle trimBox = GetPdfObject().GetAsRectangle(PdfName.TrimBox); + return trimBox == null ? GetCropBox() : trimBox; } /// Get decoded bytes for the whole page content. /// byte array. - /// in case any @see IOException. + /// + /// in case of any + /// IOException). + /// public virtual byte[] GetContentBytes() { try { MemoryStream baos = new MemoryStream(); int streamCount = GetContentStreamCount(); + byte[] streamBytes; for (int i = 0; i < streamCount; i++) { - baos.Write(GetStreamBytes(i)); + streamBytes = GetStreamBytes(i); + baos.Write(streamBytes); + if (0 != streamBytes.Length && !char.IsWhiteSpace((char)streamBytes[streamBytes.Length - 1])) { + baos.Write('\n'); + } } return baos.ToArray(); } @@ -485,14 +816,17 @@ public virtual byte[] GetContentBytes() { /// Gets decoded bytes of a certain stream of a page content. /// index of stream inside Content. /// byte array. - /// in case any @see IOException. + /// + /// in case of any + /// IOException). + /// public virtual byte[] GetStreamBytes(int index) { return GetContentStream(index).GetBytes(); } /// Calculates and returns next available MCID reference. /// calculated MCID reference. - /// + /// in case of not tagged document. public virtual int GetNextMcid() { if (!GetDocument().IsTagged()) { throw new PdfException(PdfException.MustBeATaggedDocument); @@ -504,6 +838,16 @@ public virtual int GetNextMcid() { return mcid++; } + /// + /// Gets + /// + /// key of the page’s entry in the structural parent tree. + /// + /// + /// + /// + /// key of the page’s entry in the structural parent tree. + /// public virtual int? GetStructParentIndex() { if (structParents == -1) { PdfNumber n = GetPdfObject().GetAsNumber(PdfName.StructParents); @@ -517,11 +861,40 @@ public virtual int GetNextMcid() { return structParents; } + /// Helper method to add an additional action to this page. + /// + /// Helper method to add an additional action to this page. + /// May be used in chain. + /// + /// + /// a + /// + /// specifying the name of an additional action + /// + /// + /// the + /// + /// to add as an additional action + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.PdfPage SetAdditionalAction(PdfName key, PdfAction action) { PdfAction.SetAdditionalAction(this, key, action); return this; } + /// + /// Gets array of annotation dictionaries that shall contain indirect references + /// to all annotations associated with the page. + /// + /// + /// the + /// List + /// containing all page's annotations. + /// public virtual IList GetAnnotations() { IList annotations = new List(); PdfArray annots = GetPdfObject().GetAsArray(PdfName.Annots); @@ -534,6 +907,19 @@ public virtual IList GetAnnotations() { return annotations; } + /// Checks if page contains the specified annotation. + /// + /// the + /// + /// to check. + /// + /// + /// + /// + /// if page contains specified annotation and + /// + /// otherwise. + /// public virtual bool ContainsAnnotation(PdfAnnotation annotation) { foreach (PdfAnnotation a in GetAnnotations()) { if (a.GetPdfObject().Equals(annotation.GetPdfObject())) { @@ -543,10 +929,55 @@ public virtual bool ContainsAnnotation(PdfAnnotation annotation) { return false; } + /// Adds specified annotation to the end of annotations array and tagged it. + /// + /// Adds specified annotation to the end of annotations array and tagged it. + /// May be used in chain. + /// + /// + /// the + /// + /// to add. + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.PdfPage AddAnnotation(PdfAnnotation annotation) { return AddAnnotation(-1, annotation, true); } + /// + /// Adds specified + /// + /// to specified index in annotations array with or without autotagging. + /// May be used in chain. + /// + /// + /// the index at which specified annotation will be added. If + /// -1 + /// then annotation will be added + /// to the end of array. + /// + /// + /// the + /// + /// to add. + /// + /// + /// if + /// + /// the added annotation will be autotagged.
    + /// (see + /// + /// ) + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.PdfPage AddAnnotation(int index, PdfAnnotation annotation, bool tagAnnotation ) { if (GetDocument().IsTagged() && tagAnnotation) { @@ -578,7 +1009,11 @@ public virtual iText.Kernel.Pdf.PdfPage AddAnnotation(int index, PdfAnnotation a /// NOTE: If document is tagged, PdfDocument's PdfTagStructure instance will point at annotation tag parent after method call. /// /// an annotation to be removed. - /// this PdfPage instance. + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.PdfPage RemoveAnnotation(PdfAnnotation annotation) { PdfArray annots = GetAnnots(false); if (annots != null) { @@ -605,6 +1040,18 @@ public virtual iText.Kernel.Pdf.PdfPage RemoveAnnotation(PdfAnnotation annotatio return this; } + /// + /// Gets the number of + /// + /// associated with this page. + /// + /// + /// the + /// int + /// number of + /// + /// associated with this page. + /// public virtual int GetAnnotsSize() { PdfArray annots = GetAnnots(false); if (annots == null) { @@ -616,7 +1063,6 @@ public virtual int GetAnnotsSize() { /// This method gets outlines of a current page /// /// return all outlines of a current page - /// public virtual IList GetOutlines(bool updateOutlines) { GetDocument().GetOutlines(updateOutlines); return GetDocument().GetCatalog().GetPagesWithOutlines().Get(GetPdfObject()); @@ -654,7 +1100,11 @@ public virtual iText.Kernel.Pdf.PdfPage SetIgnorePageRotationForContent(bool ign /// May be NULL /// /// The label prefix for page labels in this range. May be NULL - /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.PdfPage SetPageLabel(PageLabelNumberingStyleConstants numberingStyle, String labelPrefix) { return SetPageLabel(numberingStyle, labelPrefix, 1); @@ -670,7 +1120,11 @@ public virtual iText.Kernel.Pdf.PdfPage SetPageLabel(PageLabelNumberingStyleCons /// The value of the numeric portion for the first page label in the range. Must be greater or /// equal 1. /// - /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.PdfPage SetPageLabel(PageLabelNumberingStyleConstants numberingStyle, String labelPrefix, int firstPage) { if (firstPage < 1) { @@ -720,6 +1174,27 @@ public virtual iText.Kernel.Pdf.PdfPage SetPageLabel(PageLabelNumberingStyleCons return this; } + /// + /// Helper method that associate specified value with specified key in the underlined + /// + /// . + /// May be used in chain. + /// + /// + /// the + /// + /// key with which the specified value is to be associated. + /// + /// + /// the + /// + /// value to be associated with the specified key. + /// + /// + /// this + /// + /// object. + /// public virtual iText.Kernel.Pdf.PdfPage Put(PdfName key, PdfObject value) { GetPdfObject().Put(key, value); return this; @@ -818,22 +1293,71 @@ private PdfStream NewContentStream(bool before) { return contentStream; } - private void FlushXObjects(ICollection xObjects) { - foreach (PdfObject obj in xObjects) { - PdfStream xObject = (PdfStream)obj; - PdfDictionary innerResources = xObject.GetAsDictionary(PdfName.Resources); - ICollection innerXObjects = null; - if (innerResources != null) { - PdfDictionary innerXObjectsDict = innerResources.GetAsDictionary(PdfName.XObject); - innerXObjects = innerXObjectsDict != null ? innerXObjectsDict.Values() : null; + private void TryFlushPageTags() { + try { + GetDocument().GetTagStructureContext().FlushPageTags(this); + GetDocument().GetStructTreeRoot().CreateParentTreeEntryForPage(this); + } + catch (Exception ex) { + throw new PdfException(PdfException.TagStructureFlushingFailedItMightBeCorrupted, ex); + } + } + + private void FlushContentStreams() { + FlushContentStreams(GetResources().GetPdfObject()); + PdfArray annots = GetAnnots(false); + if (annots != null) { + for (int i = 0; i < annots.Size(); ++i) { + PdfDictionary apDict = annots.GetAsDictionary(i).GetAsDictionary(PdfName.AP); + if (apDict != null) { + FlushAppearanceStreams(apDict); + } + } + } + } + + private void FlushContentStreams(PdfDictionary resources) { + if (resources != null) { + FlushWithResources(resources.GetAsDictionary(PdfName.XObject)); + FlushWithResources(resources.GetAsDictionary(PdfName.Pattern)); + FlushWithResources(resources.GetAsDictionary(PdfName.Shading)); + } + } + + private void FlushWithResources(PdfDictionary objsCollection) { + if (objsCollection == null) { + return; + } + foreach (PdfObject obj in objsCollection.Values()) { + if (obj.IsFlushed()) { + continue; } - obj.Flush(); - if (innerXObjects != null) { - FlushXObjects(innerXObjects); + FlushContentStreams(((PdfDictionary)obj).GetAsDictionary(PdfName.Resources)); + FlushMustBeIndirectObject(obj); + } + } + + private void FlushAppearanceStreams(PdfDictionary appearanceStreamsDict) { + foreach (PdfObject val in appearanceStreamsDict.Values()) { + if (val is PdfDictionary) { + PdfDictionary ap = (PdfDictionary)val; + if (ap.IsDictionary()) { + FlushAppearanceStreams(ap); + } + else { + if (ap.IsStream()) { + FlushMustBeIndirectObject(ap); + } + } } } } + private void FlushMustBeIndirectObject(PdfObject obj) { + // TODO DEVSIX-744 + obj.MakeIndirect(GetDocument()).Flush(); + } + /* * initialization parentPages if needed */ diff --git a/itext/itext.kernel/itext/kernel/pdf/PdfPagesTree.cs b/itext/itext.kernel/itext/kernel/pdf/PdfPagesTree.cs index 2d2dcec441..2e687082a2 100644 --- a/itext/itext.kernel/itext/kernel/pdf/PdfPagesTree.cs +++ b/itext/itext.kernel/itext/kernel/pdf/PdfPagesTree.cs @@ -50,7 +50,7 @@ source product. namespace iText.Kernel.Pdf { /// /// Algorithm for construction - /// PdfPages + /// /// tree /// internal class PdfPagesTree { @@ -221,7 +221,8 @@ public virtual void AddPage(PdfPage pdfPage) { /// one-base index of the page /// /// - /// PdfPage + /// + /// to insert. /// public virtual void AddPage(int index, PdfPage pdfPage) { --index; @@ -268,7 +269,7 @@ public virtual PdfPage RemovePage(int pageNum) { /// Generate PdfPages tree. /// /// root - /// PdfPages + /// /// /// in case empty document protected internal virtual PdfObject GenerateTree() { diff --git a/itext/itext.kernel/itext/kernel/pdf/PdfReader.cs b/itext/itext.kernel/itext/kernel/pdf/PdfReader.cs index d33c574167..f95396941b 100644 --- a/itext/itext.kernel/itext/kernel/pdf/PdfReader.cs +++ b/itext/itext.kernel/itext/kernel/pdf/PdfReader.cs @@ -122,7 +122,6 @@ public PdfReader(IRandomAccessSource byteSource, ReaderProperties properties) { /// /// properties of the created reader /// on error - /// on error public PdfReader(Stream @is, ReaderProperties properties) : this(new RandomAccessSourceFactory().CreateSource(@is), properties) { } @@ -135,7 +134,6 @@ public PdfReader(Stream @is, ReaderProperties properties) /// if user doesn't want to close stream, he should set closeStream=false; /// /// on error - /// on error public PdfReader(Stream @is) : this(@is, new ReaderProperties()) { } @@ -212,7 +210,6 @@ public virtual long GetLastXref() { /// true if to get decoded stream bytes, false if to leave it originally encoded. /// byte[] /// - /// public virtual byte[] ReadStreamBytes(PdfStream stream, bool decode) { byte[] b = ReadStreamBytesRaw(stream); if (decode && b != null) { @@ -288,7 +285,6 @@ public virtual byte[] ReadStreamBytesRaw(PdfStream stream) { /// true if to get decoded stream, false if to leave it originally encoded. /// InputStream /// - /// public virtual Stream ReadStream(PdfStream stream, bool decode) { byte[] bytes = ReadStreamBytes(stream, decode); return bytes != null ? new MemoryStream(bytes) : null; @@ -473,6 +469,9 @@ private void ReadDecryptObj() { encrypted = true; PdfName filter = enc.GetAsName(PdfName.Filter); if (PdfName.Adobe_PubSec.Equals(filter)) { + if (properties.certificate == null) { + throw new PdfException(PdfException.CertificateIsNotProvidedDocumentIsEncryptedWithPublicKeyCertificate); + } decrypt = new PdfEncryption(enc, properties.certificateKey, properties.certificate); } else { @@ -516,7 +515,7 @@ protected internal virtual void ReadObjectStream(PdfStream objectStream) { address[k] = tokens.GetIntValue() + first; } if (!ok) { - throw new PdfException(PdfException.ErrorReadingObjectStream); + throw new PdfException(PdfException.ErrorWhileReadingObjectStream); } for (int k_1 = 0; k_1 < n; ++k_1) { tokens.Seek(address[k_1]); @@ -602,7 +601,7 @@ protected internal virtual PdfObject ReadObject(bool readAsDirect, bool objStm) pdfString.SetDecryptInfoNum(currentIndirectReference.GetObjNumber()); pdfString.SetDecryptInfoGen(currentIndirectReference.GetGenNumber()); } - return properties.password == null || objStm ? pdfString : pdfString.Decrypt(decrypt); + return !IsEncrypted() || objStm ? pdfString : pdfString.Decrypt(decrypt); } case PdfTokenizer.TokenType.Name: { @@ -805,6 +804,22 @@ protected internal virtual PdfDictionary ReadXrefSection() { tokens.NextValidToken(); int gen = tokens.GetIntValue(); tokens.NextValidToken(); + if (pos == 0L && gen == 65535 && num == 1) { + // Very rarely can an XREF have an incorrect start number. (SUP-1557) + // e.g. + // xref + // 1 13 + // 0000000000 65535 f + // 0000000009 00000 n + // 0000215136 00000 n + // [...] + // Because of how iText reads (and initializes) the XREF, this will lead to the XREF having two 0000 65535 entries. + // This throws off the parsing and other operations you'd like to perform. + // To fix this we reset our index and decrease the limit when we've encountered the magic entry at position 1. + num = 0; + end--; + continue; + } PdfIndirectReference reference = xref.Get(num); if (reference == null) { reference = new PdfIndirectReference(pdfDocument, num, gen, pos); @@ -821,7 +836,7 @@ protected internal virtual PdfDictionary ReadXrefSection() { if (tokens.TokenValueEqualsTo(PdfTokenizer.N)) { if (xref.Get(num) == null) { if (pos == 0) { - tokens.ThrowError(PdfException.FilePosition0CrossReferenceEntryInThisXrefSubsection); + tokens.ThrowError(PdfException.FilePosition1CrossReferenceEntryInThisXrefSubsection); } xref.Add(reference); } diff --git a/itext/itext.kernel/itext/kernel/pdf/PdfResources.cs b/itext/itext.kernel/itext/kernel/pdf/PdfResources.cs index 09b0f98f1f..48c1905130 100644 --- a/itext/itext.kernel/itext/kernel/pdf/PdfResources.cs +++ b/itext/itext.kernel/itext/kernel/pdf/PdfResources.cs @@ -43,12 +43,22 @@ source product. */ using System; using System.Collections.Generic; +using iText.IO.Util; +using iText.Kernel; using iText.Kernel.Font; using iText.Kernel.Pdf.Colorspace; using iText.Kernel.Pdf.Extgstate; using iText.Kernel.Pdf.Xobject; namespace iText.Kernel.Pdf { + /// + /// Wrapper class that represent resource dictionary - that define named resources + /// used by content streams operators. + /// + /// + /// Wrapper class that represent resource dictionary - that define named resources + /// used by content streams operators. (ISO 32000-1, 7.8.3 Resource Dictionaries) + /// public class PdfResources : PdfObjectWrapper { private const String F = "F"; @@ -96,35 +106,130 @@ public class PdfResources : PdfObjectWrapper { private bool isModified = false; + /// Creates new instance from given dictionary. + /// + /// the + /// + /// object from which the resource object will be created. + /// public PdfResources(PdfDictionary pdfObject) : base(pdfObject) { BuildResources(pdfObject); } + /// Creates new instance from empty dictionary. public PdfResources() : this(new PdfDictionary()) { } - /// Add font to resources and register PdfFont in the document for further flushing. - /// font resource name. + /// Adds font to resources and register PdfFont in the document for further flushing. + /// added font resource name. public virtual PdfName AddFont(PdfDocument pdfDocument, PdfFont font) { pdfDocument.GetDocumentFonts().Add(font); return AddResource(font, fontNamesGen); } + /// + /// Adds + /// + /// object to the resources. + /// + /// + /// the + /// + /// to add. + /// + /// added image resource name. public virtual PdfName AddImage(PdfImageXObject image) { return AddResource(image, imageNamesGen); } + /// + /// Adds + /// + /// to the resources as image. + /// + /// + /// the + /// + /// to add. + /// + /// added image resources name. + public virtual PdfName AddImage(PdfStream image) { + return AddResource(image, imageNamesGen); + } + + /// + /// Adds + /// + /// to the resources as image. + /// + /// + /// the + /// + /// to add. Should be + /// + /// . + /// + /// added image resources name. + [System.ObsoleteAttribute(@"Will be removed in iText 7.1. Use more safe AddImage(PdfStream) instead.")] public virtual PdfName AddImage(PdfObject image) { + if (image.GetObjectType() != PdfObject.STREAM) { + throw new PdfException(PdfException.CannotAddNonStreamImageToResources1).SetMessageParams(image.GetType(). + ToString()); + } return AddResource(image, imageNamesGen); } + /// + /// Adds + /// + /// object to the resources. + /// + /// + /// the + /// + /// to add. + /// + /// added form resource name. public virtual PdfName AddForm(PdfFormXObject form) { return AddResource(form, formNamesGen); } + /// + /// Adds + /// + /// to the resources as form. + /// + /// + /// the + /// + /// to add. + /// + /// added form resources name. + public virtual PdfName AddForm(PdfStream form) { + return AddResource(form, formNamesGen); + } + + /// + /// Adds + /// + /// to the resources as form. + /// + /// + /// the + /// + /// to add. Should be + /// + /// . + /// + /// added form resources name. + [System.ObsoleteAttribute(@"Will be removed in iText 7.1. Use more safe AddForm(PdfStream) instead.")] public virtual PdfName AddForm(PdfObject form) { + if (form.GetObjectType() != PdfObject.STREAM) { + throw new PdfException(PdfException.CannotAddNonStreamFormToResources1).SetMessageParams(form.GetType().ToString + ()); + } return AddResource(form, formNamesGen); } @@ -150,39 +255,234 @@ public virtual PdfName AddForm(PdfFormXObject form, PdfName name) { return name; } + /// + /// Adds + /// + /// object to the resources. + /// + /// + /// the + /// + /// to add. + /// + /// added graphics state parameter dictionary resource name. public virtual PdfName AddExtGState(PdfExtGState extGState) { return AddResource(extGState, egsNamesGen); } + /// + /// Adds + /// + /// to the resources as graphics state parameter dictionary. + /// + /// + /// the + /// + /// to add. + /// + /// added graphics state parameter dictionary resources name. + public virtual PdfName AddExtGState(PdfDictionary extGState) { + return AddResource(extGState, egsNamesGen); + } + + /// + /// Adds + /// + /// to the resources as graphics state parameter dictionary. + /// + /// + /// the + /// + /// to add. Should be + /// + /// . + /// + /// added graphics state parameter dictionary resources name. + [System.ObsoleteAttribute(@"Will be removed in iText 7.1. Use more safe AddExtGState(PdfDictionary) instead." + )] public virtual PdfName AddExtGState(PdfObject extGState) { + if (extGState.GetObjectType() != PdfObject.DICTIONARY) { + throw new PdfException(PdfException.CannotAddNonDictionaryExtGStateToResources1).SetMessageParams(extGState + .GetType().ToString()); + } return AddResource(extGState, egsNamesGen); } + /// + /// Adds + /// + /// to the resources as properties list. + /// + /// + /// the + /// + /// to add. + /// + /// added properties list resources name. + public virtual PdfName AddProperties(PdfDictionary properties) { + return AddResource(properties, propNamesGen); + } + + /// + /// Adds + /// + /// to the resources as properties list. + /// + /// + /// the + /// + /// to add. Should be + /// + /// . + /// + /// added properties list resources name. + [System.ObsoleteAttribute(@"Will be removed in iText 7.1. Use more safe AddProperties(PdfDictionary) instead." + )] public virtual PdfName AddProperties(PdfObject properties) { + if (properties.GetObjectType() != PdfObject.DICTIONARY) { + throw new PdfException(PdfException.CannotAddNonDictionaryPropertiesToResources1).SetMessageParams(properties + .GetType().ToString()); + } return AddResource(properties, propNamesGen); } + /// + /// Adds + /// + /// object to the resources. + /// + /// + /// the + /// + /// to add. + /// + /// added color space resource name. public virtual PdfName AddColorSpace(PdfColorSpace cs) { return AddResource(cs, csNamesGen); } + /// + /// Adds + /// + /// to the resources as color space. + /// + /// + /// the + /// + /// to add. + /// + /// added color space resources name. public virtual PdfName AddColorSpace(PdfObject colorSpace) { return AddResource(colorSpace, csNamesGen); } + /// + /// Adds + /// + /// object to the resources. + /// + /// + /// the + /// + /// to add. + /// + /// added pattern resource name. public virtual PdfName AddPattern(PdfPattern pattern) { return AddResource(pattern, patternNamesGen); } + /// + /// Adds + /// + /// to the resources as pattern. + /// + /// + /// the + /// + /// to add. + /// + /// added pattern resources name. + public virtual PdfName AddPattern(PdfDictionary pattern) { + return AddResource(pattern, patternNamesGen); + } + + /// + /// Adds + /// + /// to the resources as pattern. + /// + /// + /// the + /// + /// to add. Should be + /// + /// or + /// + /// . + /// + /// added pattern resources name. + [System.ObsoleteAttribute(@"Will be removed in iText 7.1. Use more safe AddPattern(PdfDictionary) instead." + )] public virtual PdfName AddPattern(PdfObject pattern) { + if (pattern is PdfDictionary) { + throw new PdfException(PdfException.CannotAddNonDictionaryPatternToResources1).SetMessageParams(pattern.GetType + ().ToString()); + } return AddResource(pattern, patternNamesGen); } + /// + /// Adds + /// + /// object to the resources. + /// + /// + /// the + /// + /// to add. + /// + /// added shading resource name. public virtual PdfName AddShading(PdfShading shading) { return AddResource(shading, shadingNamesGen); } + /// + /// Adds + /// + /// to the resources as shading dictionary. + /// + /// + /// the + /// + /// to add. + /// + /// added shading dictionary resources name. + public virtual PdfName AddShading(PdfDictionary shading) { + return AddResource(shading, shadingNamesGen); + } + + /// + /// Adds + /// + /// to the resources as shading dictionary. + /// + /// + /// the + /// + /// to add. Should be + /// + /// or + /// + /// . + /// + /// added shading dictionary resources name. + [System.ObsoleteAttribute(@"Will be removed in iText 7.1. Use more safe AddShading(PdfDictionary) instead." + )] public virtual PdfName AddShading(PdfObject shading) { + if (shading is PdfDictionary) { + throw new PdfException(PdfException.CannotAddNonDictionaryShadingToResources1).SetMessageParams(shading.GetType + ().ToString()); + } return AddResource(shading, shadingNamesGen); } @@ -202,31 +502,84 @@ protected internal virtual void SetModified(bool isModified) { this.isModified = isModified; } - /// Sets the default color space. - /// - /// - /// + /// Sets the default color space (see ISO-320001 Paragraph 8.6.5.6). + /// + /// the name of Default Color Space. Should be + /// + /// , + /// + /// , or + /// + /// . + /// + /// the value of the default color space to be set. + [System.ObsoleteAttribute(@"Will be removed in iText 7.1.0. Use SetDefaultGray(iText.Kernel.Pdf.Colorspace.PdfColorSpace) ,SetDefaultRgb(iText.Kernel.Pdf.Colorspace.PdfColorSpace) or SetDefaultCmyk(iText.Kernel.Pdf.Colorspace.PdfColorSpace) instead." + )] public virtual void SetDefaultColorSpace(PdfName defaultCsKey, PdfColorSpace defaultCsValue) { + if (!defaultCsKey.Equals(PdfName.DefaultCMYK) && !defaultCsKey.Equals(PdfName.DefaultGray) && !defaultCsKey + .Equals(PdfName.DefaultRGB)) { + throw new PdfException(PdfException.UnsupportedDefaultColorSpaceName1).SetMessageParams(defaultCsKey.ToString + ()); + } AddResource(defaultCsValue.GetPdfObject(), PdfName.ColorSpace, defaultCsKey); } + /// Sets the value of default Gray Color Space (see ISO-320001 Paragraph 8.6.5.6). + /// the color space to set. public virtual void SetDefaultGray(PdfColorSpace defaultCs) { - SetDefaultColorSpace(PdfName.DefaultGray, defaultCs); + AddResource(defaultCs.GetPdfObject(), PdfName.ColorSpace, PdfName.DefaultGray); } + /// Sets the value of default RGB Color Space (see ISO-320001 Paragraph 8.6.5.6). + /// the color space to set. public virtual void SetDefaultRgb(PdfColorSpace defaultCs) { - SetDefaultColorSpace(PdfName.DefaultRGB, defaultCs); + AddResource(defaultCs.GetPdfObject(), PdfName.ColorSpace, PdfName.DefaultRGB); } + /// Sets the value of default CMYK Color Space (see ISO-320001 Paragraph 8.6.5.6). + /// the color space to set. public virtual void SetDefaultCmyk(PdfColorSpace defaultCs) { - SetDefaultColorSpace(PdfName.DefaultCMYK, defaultCs); + AddResource(defaultCs.GetPdfObject(), PdfName.ColorSpace, PdfName.DefaultCMYK); } + /// + /// Gets the mapped resource name of the + /// + /// under the given wrapper. + ///
    + ///
    + /// Note: if the name for the object won't be found, then the name of object's Indirect Reference will be searched. + ///
    + /// + /// the wrapper of the + /// + /// , for which the name will be searched. + /// + /// + /// + /// the mapped resource name or + /// + /// if object isn't added to resources. + /// public virtual PdfName GetResourceName(PdfObjectWrapper resource) where T : PdfObject { - return resourceToName.Get(resource.GetPdfObject()); + return GetResourceName(resource.GetPdfObject()); } + /// + /// Gets the mapped resource name of the given + /// + /// . + ///
    + ///
    + /// Note: if the name for the object won't be found, then the name of object's Indirect Reference will be searched. + ///
    + /// the object, for which the name will be searched. + /// + /// the mapped resource name or + /// + /// if object isn't added to resources. + /// public virtual PdfName GetResourceName(PdfObject resource) { PdfName resName = resourceToName.Get(resource); if (resName == null) { @@ -235,6 +588,8 @@ public virtual PdfName GetResourceName(PdfObject resource) { return resName; } + /// Gets the names of all the added resources. + /// the name of all the added resources. public virtual ICollection GetResourceNames() { ICollection names = new SortedSet(); // TODO: isn't it better to use HashSet? Do we really need certain order? @@ -244,44 +599,76 @@ public virtual ICollection GetResourceNames() { return names; } + /// Gets the array of predefined procedure set names (see ISO-320001 Paragraph 14.2). + /// the array of predefined procedure set names. public virtual PdfArray GetProcSet() { return GetPdfObject().GetAsArray(PdfName.ProcSet); } + /// Sets the array of predefined procedure set names (see ISO-320001 Paragraph 14.2). + /// the array of predefined procedure set names to be set. public virtual void SetProcSet(PdfArray array) { GetPdfObject().Put(PdfName.ProcSet, array); } + /// Gets the names of all resources of specified type. + /// + /// the resource type. Should be + /// + /// , + /// + /// , + /// + /// , + /// + /// , + /// + /// , + /// + /// . + /// + /// + /// set of resources name of corresponding type. May be empty. + /// Will be empty in case of incorrect resource type. + /// public virtual ICollection GetResourceNames(PdfName resType) { PdfDictionary resourceCategory = GetPdfObject().GetAsDictionary(resType); return resourceCategory == null ? new SortedSet() : resourceCategory.KeySet(); } // TODO: TreeSet or HashSet enough? - public virtual PdfDictionary GetResource(PdfName pdfName) { - return GetPdfObject().GetAsDictionary(pdfName); - } - - // public List getFonts(boolean updateFonts) throws IOException { - // if (updateFonts) { - // getPdfObject().remove(PdfName.Font); - // PdfDictionary fMap = getResource(PdfName.Font); - // if (fMap != null) { - // addFont(fMap.entrySet()); - // } - // PdfDictionary xMap = getResource(PdfName.XObject); - // if (xMap != null && !xMap.isEmpty()) { - // callXObjectFont(xMap.entrySet(), new HashSet()); - // } - // } - // List fonts = new ArrayList<>(); - // for (PdfObject fontDict : getPdfObject().getAsDictionary(PdfName.Font).values()) { - // if (fontDict.isDictionary()) { - // fonts.add((PdfDictionary) fontDict); - // } - // } - // return fonts; - // } + /// + /// Get the + /// + /// object that that contain resources of specified type. + /// + /// + /// the resource type. Should be + /// + /// , + /// + /// , + /// + /// , + /// + /// , + /// + /// , + /// + /// . + /// + /// + /// the + /// + /// object containing all resources of specified type, + /// or + /// + /// in case of incorrect resource type. + /// + public virtual PdfDictionary GetResource(PdfName resType) { + return GetPdfObject().GetAsDictionary(resType); + } + protected internal override bool IsWrappedObjectMustBeIndirect() { return false; } @@ -297,7 +684,7 @@ protected internal virtual void AddResource(PdfObject resource, PdfName resType, CheckAndResolveCircularReferences(resource); } if (readOnly) { - SetPdfObject(new PdfDictionary(GetPdfObject())); + SetPdfObject(GetPdfObject().Clone(JavaCollectionsUtil.EmptyList())); BuildResources(GetPdfObject()); isModified = true; readOnly = false; @@ -343,47 +730,6 @@ protected internal virtual void BuildResources(PdfDictionary dictionary) { } } - // private void addFont(Collection entrySet) throws IOException { - // for (PdfObject entry : entrySet) { - // PdfDictionary fonts = getPdfObject().getAsDictionary(PdfName.Font); - // if (entry.isIndirectReference() && !fonts.containsValue(entry)) { - // fonts.put((PdfIndirectReference) entry.getValue(), - // PdfFont.createFont((PdfDictionary) ((PdfIndirectReference) entry.getValue()).getRefersTo())); - // } else if (entry.getValue().isDictionary()) { - // PdfFont font = PdfFont.createFont((PdfDictionary) entry.getValue()); - // fontsMap.put(font.getPdfObject().getIndirectReference(), font); - // } - // } - // } - // private void addFontFromXObject(Set> entrySet, Set visitedResources) throws IOException { - // PdfDictionary xObject = new PdfDictionary(entrySet); - // PdfDictionary resources = xObject.getAsDictionary(PdfName.Resources); - // if (resources == null) - // return; - // PdfDictionary font = resources.getAsDictionary(PdfName.Font); - // - // if (font != null) { - // addFont(font.values()); - // } - // PdfDictionary xobj = resources.getAsDictionary(PdfName.XObject); - // if (xobj != null) { - // if (visitedResources.add(xobj)) { - // callXObjectFont(xobj.entrySet(), visitedResources); - // visitedResources.remove(xobj); - // } else { - // throw new IOException(IOException.IllegalResourceTree); - // } - // } - // } - // private void callXObjectFont(Set> entrySet, Set visitedResources) throws IOException { - // for (Map.Entry entry : entrySet) { - // if (entry.getValue().isIndirectReference()) { - // if (((PdfIndirectReference) entry.getValue()).getRefersTo().isStream()) { - // addFontFromXObject(((PdfStream) ((PdfIndirectReference) entry.getValue()).getRefersTo()).entrySet(), visitedResources); - // } - // } - // } - // } private void CheckAndResolveCircularReferences(PdfObject pdfObject) { // Consider the situation when an XObject references the resources of the first page. // We add this XObject to the first page, there is no need to resolve any circular references @@ -424,11 +770,19 @@ internal class ResourceNameGenerator { /// class. /// /// - /// Type of resource ( + /// Type of resource. Should be + /// + /// , + /// + /// , + /// + /// , + /// + /// , /// /// , /// - /// etc). + /// . /// /// Prefix used for generating names. /// @@ -447,23 +801,52 @@ public ResourceNameGenerator(PdfName resourceType, String prefix, int seed) { /// class. /// /// - /// Type of resource ( + /// Type of resource. Should be + /// + /// , + /// + /// , + /// + /// , + /// + /// , /// /// , /// - /// etc). + /// . /// /// Prefix used for generating names. public ResourceNameGenerator(PdfName resourceType, String prefix) : this(resourceType, prefix, 1) { } + /// Gets the resource type of generator. + /// + /// Type of resource. May be + /// + /// , + /// + /// , + /// + /// , + /// + /// , + /// + /// , + /// + /// . + /// public virtual PdfName GetResourceType() { return resourceType; } /// Generates new (unique) resource name. - /// New (unique) resource name. + /// + /// the + /// + /// object for which name will be generated. + /// + /// new (unique) resource name. public virtual PdfName Generate(PdfResources resources) { PdfName newName = new PdfName(prefix + counter++); PdfDictionary r = resources.GetPdfObject(); diff --git a/itext/itext.kernel/itext/kernel/pdf/PdfStream.cs b/itext/itext.kernel/itext/kernel/pdf/PdfStream.cs index 18e9ee3c98..f1c79bc6fd 100644 --- a/itext/itext.kernel/itext/kernel/pdf/PdfStream.cs +++ b/itext/itext.kernel/itext/kernel/pdf/PdfStream.cs @@ -72,7 +72,6 @@ public class PdfStream : PdfDictionary { /// /// the compression level (0 = best speed, 9 = best compression, -1 is default) /// - /// on error. public PdfStream(byte[] bytes, int compressionLevel) : base() { // Output stream associated with PDF stream. @@ -111,7 +110,6 @@ public PdfStream(byte[] bytes) /// the data to write to this stream /// the compression level (0 = best speed, 9 = best compression, -1 is default) /// - /// on error. public PdfStream(PdfDocument doc, Stream inputStream, int compressionLevel) : base() { if (doc == null) { @@ -141,7 +139,6 @@ public PdfStream(PdfDocument doc, Stream inputStream, int compressionLevel) /// /// /// the data to write to this stream - /// on error. public PdfStream(PdfDocument doc, Stream inputStream) : this(doc, inputStream, CompressionConstants.UNDEFINED_COMPRESSION) { } @@ -153,7 +150,6 @@ public PdfStream(PdfDocument doc, Stream inputStream) /// /// the compression level (0 = best speed, 9 = best compression, -1 is default) /// - /// on error. public PdfStream(int compressionLevel) : this(null, compressionLevel) { } @@ -219,7 +215,6 @@ public virtual int GetLength() { /// Gets decoded stream bytes. /// byte[] - /// public virtual byte[] GetBytes() { return GetBytes(true); } @@ -238,7 +233,6 @@ public virtual byte[] GetBytes() { /// InputStream /// . ///
    - /// error. public virtual byte[] GetBytes(bool decoded) { if (inputStream != null) { LoggerFactory.GetLogger(typeof(iText.Kernel.Pdf.PdfStream)).Warn("PdfStream was created by InputStream." + @@ -300,7 +294,7 @@ public virtual void SetData(byte[] bytes) { /// public virtual void SetData(byte[] bytes, bool append) { if (inputStream != null) { - throw new PdfException(PdfException.CannotSetDataToPdfstreamWhichWasCreatedByInputstream); + throw new PdfException(PdfException.CannotSetDataToPdfstreamWhichWasCreatedByInputStream); } bool outputStreamIsUninitialized = outputStream == null; if (outputStreamIsUninitialized) { @@ -392,7 +386,6 @@ protected internal virtual long GetOffset() { /// PdfReader.checkPdfStreamLength() /// method. /// - /// error. protected internal virtual void UpdateLength(int length) { this.length = length; } diff --git a/itext/itext.kernel/itext/kernel/pdf/PdfString.cs b/itext/itext.kernel/itext/kernel/pdf/PdfString.cs index 0ceb6b15db..d608819e13 100644 --- a/itext/itext.kernel/itext/kernel/pdf/PdfString.cs +++ b/itext/itext.kernel/itext/kernel/pdf/PdfString.cs @@ -70,8 +70,6 @@ namespace iText.Kernel.Pdf { /// /// public class PdfString : PdfPrimitiveObject { - private static String defaultCharset = "UTF-8"; - protected internal String value; protected internal String encoding; @@ -156,9 +154,13 @@ public virtual String GetEncoding() { /// Sets the encoding of this string. /// NOTE. Byte content will be removed. /// + [System.ObsoleteAttribute(@"Create a new instance with PdfString(System.String, System.String) instead.")] public virtual void SetEncoding(String encoding) { + if (value == null) { + GenerateValue(); + this.content = null; + } this.encoding = encoding; - this.content = null; } /// @@ -240,6 +242,26 @@ public override PdfObject CopyTo(PdfDocument document, bool allowDuplicating) { return (iText.Kernel.Pdf.PdfString)base.CopyTo(document, allowDuplicating); } + public override bool Equals(Object o) { + if (this == o) { + return true; + } + if (o == null || GetType() != o.GetType()) { + return false; + } + iText.Kernel.Pdf.PdfString that = (iText.Kernel.Pdf.PdfString)o; + String v1 = GetValue(); + String v2 = that.GetValue(); + if (v1 != null && v1.Equals(v2)) { + String e1 = GetEncoding(); + String e2 = that.GetEncoding(); + if ((e1 == null && e2 == null) || (e1 != null && e1.Equals(e2))) { + return true; + } + } + return false; + } + public override String ToString() { if (value == null) { return iText.IO.Util.JavaUtil.GetStringForBytes(PdfTokenizer.DecodeStringContent(content, hexWriting)); @@ -249,6 +271,13 @@ public override String ToString() { } } + public override int GetHashCode() { + String v = GetValue(); + String e = GetEncoding(); + int result = v != null ? v.GetHashCode() : 0; + return 31 * result + (e != null ? e.GetHashCode() : 0); + } + protected internal virtual void GenerateValue() { System.Diagnostics.Debug.Assert(content != null, "No byte[] content to generate value"); value = PdfEncodings.ConvertToString(PdfTokenizer.DecodeStringContent(content, hexWriting), null); diff --git a/itext/itext.kernel/itext/kernel/pdf/PdfVersion.cs b/itext/itext.kernel/itext/kernel/pdf/PdfVersion.cs index 2975b99f39..bc2d3423c3 100644 --- a/itext/itext.kernel/itext/kernel/pdf/PdfVersion.cs +++ b/itext/itext.kernel/itext/kernel/pdf/PdfVersion.cs @@ -45,14 +45,14 @@ source product. using System.Collections.Generic; namespace iText.Kernel.Pdf { - /// Enum listing all official PDF versions. + /// This class represents all official PDF versions. public class PdfVersion : IComparable { private static readonly IList values = new List( ); public static readonly iText.Kernel.Pdf.PdfVersion PDF_1_0 = CreatePdfVersion(1, 0); - public static readonly iText.Kernel.Pdf.PdfVersion PDF_1_1 = CreatePdfVersion(1, 0); + public static readonly iText.Kernel.Pdf.PdfVersion PDF_1_1 = CreatePdfVersion(1, 1); public static readonly iText.Kernel.Pdf.PdfVersion PDF_1_2 = CreatePdfVersion(1, 2); @@ -72,7 +72,7 @@ public class PdfVersion : IComparable { private int minor; - /// Creates a PdfVersion enum. + /// Creates a PdfVersion class. /// major version number /// minor version number private PdfVersion(int major, int minor) { @@ -89,7 +89,7 @@ public virtual PdfName ToPdfName() { } /// - /// Creates a PdfVersion enum from a String object if the specified version + /// Creates a PdfVersion class from a String object if the specified version /// can be found. /// /// version number @@ -104,7 +104,7 @@ public static iText.Kernel.Pdf.PdfVersion FromString(String value) { } /// - /// Creates a PdfVersion enum from a + /// Creates a PdfVersion class from a /// /// object if the specified version /// can be found. diff --git a/itext/itext.kernel/itext/kernel/pdf/PdfWriter.cs b/itext/itext.kernel/itext/kernel/pdf/PdfWriter.cs index 07bbbcceea..b2b46ddbe6 100644 --- a/itext/itext.kernel/itext/kernel/pdf/PdfWriter.cs +++ b/itext/itext.kernel/itext/kernel/pdf/PdfWriter.cs @@ -57,11 +57,6 @@ public class PdfWriter : PdfOutputStream { private static readonly byte[] endobj = ByteUtils.GetIsoBytes("\nendobj\n"); - private Dictionary streamMap = new Dictionary(); - - private readonly IntHashtable serialized = new IntHashtable(); - private PdfOutputStream duplicateStream = null; protected internal WriterProperties properties; @@ -73,9 +68,21 @@ public class PdfWriter : PdfOutputStream { /// internal PdfObjectStream objectStream = null; + /// Is used to avoid duplications on object copying. + /// + /// Is used to avoid duplications on object copying. + /// It stores hashes of the indirect reference from the source document and the corresponding + /// indirect references of the copied objects from the new document. + /// protected internal IDictionary copiedObjects = new Dictionary(); + /// Is used in smart mode to store serialized objects content. + private Dictionary serializedContentToObjectRef = new + Dictionary(); + + private Dictionary objectRefToSerializedContent = new Dictionary(); + protected internal bool isUserWarnedAboutAcroFormCopying; public PdfWriter(Stream os) @@ -83,7 +90,7 @@ public PdfWriter(Stream os) } public PdfWriter(Stream os, WriterProperties properties) - : base(os) { + : base(FileUtil.WrapWithBufferedOutputStream(os)) { // For internal usage only //forewarned is forearmed this.properties = properties; @@ -185,16 +192,25 @@ public override void Write(byte[] b, int off, int len) { /// public override void Close() { - base.Close(); - if (duplicateStream != null) { - duplicateStream.Close(); + try { + base.Close(); + } + finally { + try { + if (duplicateStream != null) { + duplicateStream.Close(); + } + } + catch (Exception ex) { + ILogger logger = LoggerFactory.GetLogger(typeof(iText.Kernel.Pdf.PdfWriter)); + logger.Error("Closing of the duplicatedStream failed.", ex); + } } } /// Gets the current object stream. /// object stream. /// - /// internal virtual PdfObjectStream GetObjectStream() { if (!IsFullCompression()) { return null; @@ -216,8 +232,7 @@ internal virtual PdfObjectStream GetObjectStream() { /// /// object to flush. /// indicates whether object can be placed into object stream. - /// - /// + /// on error. protected internal virtual void FlushObject(PdfObject pdfObject, bool canBeInObjStm) { PdfIndirectReference indirectReference = pdfObject.GetIndirectReference(); if (IsFullCompression() && canBeInObjStm) { @@ -276,28 +291,36 @@ protected internal virtual PdfObject CopyObject(PdfObject obj, PdfDocument docum obj = PdfNull.PDF_NULL; } PdfIndirectReference indirectReference = obj.GetIndirectReference(); - PdfIndirectReference copiedIndirectReference; int copyObjectKey = 0; - if (!allowDuplicating && indirectReference != null) { - copyObjectKey = GetCopyObjectKey(obj); - copiedIndirectReference = copiedObjects.Get(copyObjectKey); + bool tryToFindDuplicate = !allowDuplicating && indirectReference != null; + if (tryToFindDuplicate) { + copyObjectKey = CalculateIndRefKey(indirectReference); + PdfIndirectReference copiedIndirectReference = copiedObjects.Get(copyObjectKey); if (copiedIndirectReference != null) { return copiedIndirectReference.GetRefersTo(); } } - if (properties.smartMode && !CheckTypeOfPdfDictionary(obj, PdfName.Page)) { - PdfObject copiedObject = SmartCopyObject(obj); - if (copiedObject != null) { - return copiedObjects.Get(GetCopyObjectKey(copiedObject)).GetRefersTo(); + if (obj.IsDictionary()) { + PdfName subtype = ((PdfDictionary)obj).GetAsName(PdfName.Subtype); + if (subtype != null && subtype.Equals(PdfName.Widget)) { + tryToFindDuplicate = false; + } + } + if (properties.smartMode && tryToFindDuplicate && !CheckTypeOfPdfDictionary(obj, PdfName.Page)) { + PdfIndirectReference copiedObjectRef = TryToFindPreviouslyCopiedEqualObject(obj); + if (copiedObjectRef != null) { + PdfIndirectReference copiedIndirectReference = copiedObjects.Get(CalculateIndRefKey(copiedObjectRef)); + copiedObjects[copyObjectKey] = copiedIndirectReference; + return copiedIndirectReference.GetRefersTo(); } } PdfObject newObject = obj.NewInstance(); if (indirectReference != null) { if (copyObjectKey == 0) { - copyObjectKey = GetCopyObjectKey(obj); + copyObjectKey = CalculateIndRefKey(indirectReference); } - PdfIndirectReference reference = newObject.MakeIndirect(document).GetIndirectReference(); - copiedObjects[copyObjectKey] = reference; + PdfIndirectReference indRef = newObject.MakeIndirect(document).GetIndirectReference(); + copiedObjects[copyObjectKey] = indRef; } newObject.CopyContent(obj, document); return newObject; @@ -306,7 +329,6 @@ protected internal virtual PdfObject CopyObject(PdfObject obj, PdfDocument docum /// Writes object to body of PDF document. /// object to write. /// - /// protected internal virtual void WriteToBody(PdfObject pdfObj) { if (crypto != null) { crypto.SetHashKeyForNextObject(pdfObj.GetIndirectReference().GetObjNumber(), pdfObj.GetIndirectReference() @@ -319,14 +341,12 @@ protected internal virtual void WriteToBody(PdfObject pdfObj) { } /// Writes PDF header. - /// protected internal virtual void WriteHeader() { WriteByte('%').WriteString(document.GetPdfVersion().ToString()).WriteString("\n%\u00e2\u00e3\u00cf\u00d3\n" ); } /// Flushes all objects which have not been flushed yet. - /// protected internal virtual void FlushWaitingObjects() { PdfXrefTable xref = document.GetXref(); bool needFlush = true; @@ -351,7 +371,6 @@ protected internal virtual void FlushWaitingObjects() { /// Flushes all modified objects which have not been flushed yet. /// Flushes all modified objects which have not been flushed yet. Used in case incremental updates. - /// protected internal virtual void FlushModifiedWaitingObjects() { PdfXrefTable xref = document.GetXref(); for (int i = 1; i < xref.Size(); i++) { @@ -369,6 +388,15 @@ protected internal virtual void FlushModifiedWaitingObjects() { } } + /// Calculates hash code for the indirect reference taking into account the document it belongs to. + /// object to be hashed. + /// calculated hash code. + protected internal static int CalculateIndRefKey(PdfIndirectReference indRef) { + int result = indRef.GetHashCode(); + result = 31 * result + indRef.GetDocument().GetHashCode(); + return result; + } + /// Calculates hash code for object to be copied. /// /// Calculates hash code for object to be copied. @@ -376,27 +404,41 @@ protected internal virtual void FlushModifiedWaitingObjects() { /// /// object to be copied. /// calculated hash code. + [System.ObsoleteAttribute(@"Functionality will be removed.")] protected internal virtual int GetCopyObjectKey(PdfObject obj) { - PdfIndirectReference reference; - if (obj.IsIndirectReference()) { - reference = (PdfIndirectReference)obj; - } - else { - reference = obj.GetIndirectReference(); + return CalculateIndRefKey(obj.GetIndirectReference()); + } + + /// Used in the smart mode. + /// + /// Used in the smart mode. + /// It serializes given object content and tries to find previously copied object with the same content. + /// If already copied object is not found, it saves current object serialized content into the map. + /// + /// an object to check if some other object with the same content was already copied. + /// indirect reference of the object with the same content, which already has a copy in the new document. + /// + private PdfIndirectReference TryToFindPreviouslyCopiedEqualObject(PdfObject @object) { + PdfWriter.SerializedPdfObject objectKey; + if (@object.IsStream() || @object.IsDictionary()) { + objectKey = new PdfWriter.SerializedPdfObject(@object, objectRefToSerializedContent); + PdfIndirectReference objectRef = serializedContentToObjectRef.Get(objectKey); + if (objectRef != null) { + return objectRef; + } + serializedContentToObjectRef[objectKey] = @object.GetIndirectReference(); } - int result = reference.GetHashCode(); - result = 31 * result + reference.GetDocument().GetHashCode(); - return result; + return null; } private void MarkArrayContentToFlush(PdfArray array) { - foreach (PdfObject item in array) { - MarkObjectToFlush(item); + for (int i = 0; i < array.Size(); i++) { + MarkObjectToFlush(array.Get(i, false)); } } private void MarkDictionaryContentToFlush(PdfDictionary dictionary) { - foreach (PdfObject item in dictionary.Values()) { + foreach (PdfObject item in dictionary.Values(false)) { MarkObjectToFlush(item); } } @@ -434,29 +476,6 @@ private iText.Kernel.Pdf.PdfWriter SetDebugMode() { return this; } - private PdfObject SmartCopyObject(PdfObject obj) { - PdfWriter.ByteStore streamKey; - if (obj.IsStream()) { - streamKey = new PdfWriter.ByteStore((PdfStream)obj, serialized); - PdfIndirectReference streamRef = streamMap.Get(streamKey); - if (streamRef != null) { - return streamRef; - } - streamMap[streamKey] = obj.GetIndirectReference(); - } - else { - if (obj.IsDictionary()) { - streamKey = new PdfWriter.ByteStore((PdfDictionary)obj, serialized); - PdfIndirectReference streamRef = streamMap.Get(streamKey); - if (streamRef != null) { - return streamRef.GetRefersTo(); - } - streamMap[streamKey] = obj.GetIndirectReference(); - } - } - return null; - } - /// private byte[] GetDebugBytes() { if (duplicateStream != null) { @@ -473,14 +492,35 @@ private static bool CheckTypeOfPdfDictionary(PdfObject dictionary, PdfName expec )); } - internal class ByteStore { - private readonly byte[] b; + internal class SerializedPdfObject { + private readonly byte[] serializedContent; private readonly int hash; private IDigest md5; - private void SerObject(PdfObject obj, int level, ByteBufferOutputStream bb, IntHashtable serialized) { + private Dictionary objToSerializedContent; + + internal SerializedPdfObject(PdfObject obj, Dictionary objToSerializedContent) { + System.Diagnostics.Debug.Assert(obj.IsDictionary() || obj.IsStream()); + this.objToSerializedContent = objToSerializedContent; + try { + md5 = Org.BouncyCastle.Security.DigestUtilities.GetDigest("MD5"); + } + catch (Exception e) { + throw new PdfException(e); + } + ByteBufferOutputStream bb = new ByteBufferOutputStream(); + int level = 100; + SerObject(obj, level, bb); + this.serializedContent = bb.ToByteArray(); + hash = CalculateHash(this.serializedContent); + md5 = null; + } + + // TODO 2: object is not checked if it was already serialized on start, double work could be done + // TODO 3: indirect objects often stored multiple times as parts of the other objects + private void SerObject(PdfObject obj, int level, ByteBufferOutputStream bb) { if (level <= 0) { return; } @@ -490,21 +530,24 @@ private void SerObject(PdfObject obj, int level, ByteBufferOutputStream bb, IntH } PdfIndirectReference reference = null; ByteBufferOutputStream savedBb = null; + int indRefKey = -1; if (obj.IsIndirectReference()) { reference = (PdfIndirectReference)obj; - int key = GetCopyObjectKey(obj); - if (serialized.ContainsKey(key)) { - bb.Append((int)serialized.Get(key)); + indRefKey = CalculateIndRefKey(reference); + byte[] cached = objToSerializedContent.Get(indRefKey); + if (cached != null) { + bb.Append(cached); return; } else { savedBb = bb; bb = new ByteBufferOutputStream(); + obj = reference.GetRefersTo(); } } if (obj.IsStream()) { bb.Append("$B"); - SerDic((PdfDictionary)obj, level - 1, bb, serialized); + SerDic((PdfDictionary)obj, level - 1, bb); if (level > 0) { md5.Reset(); bb.Append(md5.Digest(((PdfStream)obj).GetBytes(false))); @@ -512,11 +555,11 @@ private void SerObject(PdfObject obj, int level, ByteBufferOutputStream bb, IntH } else { if (obj.IsDictionary()) { - SerDic((PdfDictionary)obj, level - 1, bb, serialized); + SerDic((PdfDictionary)obj, level - 1, bb); } else { if (obj.IsArray()) { - SerArray((PdfArray)obj, level - 1, bb, serialized); + SerArray((PdfArray)obj, level - 1, bb); } else { if (obj.IsString()) { @@ -533,22 +576,20 @@ private void SerObject(PdfObject obj, int level, ByteBufferOutputStream bb, IntH } } } + // PdfNull case is also here if (savedBb != null) { - int key = GetCopyObjectKey(reference); - if (!serialized.ContainsKey(key)) { - serialized.Put(key, CalculateHash(bb.GetBuffer())); - } + objToSerializedContent[indRefKey] = bb.GetBuffer(); savedBb.Append(bb); } } - private void SerDic(PdfDictionary dic, int level, ByteBufferOutputStream bb, IntHashtable serialized) { + private void SerDic(PdfDictionary dic, int level, ByteBufferOutputStream bb) { bb.Append("$D"); if (level <= 0) { return; } PdfName[] keys = new PdfName[dic.KeySet().Count]; - dic.KeySet().ToArray(keys); + keys = dic.KeySet().ToArray(keys); iText.IO.Util.JavaUtil.Sort(keys); foreach (Object key in keys) { if (key.Equals(PdfName.P) && (dic.Get((PdfName)key).IsIndirectReference() || dic.Get((PdfName)key).IsDictionary @@ -556,49 +597,19 @@ private void SerDic(PdfDictionary dic, int level, ByteBufferOutputStream bb, Int // ignore recursive call continue; } - SerObject((PdfObject)key, level, bb, serialized); - SerObject(dic.Get((PdfName)key, false), level, bb, serialized); + SerObject((PdfObject)key, level, bb); + SerObject(dic.Get((PdfName)key, false), level, bb); } } - private void SerArray(PdfArray array, int level, ByteBufferOutputStream bb, IntHashtable serialized) { + private void SerArray(PdfArray array, int level, ByteBufferOutputStream bb) { bb.Append("$A"); if (level <= 0) { return; } for (int k = 0; k < array.Size(); ++k) { - SerObject(array.Get(k, false), level, bb, serialized); - } - } - - internal ByteStore(PdfStream str, IntHashtable serialized) { - try { - md5 = Org.BouncyCastle.Security.DigestUtilities.GetDigest("MD5"); - } - catch (Exception e) { - throw new PdfException(e); - } - ByteBufferOutputStream bb = new ByteBufferOutputStream(); - int level = 100; - SerObject(str, level, bb, serialized); - this.b = bb.ToByteArray(); - hash = CalculateHash(this.b); - md5 = null; - } - - internal ByteStore(PdfDictionary dict, IntHashtable serialized) { - try { - md5 = Org.BouncyCastle.Security.DigestUtilities.GetDigest("MD5"); - } - catch (Exception e) { - throw new PdfException(e); + SerObject(array.Get(k, false), level, bb); } - ByteBufferOutputStream bb = new ByteBufferOutputStream(); - int level = 100; - SerObject(dict, level, bb, serialized); - this.b = bb.ToByteArray(); - hash = CalculateHash(this.b); - md5 = null; } private static int CalculateHash(byte[] b) { @@ -611,26 +622,13 @@ private static int CalculateHash(byte[] b) { } public override bool Equals(Object obj) { - return obj is PdfWriter.ByteStore && GetHashCode() == obj.GetHashCode() && iText.IO.Util.JavaUtil.ArraysEquals - (b, ((PdfWriter.ByteStore)obj).b); + return obj is PdfWriter.SerializedPdfObject && GetHashCode() == obj.GetHashCode() && iText.IO.Util.JavaUtil.ArraysEquals + (serializedContent, ((PdfWriter.SerializedPdfObject)obj).serializedContent); } public override int GetHashCode() { return hash; } - - protected internal virtual int GetCopyObjectKey(PdfObject obj) { - PdfIndirectReference reference; - if (obj.IsIndirectReference()) { - reference = (PdfIndirectReference)obj; - } - else { - reference = obj.GetIndirectReference(); - } - int result = reference.GetHashCode(); - result = 31 * result + reference.GetDocument().GetHashCode(); - return result; - } } } } diff --git a/itext/itext.kernel/itext/kernel/pdf/PdfXrefTable.cs b/itext/itext.kernel/itext/kernel/pdf/PdfXrefTable.cs index 888d49e3b7..7a2216eec8 100644 --- a/itext/itext.kernel/itext/kernel/pdf/PdfXrefTable.cs +++ b/itext/itext.kernel/itext/kernel/pdf/PdfXrefTable.cs @@ -43,8 +43,8 @@ source product. */ using System; using System.Collections.Generic; +using System.Text; using iText.IO.Source; -using iText.IO.Util; using iText.Kernel; namespace iText.Kernel.Pdf { @@ -53,10 +53,6 @@ internal class PdfXrefTable { private const int MAX_GENERATION = 65535; - private const String objectOffsetFormatter = "0000000000"; - - private const String objectGenerationFormatter = "00000"; - private static readonly byte[] freeXRefEntry = ByteUtils.GetIsoBytes("f \n"); private static readonly byte[] inUseXRefEntry = ByteUtils.GetIsoBytes("n \n"); @@ -125,6 +121,13 @@ protected internal virtual PdfIndirectReference CreateNextIndirectReference(PdfD return ((PdfIndirectReference)reference.SetState(PdfObject.MODIFIED)); } + //For Object streams + internal virtual PdfIndirectReference CreateNewIndirectReference(PdfDocument document) { + PdfIndirectReference reference = new PdfIndirectReference(document, ++count); + Add(reference); + return ((PdfIndirectReference)reference.SetState(PdfObject.MODIFIED)); + } + protected internal virtual void FreeReference(PdfIndirectReference reference) { reference.SetOffset(0); reference.SetState(PdfObject.FREE); @@ -148,7 +151,6 @@ protected internal virtual void SetCapacity(int capacity) { /// Writes cross reference table and trailer to PDF. /// - /// protected internal virtual void WriteXrefTableAndTrailer(PdfDocument document, PdfObject fileId, PdfObject crypto) { PdfWriter writer = document.GetWriter(); @@ -282,9 +284,10 @@ protected internal virtual void WriteXrefTableAndTrailer(PdfDocument document, P writer.WriteInteger(first).WriteSpace().WriteInteger(len).WriteByte((byte)'\n'); for (int i_2 = first; i_2 < first + len; i_2++) { PdfIndirectReference reference = xrefTable.Get(i_2); - writer.WriteString(DecimalFormatUtil.FormatNumber(reference.GetOffset(), objectOffsetFormatter)).WriteSpace - ().WriteString(DecimalFormatUtil.FormatNumber(reference.GetGenNumber(), objectGenerationFormatter)).WriteSpace - (); + StringBuilder off = new StringBuilder("0000000000").Append(reference.GetOffset()); + StringBuilder gen = new StringBuilder("00000").Append(reference.GetGenNumber()); + writer.WriteString(off.JSubstring(off.Length - 10, off.Length)).WriteSpace().WriteString(gen.JSubstring(gen + .Length - 5, gen.Length)).WriteSpace(); if (reference.IsFree()) { writer.WriteBytes(freeXRefEntry); } diff --git a/itext/itext.kernel/itext/kernel/pdf/action/PdfAction.cs b/itext/itext.kernel/itext/kernel/pdf/action/PdfAction.cs index dbb88c42a7..55f006ac9e 100644 --- a/itext/itext.kernel/itext/kernel/pdf/action/PdfAction.cs +++ b/itext/itext.kernel/itext/kernel/pdf/action/PdfAction.cs @@ -50,103 +50,182 @@ source product. using iText.Kernel.Pdf.Navigation; namespace iText.Kernel.Pdf.Action { + /// A wrapper for action dictionaries (ISO 32000-1 section 12.6). + /// + /// A wrapper for action dictionaries (ISO 32000-1 section 12.6). + /// An action dictionary defines the characteristics and behaviour of an action. + /// public class PdfAction : PdfObjectWrapper { - /// a possible submitvalue + /// A possible submit value public const int SUBMIT_EXCLUDE = 1; - /// a possible submitvalue + /// A possible submit value public const int SUBMIT_INCLUDE_NO_VALUE_FIELDS = 2; - /// a possible submitvalue + /// A possible submit value public const int SUBMIT_HTML_FORMAT = 4; - /// a possible submitvalue + /// A possible submit value public const int SUBMIT_HTML_GET = 8; - /// a possible submitvalue + /// A possible submit value public const int SUBMIT_COORDINATES = 16; - /// a possible submitvalue + /// A possible submit value public const int SUBMIT_XFDF = 32; - /// a possible submitvalue + /// A possible submit value public const int SUBMIT_INCLUDE_APPEND_SAVES = 64; - /// a possible submitvalue + /// A possible submit value public const int SUBMIT_INCLUDE_ANNOTATIONS = 128; - /// a possible submitvalue + /// A possible submit value public const int SUBMIT_PDF = 256; - /// a possible submitvalue + /// A possible submit value public const int SUBMIT_CANONICAL_FORMAT = 512; - /// a possible submitvalue + /// A possible submit value public const int SUBMIT_EXCL_NON_USER_ANNOTS = 1024; - /// a possible submitvalue + /// A possible submit value public const int SUBMIT_EXCL_F_KEY = 2048; - /// a possible submitvalue + /// A possible submit value public const int SUBMIT_EMBED_FORM = 8196; - /// a possible submitvalue + /// A possible submit value public const int RESET_EXCLUDE = 1; + /// Constructs an empty action that can be further modified. public PdfAction() : this(new PdfDictionary()) { Put(PdfName.Type, PdfName.Action); } + /// + /// Constructs a + /// + /// instance with a given dictionary. It can be used for handy + /// property reading in reading mode or modifying in stamping mode. + /// + /// the dictionary to construct the wrapper around public PdfAction(PdfDictionary pdfObject) : base(pdfObject) { MarkObjectAsIndirect(GetPdfObject()); } + /// Creates a GoTo action (section 12.6.4.2 of ISO 32000-1) via a given destination. + /// the desired destination of the action + /// created action public static iText.Kernel.Pdf.Action.PdfAction CreateGoTo(PdfDestination destination) { return new iText.Kernel.Pdf.Action.PdfAction().Put(PdfName.S, PdfName.GoTo).Put(PdfName.D, destination.GetPdfObject ()); } + /// + /// Creates a GoTo action (section 12.6.4.2 of ISO 32000-1) via a given + /// + /// name. + /// + /// + /// + /// + /// name + /// + /// created action public static iText.Kernel.Pdf.Action.PdfAction CreateGoTo(String destination) { return CreateGoTo(new PdfStringDestination(destination)); } + /// Creates a GoToR action, or remote action (section 12.6.4.3 of ISO 32000-1). + /// the file in which the destination shall be located + /// the destination in the remote document to jump to + /// a flag specifying whether to open the destination document in a new window + /// created action public static iText.Kernel.Pdf.Action.PdfAction CreateGoToR(PdfFileSpec fileSpec, PdfDestination destination , bool newWindow) { return new iText.Kernel.Pdf.Action.PdfAction().Put(PdfName.S, PdfName.GoToR).Put(PdfName.F, fileSpec.GetPdfObject ()).Put(PdfName.D, destination.GetPdfObject()).Put(PdfName.NewWindow, new PdfBoolean(newWindow)); } + /// Creates a GoToR action, or remote action (section 12.6.4.3 of ISO 32000-1). + /// the file in which the destination shall be located + /// the destination in the remote document to jump to + /// created action public static iText.Kernel.Pdf.Action.PdfAction CreateGoToR(PdfFileSpec fileSpec, PdfDestination destination ) { return new iText.Kernel.Pdf.Action.PdfAction().Put(PdfName.S, PdfName.GoToR).Put(PdfName.F, fileSpec.GetPdfObject ()).Put(PdfName.D, destination.GetPdfObject()); } + /// Creates a GoToR action, or remote action (section 12.6.4.3 of ISO 32000-1). + /// the remote destination file to jump to + /// the remote destination document page to jump to + /// created action public static iText.Kernel.Pdf.Action.PdfAction CreateGoToR(String filename, int pageNum) { return CreateGoToR(filename, pageNum, false); } + /// Creates a GoToR action, or remote action (section 12.6.4.3 of ISO 32000-1). + /// the remote destination file to jump to + /// the remote destination document page to jump to + /// a flag specifying whether to open the destination document in a new window + /// created action public static iText.Kernel.Pdf.Action.PdfAction CreateGoToR(String filename, int pageNum, bool newWindow) { return CreateGoToR(new PdfStringFS(filename), PdfExplicitDestination.CreateFitH(pageNum, 10000), newWindow ); } + /// Creates a GoToR action, or remote action (section 12.6.4.3 of ISO 32000-1). + /// the remote destination file to jump to + /// the string destination in the remote document to jump to + /// a flag specifying whether to open the destination document in a new window + /// created action public static iText.Kernel.Pdf.Action.PdfAction CreateGoToR(String filename, String destination, bool newWindow ) { return CreateGoToR(new PdfStringFS(filename), new PdfStringDestination(destination), newWindow); } + /// Creates a GoToR action, or remote action (section 12.6.4.3 of ISO 32000-1). + /// the remote destination file to jump to + /// the string destination in the remote document to jump to + /// created action public static iText.Kernel.Pdf.Action.PdfAction CreateGoToR(String filename, String destination) { return CreateGoToR(filename, destination, false); } + /// Creates a GoToE action, or embedded file action (section 12.6.4.4 of ISO 32000-1). + /// the destination in the target to jump to + /// + /// if true, the destination document should be opened in a new window; + /// if false, the destination document should replace the current document in the same window + /// + /// + /// A target dictionary specifying path information to the target document. + /// Each target dictionary specifies one element in the full path to the target and + /// may have nested target dictionaries specifying additional elements + /// + /// created action public static iText.Kernel.Pdf.Action.PdfAction CreateGoToE(PdfDestination destination, bool newWindow, PdfTargetDictionary targetDictionary) { return CreateGoToE(null, destination, newWindow, targetDictionary); } + /// Creates a GoToE action, or embedded file action (section 12.6.4.4 of ISO 32000-1). + /// The root document of the target relative to the root document of the source + /// the destination in the target to jump to + /// + /// if true, the destination document should be opened in a new window; + /// if false, the destination document should replace the current document in the same window + /// + /// + /// A target dictionary specifying path information to the target document. + /// Each target dictionary specifies one element in the full path to the target and + /// may have nested target dictionaries specifying additional elements + /// + /// created action public static iText.Kernel.Pdf.Action.PdfAction CreateGoToE(PdfFileSpec fileSpec, PdfDestination destination , bool newWindow, PdfTargetDictionary targetDictionary) { iText.Kernel.Pdf.Action.PdfAction action = new iText.Kernel.Pdf.Action.PdfAction().Put(PdfName.S, PdfName. @@ -163,10 +242,19 @@ public static iText.Kernel.Pdf.Action.PdfAction CreateGoToE(PdfFileSpec fileSpec return action; } + /// Creates a Launch action (section 12.6.4.5 of ISO 32000-1). + /// the application that shall be launched or the document that shall beopened or printed + /// + /// a flag specifying whether to open the destination document in a new window + /// created action public static iText.Kernel.Pdf.Action.PdfAction CreateLaunch(PdfFileSpec fileSpec, bool newWindow) { return CreateLaunch(fileSpec, null, newWindow); } + /// Creates a Launch action (section 12.6.4.5 of ISO 32000-1). + /// the application that shall be launched or the document that shall beopened or printed + /// + /// created action public static iText.Kernel.Pdf.Action.PdfAction CreateLaunch(PdfFileSpec fileSpec) { iText.Kernel.Pdf.Action.PdfAction action = new iText.Kernel.Pdf.Action.PdfAction().Put(PdfName.S, PdfName. Launch); @@ -176,6 +264,12 @@ public static iText.Kernel.Pdf.Action.PdfAction CreateLaunch(PdfFileSpec fileSpe return action; } + /// Creates a Launch action (section 12.6.4.5 of ISO 32000-1). + /// the application that shall be launched or the document that shall beopened or printed + /// + /// A dictionary containing Windows-specific launch parameters + /// a flag specifying whether to open the destination document in a new window + /// created action public static iText.Kernel.Pdf.Action.PdfAction CreateLaunch(PdfFileSpec fileSpec, PdfWin win, bool newWindow ) { iText.Kernel.Pdf.Action.PdfAction action = new iText.Kernel.Pdf.Action.PdfAction().Put(PdfName.S, PdfName. @@ -189,6 +283,18 @@ public static iText.Kernel.Pdf.Action.PdfAction CreateLaunch(PdfFileSpec fileSpe return action; } + /// Creates a Thread action (section 12.6.4.6 of ISO 32000-1). + /// + /// Creates a Thread action (section 12.6.4.6 of ISO 32000-1). + /// A thread action jumps to a specified bead on an article thread (see 12.4.3, “Articles”), + /// in either the current document or a different one. Table 205 shows the action dictionary + /// entries specific to this type of action. + /// + /// the file containing the thread. If this entry is absent, the thread is in the current file + /// + /// the destination thread + /// the bead in the destination thread + /// created action public static iText.Kernel.Pdf.Action.PdfAction CreateThread(PdfFileSpec fileSpec, PdfObject destinationThread , PdfObject bead) { iText.Kernel.Pdf.Action.PdfAction action = new iText.Kernel.Pdf.Action.PdfAction().Put(PdfName.S, PdfName. @@ -199,30 +305,84 @@ public static iText.Kernel.Pdf.Action.PdfAction CreateThread(PdfFileSpec fileSpe return action; } + /// Creates a Thread action (section 12.6.4.6 of ISO 32000-1). + /// + /// Creates a Thread action (section 12.6.4.6 of ISO 32000-1). + /// A thread action jumps to a specified bead on an article thread (see 12.4.3, “Articles”), + /// in either the current document or a different one. Table 205 shows the action dictionary + /// entries specific to this type of action. + /// + /// the file containing the thread. If this entry is absent, the thread is in the current file + /// + /// created action public static iText.Kernel.Pdf.Action.PdfAction CreateThread(PdfFileSpec fileSpec) { return CreateThread(fileSpec, null, null); } + /// Creates a URI action (section 12.6.4.7 of ISO 32000-1). + /// the uniform resource identifier to resolve + /// created action public static iText.Kernel.Pdf.Action.PdfAction CreateURI(String uri) { return CreateURI(uri, false); } + /// Creates a URI action (section 12.6.4.7 of ISO 32000-1). + /// the uniform resource identifier to resolve + /// a flag specifying whether to track the mouse position when the URI is resolved + /// created action public static iText.Kernel.Pdf.Action.PdfAction CreateURI(String uri, bool isMap) { return new iText.Kernel.Pdf.Action.PdfAction().Put(PdfName.S, PdfName.URI).Put(PdfName.URI, new PdfString( uri)).Put(PdfName.IsMap, new PdfBoolean(isMap)); } + /// Creates a Sound action (section 12.6.4.8 of ISO 32000-1). + /// a sound object defining the sound that shall be played (see section 13.3 of ISO 32000-1) + /// + /// created action public static iText.Kernel.Pdf.Action.PdfAction CreateSound(PdfStream sound) { return new iText.Kernel.Pdf.Action.PdfAction().Put(PdfName.S, PdfName.Sound).Put(PdfName.Sound, sound); } + /// Creates a Sound action (section 12.6.4.8 of ISO 32000-1). + /// a sound object defining the sound that shall be played (see section 13.3 of ISO 32000-1) + /// + /// the volume at which to play the sound, in the range -1.0 to 1.0. Default value: 1.0 + /// + /// a flag specifying whether to play the sound synchronously or asynchronously. + /// If this flag is true, the conforming reader retains control, allowing no further user + /// interaction other than canceling the sound, until the sound has been completely played. + /// Default value: false + /// + /// + /// a flag specifying whether to repeat the sound indefinitely + /// If this entry is present, the Synchronous entry shall be ignored. Default value: false + /// + /// a flag specifying whether to mix this sound with any other sound already playing + /// created action public static iText.Kernel.Pdf.Action.PdfAction CreateSound(PdfStream sound, float volume, bool synchronous , bool repeat, bool mix) { + if (volume < -1 || volume > 1) { + throw new ArgumentException("volume"); + } return new iText.Kernel.Pdf.Action.PdfAction().Put(PdfName.S, PdfName.Sound).Put(PdfName.Sound, sound).Put (PdfName.Volume, new PdfNumber(volume)).Put(PdfName.Synchronous, new PdfBoolean(synchronous)).Put(PdfName .Repeat, new PdfBoolean(repeat)).Put(PdfName.Mix, new PdfBoolean(mix)); } + /// Creates a Movie annotation (section 12.6.4.9 of ISO 32000-1). + /// a movie annotation identifying the movie that shall be played + /// the title of a movie annotation identifying the movie that shall be played + /// + /// the operation that shall be performed on the movie. Shall be one of the following: + /// + /// , + /// + /// , + /// + /// , + /// + /// + /// created annotation public static iText.Kernel.Pdf.Action.PdfAction CreateMovie(PdfAnnotation annotation, String title, PdfName operation) { iText.Kernel.Pdf.Action.PdfAction action = new iText.Kernel.Pdf.Action.PdfAction().Put(PdfName.S, PdfName. @@ -233,34 +393,90 @@ public static iText.Kernel.Pdf.Action.PdfAction CreateMovie(PdfAnnotation annota return action; } + /// Creates a Hide action (section 12.6.4.10 of ISO 32000-1). + /// the annotation to be hidden or shown + /// a flag indicating whether to hide the annotation (true) or show it (false) + /// + /// created action public static iText.Kernel.Pdf.Action.PdfAction CreateHide(PdfAnnotation annotation, bool hidden) { return new iText.Kernel.Pdf.Action.PdfAction().Put(PdfName.S, PdfName.Hide).Put(PdfName.T, annotation.GetPdfObject ()).Put(PdfName.H, new PdfBoolean(hidden)); } + /// Creates a Hide action (section 12.6.4.10 of ISO 32000-1). + /// the annotations to be hidden or shown + /// a flag indicating whether to hide the annotation (true) or show it (false) + /// + /// created action public static iText.Kernel.Pdf.Action.PdfAction CreateHide(PdfAnnotation[] annotations, bool hidden) { return new iText.Kernel.Pdf.Action.PdfAction().Put(PdfName.S, PdfName.Hide).Put(PdfName.T, GetPdfArrayFromAnnotationsList (annotations)).Put(PdfName.H, new PdfBoolean(hidden)); } + /// Creates a Hide action (section 12.6.4.10 of ISO 32000-1). + /// + /// a text string giving the fully qualified field name of an interactive form field whose + /// associated widget annotation or annotations are to be affected + /// + /// a flag indicating whether to hide the annotation (true) or show it (false) + /// + /// created action public static iText.Kernel.Pdf.Action.PdfAction CreateHide(String text, bool hidden) { return new iText.Kernel.Pdf.Action.PdfAction().Put(PdfName.S, PdfName.Hide).Put(PdfName.T, new PdfString(text )).Put(PdfName.H, new PdfBoolean(hidden)); } + /// Creates a Hide action (section 12.6.4.10 of ISO 32000-1). + /// + /// a text string array giving the fully qualified field names of interactive form fields whose + /// associated widget annotation or annotations are to be affected + /// + /// a flag indicating whether to hide the annotation (true) or show it (false) + /// + /// created action public static iText.Kernel.Pdf.Action.PdfAction CreateHide(String[] text, bool hidden) { return new iText.Kernel.Pdf.Action.PdfAction().Put(PdfName.S, PdfName.Hide).Put(PdfName.T, GetArrayFromStringList (text)).Put(PdfName.H, new PdfBoolean(hidden)); } + /// Creates a Named action (section 12.6.4.11 of ISO 32000-1). + /// + /// the name of the action that shall be performed. Shall be one of the following: + /// + /// , + /// + /// , + /// + /// , + /// + /// + /// created action public static iText.Kernel.Pdf.Action.PdfAction CreateNamed(PdfName namedAction) { return new iText.Kernel.Pdf.Action.PdfAction().Put(PdfName.S, PdfName.Named).Put(PdfName.N, namedAction); } + /// Creates a Set-OCG-State action (section 12.6.4.12 of ISO 32000-1). + /// + /// a list of + /// + /// state descriptions + /// + /// created action public static iText.Kernel.Pdf.Action.PdfAction CreateSetOcgState(IList states) { return CreateSetOcgState(states, false); } + /// Creates a Set-OCG-State action (section 12.6.4.12 of ISO 32000-1). + /// + /// states a list of + /// + /// state descriptions + /// + /// + /// If true, indicates that radio-button state relationships between optional content groups + /// should be preserved when the states are applied + /// + /// created action public static iText.Kernel.Pdf.Action.PdfAction CreateSetOcgState(IList states, bool preserveRb ) { PdfArray stateArr = new PdfArray(); @@ -271,6 +487,12 @@ public static iText.Kernel.Pdf.Action.PdfAction CreateSetOcgState(IListCreates a Rendition action (section 12.6.4.13 of ISO 32000-1). + /// the name of the media clip, for use in the user interface. + /// a full file specification or form XObject that specifies the actual media data + /// an ASCII string identifying the type of data + /// a screen annotation + /// created action public static iText.Kernel.Pdf.Action.PdfAction CreateRendition(String file, PdfFileSpec fileSpec, String mimeType, PdfAnnotation screenAnnotation) { return new iText.Kernel.Pdf.Action.PdfAction().Put(PdfName.S, PdfName.Rendition).Put(PdfName.OP, new PdfNumber @@ -278,18 +500,33 @@ public static iText.Kernel.Pdf.Action.PdfAction CreateRendition(String file, Pdf mimeType).GetPdfObject()); } + /// Creates a JavaScript action (section 12.6.4.16 of ISO 32000-1). + /// a text string containing the JavaScript script to be executed. + /// created action public static iText.Kernel.Pdf.Action.PdfAction CreateJavaScript(String javaScript) { return new iText.Kernel.Pdf.Action.PdfAction().Put(PdfName.S, PdfName.JavaScript).Put(PdfName.JS, new PdfString (javaScript)); } + /// Creates a Submit-Form Action (section 12.7.5.2 of ISO 32000-1). + /// a uniform resource locator, as described in 7.11.5, "URL Specifications" + /// + /// an array identifying which fields to include in the submission or which to exclude, + /// depending on the setting of the Include/Exclude flag in the Flags entry. + /// This is an optional parameter and can be null + /// + /// + /// a set of flags specifying various characteristics of the action (see Table 237 of ISO 32000-1). + /// Default value to be passed: 0. + /// + /// created action public static iText.Kernel.Pdf.Action.PdfAction CreateSubmitForm(String file, Object[] names, int flags) { iText.Kernel.Pdf.Action.PdfAction action = new iText.Kernel.Pdf.Action.PdfAction(); action.Put(PdfName.S, PdfName.SubmitForm); - PdfDictionary dic = new PdfDictionary(); - dic.Put(PdfName.F, new PdfString(file)); - dic.Put(PdfName.FS, PdfName.URL); - action.Put(PdfName.F, dic); + PdfDictionary urlFileSpec = new PdfDictionary(); + urlFileSpec.Put(PdfName.F, new PdfString(file)); + urlFileSpec.Put(PdfName.FS, PdfName.URL); + action.Put(PdfName.F, urlFileSpec); if (names != null) { action.Put(PdfName.Fields, BuildArray(names)); } @@ -297,6 +534,16 @@ public static iText.Kernel.Pdf.Action.PdfAction CreateSubmitForm(String file, Ob return action; } + /// Creates a Reset-Form Action (section 12.7.5.3 of ISO 32000-1). + /// + /// an array identifying which fields to reset or which to exclude from resetting, + /// depending on the setting of the Include/Exclude flag in the Flags entry (see Table 239 of ISO 32000-1). + /// + /// + /// a set of flags specifying various characteristics of the action (see Table 239 of ISO 32000-1). + /// Default value to be passed: 0. + /// + /// created action public static iText.Kernel.Pdf.Action.PdfAction CreateResetForm(Object[] names, int flags) { iText.Kernel.Pdf.Action.PdfAction action = new iText.Kernel.Pdf.Action.PdfAction(); action.Put(PdfName.S, PdfName.ResetForm); @@ -307,6 +554,22 @@ public static iText.Kernel.Pdf.Action.PdfAction CreateResetForm(Object[] names, return action; } + /// + /// Adds an additional action to the provided + /// PdfObjectWrapper + /// wrapper. + /// + /// the wrapper to add an additional action to + /// + /// a + /// + /// specifying the name of an additional action + /// + /// + /// the + /// + /// to add as an additional action + /// public static void SetAdditionalAction(PdfObjectWrapper wrapper, PdfName key, iText.Kernel.Pdf.Action.PdfAction action) { PdfDictionary dic; @@ -321,30 +584,62 @@ public static void SetAdditionalAction(PdfObjectWrapper wrapper, wrapper.GetPdfObject().Put(PdfName.AA, dic); } - /// Add a chained action. - /// - public virtual void Next(iText.Kernel.Pdf.Action.PdfAction na) { - PdfObject nextAction = GetPdfObject().Get(PdfName.Next); - if (nextAction == null) { - Put(PdfName.Next, na.GetPdfObject()); + /// Adds a chained action. + /// the next action or sequence of actions that shall be performed after the current action + /// + public virtual void Next(iText.Kernel.Pdf.Action.PdfAction nextAction) { + PdfObject currentNextAction = GetPdfObject().Get(PdfName.Next); + if (currentNextAction == null) { + Put(PdfName.Next, nextAction.GetPdfObject()); } else { - if (nextAction.IsDictionary()) { - PdfArray array = new PdfArray(nextAction); - array.Add(na.GetPdfObject()); + if (currentNextAction.IsDictionary()) { + PdfArray array = new PdfArray(currentNextAction); + array.Add(nextAction.GetPdfObject()); Put(PdfName.Next, array); } else { - ((PdfArray)nextAction).Add(na.GetPdfObject()); + ((PdfArray)currentNextAction).Add(nextAction.GetPdfObject()); } } } + /// + /// Inserts the value into the underlying object of this + /// + /// and associates it with the specified key. + /// If the key is already present in this + /// + /// , this method will override the old value with the specified one. + /// + /// key to insert or to override + /// the value to associate with the specified key + /// + /// this + /// + /// instance + /// public virtual iText.Kernel.Pdf.Action.PdfAction Put(PdfName key, PdfObject value) { GetPdfObject().Put(key, value); return this; } + /// + /// To manually flush a + /// PdfObject + /// behind this wrapper, you have to ensure + /// that this object is added to the document, i.e. it has an indirect reference. + /// Basically this means that before flushing you need to explicitly call + /// + /// . + /// For example: wrapperInstance.makeIndirect(document).flush(); + /// Note that not every wrapper require this, only those that have such warning in documentation. + /// + public override void Flush() { + base.Flush(); + } + + /// protected internal override bool IsWrappedObjectMustBeIndirect() { return true; } diff --git a/itext/itext.kernel/itext/kernel/pdf/action/PdfActionOcgState.cs b/itext/itext.kernel/itext/kernel/pdf/action/PdfActionOcgState.cs index 32f88de906..059645960d 100644 --- a/itext/itext.kernel/itext/kernel/pdf/action/PdfActionOcgState.cs +++ b/itext/itext.kernel/itext/kernel/pdf/action/PdfActionOcgState.cs @@ -45,26 +45,74 @@ source product. using iText.Kernel.Pdf; namespace iText.Kernel.Pdf.Action { - /// USed in Set OCG State actions. + /// This is a helper class for optional content states use in Set-OCG-State actions. + /// + /// This is a helper class for optional content states use in Set-OCG-State actions. + /// See + /// + /// . + /// public class PdfActionOcgState { - /// Can be: OFF, ON, Toggle + /// + /// Can be: + /// + /// , + /// + /// , + /// + /// private PdfName state; + /// Optional content group dictionaries private IList ocgs; + /// Constructs an optional content state object. + /// + /// a + /// + /// describing the state. Shall be one of the following: + /// + /// , + /// + /// , + /// + /// + /// a list of the OCG dictionaries public PdfActionOcgState(PdfName state, IList ocgs) { this.state = state; this.ocgs = ocgs; } + /// Gets the state the optional content groups should be switched to + /// + /// the state, one of the following: + /// + /// , + /// + /// , + /// + /// public virtual PdfName GetState() { return state; } + /// Gets a list of optional content groups that shall have the state changed + /// the list of optional content groups public virtual IList GetOcgs() { return ocgs; } + /// + /// Gets a list of + /// + /// that is describing this particular optional content group states. + /// + /// + /// a list of + /// + /// for construction of a + /// + /// public virtual IList GetObjectList() { IList states = new List(); states.Add(state); diff --git a/itext/itext.kernel/itext/kernel/pdf/action/PdfMediaClipData.cs b/itext/itext.kernel/itext/kernel/pdf/action/PdfMediaClipData.cs index 952fbfdb15..be03c5f71a 100644 --- a/itext/itext.kernel/itext/kernel/pdf/action/PdfMediaClipData.cs +++ b/itext/itext.kernel/itext/kernel/pdf/action/PdfMediaClipData.cs @@ -46,13 +46,29 @@ source product. using iText.Kernel.Pdf.Filespec; namespace iText.Kernel.Pdf.Action { + /// This class is a wrapper of media clip data dictionary that defines the data for a media object that can be played. + /// public class PdfMediaClipData : PdfObjectWrapper { private static readonly PdfString TEMPACCESS = new PdfString("TEMPACCESS"); + /// + /// Constructs a new + /// + /// wrapper using an existing dictionary. + /// + /// the dictionary to construct the wrapper from public PdfMediaClipData(PdfDictionary pdfObject) : base(pdfObject) { } + /// + /// Constructs a new + /// + /// wrapper around a newly created dictionary. + /// + /// the name of the file to create a media clip for + /// a file specification that specifies the actual media data + /// an ASCII string identifying the type of data public PdfMediaClipData(String file, PdfFileSpec fs, String mimeType) : this(new PdfDictionary()) { PdfDictionary dic = new PdfDictionary(); @@ -66,6 +82,22 @@ public PdfMediaClipData(String file, PdfFileSpec fs, String mimeType) GetPdfObject().Put(PdfName.D, fs.GetPdfObject()); } + /// + /// To manually flush a + /// PdfObject + /// behind this wrapper, you have to ensure + /// that this object is added to the document, i.e. it has an indirect reference. + /// Basically this means that before flushing you need to explicitly call + /// + /// . + /// For example: wrapperInstance.makeIndirect(document).flush(); + /// Note that not every wrapper require this, only those that have such warning in documentation. + /// + public override void Flush() { + base.Flush(); + } + + /// protected internal override bool IsWrappedObjectMustBeIndirect() { return true; } diff --git a/itext/itext.kernel/itext/kernel/pdf/action/PdfRendition.cs b/itext/itext.kernel/itext/kernel/pdf/action/PdfRendition.cs index a303a64553..3e7d0bcbb8 100644 --- a/itext/itext.kernel/itext/kernel/pdf/action/PdfRendition.cs +++ b/itext/itext.kernel/itext/kernel/pdf/action/PdfRendition.cs @@ -46,11 +46,22 @@ source product. using iText.Kernel.Pdf.Filespec; namespace iText.Kernel.Pdf.Action { + /// This a wrapper around a rendition dictionary. + /// This a wrapper around a rendition dictionary. See ISO 32000-1 sections 13.2.3.2, 13.2.3.3. public class PdfRendition : PdfObjectWrapper { + /// + /// Creates a new wrapper around an existing + /// + /// + /// a rendition object to create a wrapper for public PdfRendition(PdfDictionary pdfObject) : base(pdfObject) { } + /// Creates a new wrapper around a newly created media rendition dictionary object. + /// a text string specifying the name of the file to display + /// a file specification that specifies the actual media data + /// an ASCII string identifying the type of data public PdfRendition(String file, PdfFileSpec fs, String mimeType) : this(new PdfDictionary()) { GetPdfObject().Put(PdfName.S, PdfName.MR); @@ -58,6 +69,22 @@ public PdfRendition(String file, PdfFileSpec fs, String mimeType) GetPdfObject().Put(PdfName.C, new PdfMediaClipData(file, fs, mimeType).GetPdfObject()); } + /// + /// To manually flush a + /// PdfObject + /// behind this wrapper, you have to ensure + /// that this object is added to the document, i.e. it has an indirect reference. + /// Basically this means that before flushing you need to explicitly call + /// + /// . + /// For example: wrapperInstance.makeIndirect(document).flush(); + /// Note that not every wrapper require this, only those that have such warning in documentation. + /// + public override void Flush() { + base.Flush(); + } + + /// protected internal override bool IsWrappedObjectMustBeIndirect() { return true; } diff --git a/itext/itext.kernel/itext/kernel/pdf/action/PdfTargetDictionary.cs b/itext/itext.kernel/itext/kernel/pdf/action/PdfTargetDictionary.cs index a2341487ee..2744a07d0a 100644 --- a/itext/itext.kernel/itext/kernel/pdf/action/PdfTargetDictionary.cs +++ b/itext/itext.kernel/itext/kernel/pdf/action/PdfTargetDictionary.cs @@ -45,92 +45,249 @@ source product. using iText.Kernel.Pdf; namespace iText.Kernel.Pdf.Action { + /// + /// A target dictionary locates the target in relation to the source, + /// in much the same way that a relative path describes the physical + /// relationship between two files in a file system. + /// + /// + /// A target dictionary locates the target in relation to the source, + /// in much the same way that a relative path describes the physical + /// relationship between two files in a file system. Target dictionaries may be + /// nested recursively to specify one or more intermediate targets before reaching the final one. + /// public class PdfTargetDictionary : PdfObjectWrapper { + /// + /// Creates a new + /// + /// object by the underlying dictionary. + /// + /// the underlying dictionary object public PdfTargetDictionary(PdfDictionary pdfObject) : base(pdfObject) { } + /// + /// Creates a new + /// + /// object given its type. The type must be either + /// + /// , or + /// + /// . If it is + /// + /// , additional entries must be specified + /// according to the spec. + /// + /// the relationship between the current document and the target public PdfTargetDictionary(PdfName r) : this(new PdfDictionary()) { Put(PdfName.R, r); } + /// + /// Creates a new + /// + /// object. + /// + /// the relationship between the current document and the target + /// the name of the file in the EmbeddedFiles name tree + /// + /// if the value is an integer, it specifies the page number (zero-based) in the current + /// document containing the file attachment annotation. If the value is a string, + /// it specifies a named destination in the current document that provides the page + /// number of the file attachment annotation + /// + /// + /// If the value is an integer, it specifies the index (zero-based) of the annotation in the + /// Annots array of the page specified by P. If the value is a text string, + /// it specifies the value of NM in the annotation dictionary + /// + /// + /// A target dictionary specifying additional path information to the target document. + /// If this entry is absent, the current document is the target file containing the destination + /// public PdfTargetDictionary(PdfName r, PdfString n, PdfObject p, PdfObject a, iText.Kernel.Pdf.Action.PdfTargetDictionary t) : this(new PdfDictionary()) { Put(PdfName.R, r).Put(PdfName.N, n).Put(PdfName.P, p).Put(PdfName.A, a).Put(PdfName.T, t.GetPdfObject()); } - /// Sets the name of the file in the EmbeddedFiles name tree. + /// Creates a new target object pointing to the parent of the current document. + /// + /// created + /// + /// + public static iText.Kernel.Pdf.Action.PdfTargetDictionary CreateParentTarget() { + return new iText.Kernel.Pdf.Action.PdfTargetDictionary(PdfName.P); + } + + /// Creates a new target object pointing to a file in the EmbeddedFiles name tree. + /// the name of the file in the EmbeddedFiles name tree + /// created object + public static iText.Kernel.Pdf.Action.PdfTargetDictionary CreateChildTarget(String embeddedFileName) { + return new iText.Kernel.Pdf.Action.PdfTargetDictionary(PdfName.C).Put(PdfName.N, new PdfString(embeddedFileName + )); + } + + /// Creates a new target object pointing to a file attachment annotation. + /// + /// a named destination in the current document that + /// provides the page number of the file attachment annotation + /// + /// + /// a unique annotation identifier ( + /// + /// entry) of the annotation + /// + /// created object + public static iText.Kernel.Pdf.Action.PdfTargetDictionary CreateChildTarget(String namedDestination, String + annotationIdentifier) { + return new iText.Kernel.Pdf.Action.PdfTargetDictionary(PdfName.C).Put(PdfName.P, new PdfString(namedDestination + )).Put(PdfName.A, new PdfString(annotationIdentifier)); + } + + /// Creates a new target object pointing to a file attachment annotation. + /// the number of the page in the current document, one-based + /// the index of the annotation in the Annots entry of the page, zero-based + /// created object + public static iText.Kernel.Pdf.Action.PdfTargetDictionary CreateChildTarget(int pageNumber, int annotationIndex + ) { + return new iText.Kernel.Pdf.Action.PdfTargetDictionary(PdfName.C).Put(PdfName.P, new PdfNumber(pageNumber + - 1)).Put(PdfName.A, new PdfNumber(annotationIndex)); + } + + /// + /// Sets the name of the file in the EmbeddedFiles name tree for the child target located + /// in the EmbeddedFiles. + /// /// the name of the file - /// + /// this object wrapper public virtual iText.Kernel.Pdf.Action.PdfTargetDictionary SetName(String name) { return Put(PdfName.N, new PdfString(name)); } - /// Gets name of the file - /// + /// + /// Gets name of the file in the EmbeddedFiles name tree for the child target located + /// in the EmbeddedFiles. + /// + /// the name of the child file for this target public virtual PdfString GetName() { return GetPdfObject().GetAsString(PdfName.N); } - /// Sets the page number in the current document containing the file attachment annotation. - /// - /// + /// + /// Sets the page number in the current document containing the file attachment annotation for the + /// child target associates with a file attachment annotation. + /// + /// + /// the page number (one-based) in the current document containing + /// the file attachment annotation + /// + /// this object wrapper public virtual iText.Kernel.Pdf.Action.PdfTargetDictionary SetPage(int pageNumber) { - return Put(PdfName.P, new PdfNumber(pageNumber)); + return Put(PdfName.P, new PdfNumber(pageNumber - 1)); } - /// Sets a named destination in the current document that provides the page number of the file attachment annotation. - /// - /// - /// + /// + /// Sets a named destination in the current document that provides the page number of the file + /// attachment annotation for the child target associated with a file attachment annotation. + /// + /// + /// a named destination in the current document that provides the page + /// number of the file attachment annotation + /// + /// this object wrapper public virtual iText.Kernel.Pdf.Action.PdfTargetDictionary SetPage(String namedDestination) { return Put(PdfName.P, new PdfString(namedDestination)); } - /// Get the page number or a named destination that provides the page number containing the file attachment annotation - /// - /// + /// Get the contents of the /P entry of this target object. + /// + /// Get the contents of the /P entry of this target object. + /// If the value is an integer, it specifies the page number (zero-based) + /// in the current document containing the file attachment annotation. + /// If the value is a string, it specifies a named destination in the current + /// document that provides the page number of the file attachment annotation. + /// + /// the /P entry of target object public virtual PdfObject GetPage() { return GetPdfObject().Get(PdfName.P); } - /// Sets the index of the annotation in Annots array of the page specified by /P entry. - /// - /// - public virtual iText.Kernel.Pdf.Action.PdfTargetDictionary SetAnnotation(int annotNumber) { - return Put(PdfName.A, new PdfNumber(annotNumber)); + /// + /// Sets the index of the annotation in Annots array of the page specified by /P entry + /// for the child target associated with a file attachment annotation. + /// + /// the index (zero-based) of the annotation in the Annots array + /// this object wrapper + public virtual iText.Kernel.Pdf.Action.PdfTargetDictionary SetAnnotation(int annotationIndex) { + return Put(PdfName.A, new PdfNumber(annotationIndex)); } - /// Sets the text value, which specifies the value of the /NM entry in the annotation dictionary. - /// - /// + /// + /// Sets the text value, which uniquely identifies an annotation (/NM entry) in an annotation dictionary + /// for the child target associated with a file attachment annotation. + /// + /// specifies the value of NM in the annotation dictionary of the target annotation + /// + /// this object wrapper public virtual iText.Kernel.Pdf.Action.PdfTargetDictionary SetAnnotation(String annotationName) { return Put(PdfName.A, new PdfString(annotationName)); } + /// Gets the object in the /A entry of the underlying object. + /// + /// Gets the object in the /A entry of the underlying object. If the value is an integer, + /// it specifies the index (zero-based) of the annotation in the Annots array of the page specified by P. + /// If the value is a text string, it specifies the value of NM in the annotation dictionary. + /// + /// the /A entry in the target object public virtual PdfObject GetAnnotation() { return GetPdfObject().Get(PdfName.A); } /// Sets a target dictionary specifying additional path information to the target document. - /// - /// + /// + /// Sets a target dictionary specifying additional path information to the target document. + /// If this entry is absent, the current document is the target file containing the destination. + /// + /// the additional path target dictionary + /// this object wrapper public virtual iText.Kernel.Pdf.Action.PdfTargetDictionary SetTarget(iText.Kernel.Pdf.Action.PdfTargetDictionary target) { return Put(PdfName.T, target.GetPdfObject()); } + /// Get a target dictionary specifying additional path information to the target document. + /// + /// Get a target dictionary specifying additional path information to the target document. + /// If the current target object is the final node in the target path, null is returned. + /// + /// a target dictionary specifying additional path information to the target document public virtual iText.Kernel.Pdf.Action.PdfTargetDictionary GetTarget() { - return new iText.Kernel.Pdf.Action.PdfTargetDictionary(GetPdfObject().GetAsDictionary(PdfName.T)); + PdfDictionary targetDictObject = GetPdfObject().GetAsDictionary(PdfName.T); + return targetDictObject != null ? new iText.Kernel.Pdf.Action.PdfTargetDictionary(targetDictObject) : null; } + /// + /// This is a convenient method to put key-value pairs to the underlying + /// + /// . + /// + /// + /// the key, a + /// + /// instance + /// + /// the value + /// this object wrapper public virtual iText.Kernel.Pdf.Action.PdfTargetDictionary Put(PdfName key, PdfObject value) { GetPdfObject().Put(key, value); return this; } + /// protected internal override bool IsWrappedObjectMustBeIndirect() { return false; } diff --git a/itext/itext.kernel/itext/kernel/pdf/action/PdfWin.cs b/itext/itext.kernel/itext/kernel/pdf/action/PdfWin.cs index 985489c02b..31f5eafc60 100644 --- a/itext/itext.kernel/itext/kernel/pdf/action/PdfWin.cs +++ b/itext/itext.kernel/itext/kernel/pdf/action/PdfWin.cs @@ -44,16 +44,40 @@ source product. using iText.Kernel.Pdf; namespace iText.Kernel.Pdf.Action { + /// This class is a wrapper around a Windows launch parameter dictionary. public class PdfWin : PdfObjectWrapper { + /// Creates a new wrapper around an existing Windows launch parameter dictionary. + /// the dictionary to create a wrapper for public PdfWin(PdfDictionary pdfObject) : base(pdfObject) { } + /// Creates a new wrapper around a newly created Windows launch parameter dictionary. + /// + /// the file name of the application that shall be launched or the document that shall be opened or printed, + /// in standard Windows pathname format. If the name string includes a backslash character (\), + /// the backslash shall itself be preceded by a backslash. + /// public PdfWin(PdfString f) : this(new PdfDictionary()) { GetPdfObject().Put(PdfName.F, f); } + /// Creates a new wrapper around a newly created Windows launch parameter dictionary. + /// + /// the file name of the application that shall be launched or the document that shall be opened or printed, + /// in standard Windows pathname format. If the name string includes a backslash character (\), + /// the backslash shall itself be preceded by a backslash + /// + /// a bye string specifying the default directory in standard DOS syntax + /// + /// an ASCII string specifying the operation to perform on the file. Shall be one of the following: + /// "open", "print" + /// + /// + /// a parameter string that shall be passed to the application. + /// This entry shall be omitted if a document is abound to be opened + /// public PdfWin(PdfString f, PdfString d, PdfString o, PdfString p) : this(new PdfDictionary()) { GetPdfObject().Put(PdfName.F, f); @@ -62,6 +86,7 @@ public PdfWin(PdfString f, PdfString d, PdfString o, PdfString p) GetPdfObject().Put(PdfName.P, p); } + /// protected internal override bool IsWrappedObjectMustBeIndirect() { return false; } diff --git a/itext/itext.kernel/itext/kernel/pdf/annot/PdfAnnotation.cs b/itext/itext.kernel/itext/kernel/pdf/annot/PdfAnnotation.cs index 7c728ce764..12d4b2d1a6 100644 --- a/itext/itext.kernel/itext/kernel/pdf/annot/PdfAnnotation.cs +++ b/itext/itext.kernel/itext/kernel/pdf/annot/PdfAnnotation.cs @@ -49,74 +49,290 @@ source product. using iText.Kernel.Pdf.Layer; namespace iText.Kernel.Pdf.Annot { + /// This is a super class for the annotation dictionary wrappers. + /// + /// This is a super class for the annotation dictionary wrappers. Derived classes represent + /// different standard types of annotations. See ISO-320001 12.5.6, “Annotation Types.” + /// public abstract class PdfAnnotation : PdfObjectWrapper { - /// Annotation flags. + /// Annotation flag. + /// + /// Annotation flag. + /// See also + /// + /// and ISO-320001, table 165. + /// public const int INVISIBLE = 1; + /// Annotation flag. + /// + /// Annotation flag. + /// See also + /// + /// and ISO-320001, table 165. + /// public const int HIDDEN = 2; + /// Annotation flag. + /// + /// Annotation flag. + /// See also + /// + /// and ISO-320001, table 165. + /// public const int PRINT = 4; + /// Annotation flag. + /// + /// Annotation flag. + /// See also + /// + /// and ISO-320001, table 165. + /// public const int NO_ZOOM = 8; + /// Annotation flag. + /// + /// Annotation flag. + /// See also + /// + /// and ISO-320001, table 165. + /// public const int NO_ROTATE = 16; + /// Annotation flag. + /// + /// Annotation flag. + /// See also + /// + /// and ISO-320001, table 165. + /// public const int NO_VIEW = 32; + /// Annotation flag. + /// + /// Annotation flag. + /// See also + /// + /// and ISO-320001, table 165. + /// public const int READ_ONLY = 64; + /// Annotation flag. + /// + /// Annotation flag. + /// See also + /// + /// and ISO-320001, table 165. + /// public const int LOCKED = 128; + /// Annotation flag. + /// + /// Annotation flag. + /// See also + /// + /// and ISO-320001, table 165. + /// public const int TOGGLE_NO_VIEW = 256; + /// Annotation flag. + /// + /// Annotation flag. + /// See also + /// + /// and ISO-320001, table 165. + /// public const int LOCKED_CONTENTS = 512; - /// Annotation highlighting modes. + /// Widget annotation highlighting mode. + /// + /// Widget annotation highlighting mode. See ISO-320001, Table 188 (H key). + /// Also see + /// + /// . + /// public static readonly PdfName HIGHLIGHT_NONE = PdfName.N; + /// Widget annotation highlighting mode. + /// + /// Widget annotation highlighting mode. See ISO-320001, Table 188 (H key). + /// Also see + /// + /// . + /// public static readonly PdfName HIGHLIGHT_INVERT = PdfName.I; + /// Widget annotation highlighting mode. + /// + /// Widget annotation highlighting mode. See ISO-320001, Table 188 (H key). + /// Also see + /// + /// . + /// public static readonly PdfName HIGHLIGHT_OUTLINE = PdfName.O; + /// Widget annotation highlighting mode. + /// + /// Widget annotation highlighting mode. See ISO-320001, Table 188 (H key). + /// Also see + /// + /// . + /// public static readonly PdfName HIGHLIGHT_PUSH = PdfName.P; + /// Widget annotation highlighting mode. + /// + /// Widget annotation highlighting mode. See ISO-320001, Table 188 (H key). + /// Also see + /// + /// . + /// public static readonly PdfName HIGHLIGHT_TOGGLE = PdfName.T; - /// Annotation highlighting modes. + /// Annotation border style. + /// + /// Annotation border style. See ISO-320001, Table 166 (S key). + /// Also see + /// + /// public static readonly PdfName STYLE_SOLID = PdfName.S; + /// Annotation border style. + /// + /// Annotation border style. See ISO-320001, Table 166 (S key). + /// Also see + /// + /// public static readonly PdfName STYLE_DASHED = PdfName.D; + /// Annotation border style. + /// + /// Annotation border style. See ISO-320001, Table 166 (S key). + /// Also see + /// + /// public static readonly PdfName STYLE_BEVELED = PdfName.B; + /// Annotation border style. + /// + /// Annotation border style. See ISO-320001, Table 166 (S key). + /// Also see + /// + /// public static readonly PdfName STYLE_INSET = PdfName.I; + /// Annotation border style. + /// + /// Annotation border style. See ISO-320001, Table 166 (S key). + /// Also see + /// + /// public static readonly PdfName STYLE_UNDERLINE = PdfName.U; - /// Annotation states. + /// Annotation state. + /// + /// Annotation state. See ISO-320001 12.5.6.3 "Annotation States" and Table 171 in particular. + /// Also see + /// + /// . + /// public static readonly PdfString Marked = new PdfString("Marked"); + /// Annotation state. + /// + /// Annotation state. See ISO-320001 12.5.6.3 "Annotation States" and Table 171 in particular. + /// Also see + /// + /// . + /// public static readonly PdfString Unmarked = new PdfString("Unmarked"); + /// Annotation state. + /// + /// Annotation state. See ISO-320001 12.5.6.3 "Annotation States" and Table 171 in particular. + /// Also see + /// + /// . + /// public static readonly PdfString Accepted = new PdfString("Accepted"); + /// Annotation state. + /// + /// Annotation state. See ISO-320001 12.5.6.3 "Annotation States" and Table 171 in particular. + /// Also see + /// + /// . + /// public static readonly PdfString Rejected = new PdfString("Rejected"); + /// Annotation state. + /// + /// Annotation state. See ISO-320001 12.5.6.3 "Annotation States" and Table 171 in particular. + /// Also see + /// + /// . + /// public static readonly PdfString Canceled = new PdfString("Cancelled"); + /// Annotation state. + /// + /// Annotation state. See ISO-320001 12.5.6.3 "Annotation States" and Table 171 in particular. + /// Also see + /// + /// . + /// public static readonly PdfString Completed = new PdfString("Completed"); + /// Annotation state. + /// + /// Annotation state. See ISO-320001 12.5.6.3 "Annotation States" and Table 171 in particular. + /// Also see + /// + /// . + /// public static readonly PdfString None = new PdfString("None"); - /// Annotation state models. + /// Annotation state model. + /// + /// Annotation state model. See ISO-320001, Table 172 (StateModel key). + /// Also see + /// + /// . + /// public static readonly PdfString MarkedModel = new PdfString("Marked"); + /// Annotation state model. + /// + /// Annotation state model. See ISO-320001, Table 172 (StateModel key). + /// Also see + /// + /// . + /// public static readonly PdfString ReviewModel = new PdfString("Review"); protected internal PdfPage page; - public static iText.Kernel.Pdf.Annot.PdfAnnotation MakeAnnotation(PdfObject pdfObject, iText.Kernel.Pdf.Annot.PdfAnnotation - parent) { + /// + /// Factory method that creates the type specific + /// + /// from the given + /// + /// that represents annotation object. This method is useful for property reading in reading mode or + /// modifying in stamping mode. See derived classes of this class to see possible specific annotation types + /// created. + /// + /// + /// a + /// + /// that represents annotation in the document. + /// + /// + /// created + /// + /// . + /// + public static iText.Kernel.Pdf.Annot.PdfAnnotation MakeAnnotation(PdfObject pdfObject) { iText.Kernel.Pdf.Annot.PdfAnnotation annotation = null; if (pdfObject.IsIndirectReference()) { pdfObject = ((PdfIndirectReference)pdfObject).GetRefersTo(); @@ -229,17 +445,40 @@ public static iText.Kernel.Pdf.Annot.PdfAnnotation MakeAnnotation(PdfObject pdfO } } } - if (annotation is PdfMarkupAnnotation) { - PdfMarkupAnnotation markup = (PdfMarkupAnnotation)annotation; - PdfDictionary inReplyTo = markup.GetInReplyToObject(); - if (inReplyTo != null) { - markup.SetInReplyTo(MakeAnnotation(inReplyTo)); - } - PdfDictionary popup = markup.GetPopupObject(); - if (popup != null) { - markup.SetPopup((PdfPopupAnnotation)MakeAnnotation(popup, markup)); - } - } + return annotation; + } + + /// + /// Factory method that creates the type specific + /// + /// from the given + /// + /// that represents annotation object. This method is useful for property reading in reading mode or + /// modifying in stamping mode. + /// + /// + /// a + /// + /// that represents annotation in the document. + /// + /// + /// parent annotation of the + /// + /// to be created. This parameter is + /// only needed if passed + /// + /// represents a pop-up annotation in the document. + /// + /// + /// created + /// + /// . + /// + [System.ObsoleteAttribute(@"This method will be removed in iText 7.1. Please, simply use MakeAnnotation(iText.Kernel.Pdf.PdfObject) ." + )] + public static iText.Kernel.Pdf.Annot.PdfAnnotation MakeAnnotation(PdfObject pdfObject, iText.Kernel.Pdf.Annot.PdfAnnotation + parent) { + iText.Kernel.Pdf.Annot.PdfAnnotation annotation = MakeAnnotation(pdfObject); if (annotation is PdfPopupAnnotation) { PdfPopupAnnotation popup = (PdfPopupAnnotation)annotation; if (parent != null) { @@ -260,6 +499,13 @@ protected internal PdfAnnotation(PdfDictionary pdfObject) MarkObjectAsIndirect(GetPdfObject()); } + /// + /// Gets a + /// + /// which value is a subtype of this annotation. + /// See ISO-320001 12.5.6, “Annotation Types” for the reference to the possible types. + /// + /// subtype of this annotation. public abstract PdfName GetSubtype(); /// Sets the layer this annotation belongs to. @@ -268,56 +514,242 @@ public virtual void SetLayer(IPdfOCG layer) { GetPdfObject().Put(PdfName.OC, layer.GetIndirectReference()); } + /// + /// Sets a + /// + /// to this annotation which will be performed when the annotation is activated. + /// + /// + /// + /// + /// to set to this annotation. + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfAnnotation SetAction(PdfAction action) { return Put(PdfName.A, action.GetPdfObject()); } + /// + /// Sets an additional + /// + /// to this annotation which will be performed in response to + /// the specific trigger event defined by + /// + /// . See ISO-320001 12.6.3, "Trigger Events". + /// + /// + /// a + /// + /// that denotes a type of the additional action to set. + /// + /// + /// + /// + /// to set as additional to this annotation. + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfAnnotation SetAdditionalAction(PdfName key, PdfAction action) { PdfAction.SetAdditionalAction(this, key, action); return this; } + /// + /// Gets the text that shall be displayed for the annotation or, if this type of annotation does not display text, + /// an alternate description of the annotation’s contents in human-readable form. + /// + /// annotation text content. public virtual PdfString GetContents() { return GetPdfObject().GetAsString(PdfName.Contents); } + /// + /// Sets the text that shall be displayed for the annotation or, if this type of annotation does not display text, + /// an alternate description of the annotation’s contents in human-readable form. + /// + /// + /// a + /// + /// containing text content to be set to the annotation. + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfAnnotation SetContents(PdfString contents) { return Put(PdfName.Contents, contents); } + /// + /// Sets the text that shall be displayed for the annotation or, if this type of annotation does not display text, + /// an alternate description of the annotation’s contents in human-readable form. + /// + /// + /// a java + /// + /// containing text content to be set to the annotation. + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfAnnotation SetContents(String contents) { return SetContents(new PdfString(contents)); } + /// + /// Gets a + /// + /// that represents a page of the document on which annotation is placed, + /// i.e. which has this annotation in it's /Annots array. + /// + /// + /// + /// + /// that is a page pdf object or null if annotation is not added to the page yet. + /// public virtual PdfDictionary GetPageObject() { return GetPdfObject().GetAsDictionary(PdfName.P); } + /// + /// Gets a + /// + /// on which annotation is placed. + /// + /// + /// + /// + /// on which annotation is placed or null if annotation is not placed yet. + /// public virtual PdfPage GetPage() { + if (page == null && GetPdfObject().IsIndirect()) { + PdfIndirectReference annotationIndirectReference = GetPdfObject().GetIndirectReference(); + PdfDocument doc = annotationIndirectReference.GetDocument(); + PdfDictionary pageDictionary = GetPageObject(); + if (pageDictionary != null) { + page = doc.GetPage(pageDictionary); + } + else { + for (int i = 1; i <= doc.GetNumberOfPages(); i++) { + PdfPage docPage = doc.GetPage(i); + foreach (iText.Kernel.Pdf.Annot.PdfAnnotation annot in docPage.GetAnnotations()) { + if (annot.GetPdfObject().GetIndirectReference().Equals(annotationIndirectReference)) { + page = docPage; + break; + } + } + } + } + } return page; } + /// Method that modifies annotation page property, which defines to which page annotation belongs. + /// + /// Method that modifies annotation page property, which defines to which page annotation belongs. + /// Keep in mind that this doesn't actually add an annotation to the page, + /// it should be done via + /// + /// . + /// Also you don't need to set this property manually, this is done automatically on addition to the page. + /// + /// + /// the + /// + /// to which annotation will be added. + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfAnnotation SetPage(PdfPage page) { this.page = page; return Put(PdfName.P, page.GetPdfObject()); } + /// + /// Gets the annotation name, a text string uniquely identifying it among all the + /// annotations on its page. + /// + /// + /// a + /// + /// with annotation name as it's value or null if name + /// is not specified. + /// public virtual PdfString GetName() { return GetPdfObject().GetAsString(PdfName.NM); } + /// + /// Sets the annotation name, a text string uniquely identifying it among all the + /// annotations on its page. + /// + /// + /// a + /// + /// to be set as annotation name. + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfAnnotation SetName(PdfString name) { return Put(PdfName.NM, name); } + /// The date and time when the annotation was most recently modified. + /// + /// The date and time when the annotation was most recently modified. + /// This is an optional property of the annotation. + /// + /// + /// a + /// + /// with the modification date as it's value or null if date is not specified. + /// public virtual PdfString GetDate() { return GetPdfObject().GetAsString(PdfName.M); } + /// The date and time when the annotation was most recently modified. + /// + /// a + /// + /// with date. The format should be a date string as described + /// in ISO-320001 7.9.4, “Dates”. + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfAnnotation SetDate(PdfString date) { return Put(PdfName.M, date); } + /// A set of flags specifying various characteristics of the annotation (see ISO-320001 12.5.3, “Annotation Flags”). + /// + /// + /// A set of flags specifying various characteristics of the annotation (see ISO-320001 12.5.3, “Annotation Flags”). + /// For specific annotation flag constants see + /// + /// . + /// Default value: 0. + /// + /// an integer interpreted as one-bit flags specifying various characteristics of the annotation. public virtual int GetFlags() { PdfNumber f = GetPdfObject().GetAsNumber(PdfName.F); if (f != null) { @@ -328,51 +760,273 @@ public virtual int GetFlags() { } } + /// Sets a set of flags specifying various characteristics of the annotation (see ISO-320001 12.5.3, “Annotation Flags”). + /// + /// + /// Sets a set of flags specifying various characteristics of the annotation (see ISO-320001 12.5.3, “Annotation Flags”). + /// On the contrary from + /// + /// , this method sets a complete set of enabled and disabled flags at once. + /// If not set specifically the default value is 0. + /// + /// an integer interpreted as set of one-bit flags specifying various characteristics of the annotation. + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfAnnotation SetFlags(int flags) { return Put(PdfName.F, new PdfNumber(flags)); } + /// Sets a flag that specifies a characteristic of the annotation to enabled state (see ISO-320001 12.5.3, “Annotation Flags”). + /// + /// + /// Sets a flag that specifies a characteristic of the annotation to enabled state (see ISO-320001 12.5.3, “Annotation Flags”). + /// On the contrary from + /// + /// , this method sets only specified flags to enabled state, + /// but doesn't disable other flags. + /// Possible flags: + ///
      + ///
    • + /// + /// - If set, do not display the annotation if it does not belong to one of the + /// standard annotation types and no annotation handler is available. If clear, display such unknown annotation + /// using an appearance stream specified by its appearance dictionary, if any. + ///
    • + ///
    • + /// + /// - If set, do not display or print the annotation or allow it to interact with + /// the user, regardless of its annotation type or whether an annotation handler is available. + ///
    • + ///
    • + /// + /// - If set, print the annotation when the page is printed. If clear, never print + /// the annotation, regardless of whether it is displayed on the screen. + ///
    • + ///
    • + /// + /// - If set, do not scale the annotation’s appearance to match the magnification of + /// the page. The location of the annotation on the page (defined by the upper-left corner of its annotation + /// rectangle) shall remain fixed, regardless of the page magnification.} + ///
    • + ///
    • + /// + /// - If set, do not rotate the annotation’s appearance to match the rotation + /// of the page. The upper-left corner of the annotation rectangle shall remain in a fixed location on the page, + /// regardless of the page rotation. + ///
    • + ///
    • + /// + /// - If set, do not display the annotation on the screen or allow it to interact + /// with the user. The annotation may be printed (depending on the setting of the Print flag) but should be considered + /// hidden for purposes of on-screen display and user interaction. + ///
    • + ///
    • + /// + /// - If set, do not allow the annotation to interact with the user. The annotation + /// may be displayed or printed (depending on the settings of the NoView and Print flags) but should not respond to mouse + /// clicks or change its appearance in response to mouse motions. + ///
    • + ///
    • + /// + /// - If set, do not allow the annotation to be deleted or its properties + /// (including position and size) to be modified by the user. However, this flag does not restrict changes to + /// the annotation’s contents, such as the value of a form field. + ///
    • + ///
    • + /// + /// - If set, invert the interpretation of the NoView flag for certain events. + ///
    • + ///
    • + /// + /// - If set, do not allow the contents of the annotation to be modified + /// by the user. This flag does not restrict deletion of the annotation or changes to other annotation properties, + /// such as position and size. + ///
    • + ///
    + ///
    + /// - an integer interpreted as set of one-bit flags which will be enabled for this annotation. + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfAnnotation SetFlag(int flag) { int flags = GetFlags(); flags = flags | flag; return SetFlags(flags); } + /// Resets a flag that specifies a characteristic of the annotation to disabled state (see ISO-320001 12.5.3, “Annotation Flags”). + /// + /// an integer interpreted as set of one-bit flags which will be reset to disabled state. + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfAnnotation ResetFlag(int flag) { int flags = GetFlags(); - flags = flags & (~flag & 0xff); + flags = flags & ~flag; return SetFlags(flags); } + /// + /// Checks if the certain flag that specifies a characteristic of the annotation + /// is in enabled state (see ISO-320001 12.5.3, “Annotation Flags”). + /// + /// + /// Checks if the certain flag that specifies a characteristic of the annotation + /// is in enabled state (see ISO-320001 12.5.3, “Annotation Flags”). + /// This method allows only one flag to be checked at once, use constants listed in + /// + /// . + /// + /// + /// an integer interpreted as set of one-bit flags. Only one bit must be set in this integer, otherwise + /// exception is thrown. + /// + /// true if the given flag is in enabled state. public virtual bool HasFlag(int flag) { + if (flag == 0) { + return false; + } + if ((flag & flag - 1) != 0) { + throw new ArgumentException("Only one flag must be checked at once."); + } int flags = GetFlags(); return (flags & flag) != 0; } + /// + /// An appearance dictionary specifying how the annotation shall be presented visually on the page during its + /// interactions with the user (see ISO-320001 12.5.5, “Appearance Streams”). + /// + /// + /// An appearance dictionary specifying how the annotation shall be presented visually on the page during its + /// interactions with the user (see ISO-320001 12.5.5, “Appearance Streams”). An appearance dictionary is a dictionary + /// containing one or several appearance streams or subdictionaries. + /// + /// + /// an appearance + /// + /// or null if it is not specified. + /// public virtual PdfDictionary GetAppearanceDictionary() { return GetPdfObject().GetAsDictionary(PdfName.AP); } + /// Specific appearance object corresponding to the specific appearance type. + /// + /// Specific appearance object corresponding to the specific appearance type. This object might be either an appearance + /// stream or an appearance subdictionary. In the latter case, the subdictionary defines multiple appearance streams + /// corresponding to different appearance states of the annotation. See ISO-320001 12.5.5, “Appearance Streams”. + /// + /// + /// a + /// + /// specifying appearance type. Possible types are + /// Normal + /// , + /// Rollover + /// and + /// Down + /// . + /// + /// + /// null if their is no such appearance type or an appearance object which might be either + /// an appearance stream or an appearance subdictionary. + /// public virtual PdfDictionary GetAppearanceObject(PdfName appearanceType) { PdfDictionary ap = GetAppearanceDictionary(); if (ap != null) { - return ap.GetAsDictionary(appearanceType); + PdfObject apObject = ap.Get(appearanceType); + if (apObject is PdfDictionary) { + return (PdfDictionary)apObject; + } } return null; } + /// The normal appearance is used when the annotation is not interacting with the user. + /// + /// The normal appearance is used when the annotation is not interacting with the user. + /// This appearance is also used for printing the annotation. + /// See also + /// + /// . + /// + /// an appearance object which might be either an appearance stream or an appearance subdictionary. public virtual PdfDictionary GetNormalAppearanceObject() { return GetAppearanceObject(PdfName.N); } + /// + /// The rollover appearance is used when the user moves the cursor into the annotation’s active area + /// without pressing the mouse button. + /// + /// + /// The rollover appearance is used when the user moves the cursor into the annotation’s active area + /// without pressing the mouse button. If not specified normal appearance is used. + /// See also + /// + /// . + /// + /// + /// null if rollover appearance is not specified or an appearance object which might be either + /// an appearance stream or an appearance subdictionary. + /// public virtual PdfDictionary GetRolloverAppearanceObject() { return GetAppearanceObject(PdfName.R); } + /// The down appearance is used when the mouse button is pressed or held down within the annotation’s active area. + /// + /// + /// The down appearance is used when the mouse button is pressed or held down within the annotation’s active area. + /// If not specified normal appearance is used. + /// See also + /// + /// . + /// + /// + /// null if down appearance is not specified or an appearance object which might be either + /// an appearance stream or an appearance subdictionary. + /// public virtual PdfDictionary GetDownAppearanceObject() { return GetAppearanceObject(PdfName.D); } + /// Sets a specific type of the appearance. + /// + /// Sets a specific type of the appearance. See + /// + /// and + /// + /// for more info. + /// + /// + /// a + /// + /// specifying appearance type. Possible types are + /// Normal + /// , + /// Rollover + /// and + /// Down + /// . + /// + /// an appearance object which might be either an appearance stream or an appearance subdictionary. + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfAnnotation SetAppearance(PdfName appearanceType, PdfDictionary appearance ) { PdfDictionary ap = GetAppearanceDictionary(); @@ -384,69 +1038,345 @@ public virtual iText.Kernel.Pdf.Annot.PdfAnnotation SetAppearance(PdfName appear return this; } + /// Sets normal appearance. + /// + /// Sets normal appearance. See + /// + /// and + /// + /// for more info. + /// + /// an appearance object which might be either an appearance stream or an appearance subdictionary. + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfAnnotation SetNormalAppearance(PdfDictionary appearance) { return SetAppearance(PdfName.N, appearance); } + /// Sets rollover appearance. + /// + /// Sets rollover appearance. See + /// + /// and + /// + /// for more info. + /// + /// an appearance object which might be either an appearance stream or an appearance subdictionary. + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfAnnotation SetRolloverAppearance(PdfDictionary appearance) { return SetAppearance(PdfName.R, appearance); } + /// Sets down appearance. + /// + /// Sets down appearance. See + /// + /// and + /// + /// for more info. + /// + /// an appearance object which might be either an appearance stream or an appearance subdictionary. + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfAnnotation SetDownAppearance(PdfDictionary appearance) { return SetAppearance(PdfName.D, appearance); } + /// + /// Sets a specific type of the appearance using + /// + /// wrapper. + /// This method is used to set only an appearance subdictionary. See + /// + /// and + /// + /// for more info. + /// + /// + /// a + /// + /// specifying appearance type. Possible types are + /// Normal + /// , + /// Rollover + /// and + /// Down + /// . + /// + /// + /// an appearance subdictionary wrapped in + /// + /// . + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfAnnotation SetAppearance(PdfName appearanceType, PdfAnnotationAppearance appearance) { return SetAppearance(appearanceType, appearance.GetPdfObject()); } + /// + /// Sets normal appearance using + /// + /// wrapper. This method is used to set only + /// appearance subdictionary. See + /// + /// and + /// + /// for more info. + /// + /// + /// an appearance subdictionary wrapped in + /// + /// . + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfAnnotation SetNormalAppearance(PdfAnnotationAppearance appearance ) { return SetAppearance(PdfName.N, appearance); } + /// + /// Sets rollover appearance using + /// + /// wrapper. This method is used to set only + /// appearance subdictionary. See + /// + /// and + /// + /// for more info. + /// + /// + /// an appearance subdictionary wrapped in + /// + /// . + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfAnnotation SetRolloverAppearance(PdfAnnotationAppearance appearance ) { return SetAppearance(PdfName.R, appearance); } + /// + /// Sets down appearance using + /// + /// wrapper. This method is used to set only + /// appearance subdictionary. See + /// + /// and + /// + /// for more info. + /// + /// + /// an appearance subdictionary wrapped in + /// + /// . + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfAnnotation SetDownAppearance(PdfAnnotationAppearance appearance) { return SetAppearance(PdfName.D, appearance); } + /// + /// The annotation’s appearance state, which selects the applicable appearance stream + /// from an appearance subdictionary if there is such. + /// + /// + /// The annotation’s appearance state, which selects the applicable appearance stream + /// from an appearance subdictionary if there is such. See + /// + /// for more info. + /// + /// + /// a + /// + /// which defines selected appearance state. + /// public virtual PdfName GetAppearanceState() { return GetPdfObject().GetAsName(PdfName.AS); } + /// + /// Sets the annotation’s appearance state, which selects the applicable appearance stream + /// from an appearance subdictionary. + /// + /// + /// Sets the annotation’s appearance state, which selects the applicable appearance stream + /// from an appearance subdictionary. See + /// + /// for more info. + /// + /// + /// a + /// + /// which defines appearance state to be selected. + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfAnnotation SetAppearanceState(PdfName @as) { return Put(PdfName.AS, @as); } + /// + ///

    + /// An array specifying the characteristics of the annotation’s border. + ///

    + /// + ///

    + /// An array specifying the characteristics of the annotation’s border. + /// The array consists of three numbers defining the horizontal corner radius, + /// vertical corner radius, and border width, all in default user space units. + /// If the corner radii are 0, the border has square (not rounded) corners; if + /// the border width is 0, no border is drawn. + ///

    + /// The array may have a fourth element, an optional dash array (see ISO-320001 8.4.3.6, “Line Dash Pattern”). + /// + /// + /// an + /// + /// specifying the characteristics of the annotation’s border. + /// public virtual PdfArray GetBorder() { return GetPdfObject().GetAsArray(PdfName.Border); } + ///

    Sets the characteristics of the annotation’s border. + /// + /// an + /// + /// specifying the characteristics of the annotation’s border. + /// See + /// + /// for more detailes. + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfAnnotation SetBorder(PdfArray border) { return Put(PdfName.Border, border); } + /// + /// An array of numbers in the range 0.0 to 1.0, representing a colour used for the following purposes: + ///
      + ///
    • The background of the annotation’s icon when closed
    • + ///
    • The title bar of the annotation’s pop-up window
    • + ///
    • The border of a link annotation
    • + ///
    + /// The number of array elements determines the colour space in which the colour shall be defined: + ///
      + ///
    • 0 - No colour; transparent
    • + ///
    • 1 - DeviceGray
    • + ///
    • 3 - DeviceRGB
    • + ///
    • 4 - DeviceCMYK
    • + ///
    + ///
    + /// An array of numbers in the range 0.0 to 1.0, representing an annotation colour. public virtual PdfArray GetColorObject() { return GetPdfObject().GetAsArray(PdfName.C); } + /// Sets an annotation color. + /// + /// Sets an annotation color. For more details on annotation color purposes and the format + /// of the passing + /// + /// see + /// + /// . + /// + /// an array of numbers in the range 0.0 to 1.0, specifying color. + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfAnnotation SetColor(PdfArray color) { return Put(PdfName.C, color); } + /// Sets an annotation color. + /// + /// Sets an annotation color. For more details on annotation color purposes and the format + /// of the passing array see + /// + /// . + /// + /// an array of numbers in the range 0.0 to 1.0, specifying color. + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfAnnotation SetColor(float[] color) { return SetColor(new PdfArray(color)); } + /// Sets an annotation color. + /// + /// Sets an annotation color. For more details on annotation color purposes + /// see + /// + /// . + /// + /// + /// + /// + /// object of the either + /// + /// , + /// + /// or + /// + /// type. + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfAnnotation SetColor(Color color) { return SetColor(new PdfArray(color.GetColorValue())); } + /// + /// The integer key of the annotation’s entry in the structural parent tree + /// (see ISO-320001 14.7.4.4, “Finding Structure Elements from Content Items”). + /// + /// integer key in structural parent tree or -1 if annotation is not tagged. public virtual int GetStructParentIndex() { PdfNumber n = GetPdfObject().GetAsNumber(PdfName.StructParent); if (n == null) { @@ -457,34 +1387,136 @@ public virtual int GetStructParentIndex() { } } + /// + /// Sets he integer key of the annotation’s entry in the structural parent tree + /// (see ISO-320001 14.7.4.4, “Finding Structure Elements from Content Items”). + /// + /// + /// Sets he integer key of the annotation’s entry in the structural parent tree + /// (see ISO-320001 14.7.4.4, “Finding Structure Elements from Content Items”). + /// Note: Normally, there is no need to take care of this manually, struct parent index is set automatically + /// if annotation is added to the tagged document's page. + /// + /// + /// integer which is to be the key of the annotation's entry + /// in structural parent tree. + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfAnnotation SetStructParentIndex(int structParentIndex) { return Put(PdfName.StructParent, new PdfNumber(structParentIndex)); } - public virtual PdfArray GetQuadPoints() { - return GetPdfObject().GetAsArray(PdfName.QuadPoints); - } - + /// A flag specifying whether the annotation shall initially be displayed open. + /// + /// A flag specifying whether the annotation shall initially be displayed open. + /// This flag has affect to not all kinds of annotations. + /// + /// true if annotation is initially open, false - if closed. public virtual bool GetOpen() { PdfBoolean open = GetPdfObject().GetAsBoolean(PdfName.Open); return open != null && open.GetValue(); } + /// Sets a flag specifying whether the annotation shall initially be displayed open. + /// + /// Sets a flag specifying whether the annotation shall initially be displayed open. + /// This flag has affect to not all kinds of annotations. + /// + /// true if annotation shall initially be open, false - if closed. + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfAnnotation SetOpen(bool open) { return Put(PdfName.Open, new PdfBoolean(open)); } + /// An array of 8 × n numbers specifying the coordinates of n quadrilaterals in default user space. + /// + /// An array of 8 × n numbers specifying the coordinates of n quadrilaterals in default user space. + /// Quadrilaterals are used to define: + ///
      + ///
    • regions inside annotation rectangle in which the link annotation should be activated;
    • + ///
    • a word or group of contiguous words in the text underlying the text markup annotation;
    • + ///
    • the content region that is intended to be removed for a redaction annotation;
    • + ///
    + ///

    + /// IMPORTANT NOTE: According to Table 179 in ISO 32000-1, the QuadPoints array lists the vertices in counterclockwise + /// order and the text orientation is defined by the first and second vertex. This basically means QuadPoints is + /// specified as lower-left, lower-right, top-right, top-left. HOWEVER, Adobe's interpretation + /// (tested at least with Acrobat 10, Acrobat 11, Reader 11) is top-left, top-right, lower-left, lower-right (Z-shaped order). + /// This means that if the QuadPoints array is specified according to the standard, the rendering is not as expected. + /// Other viewers seem to follow Adobe's interpretation. Hence we recommend to use and expect QuadPoints array in Z-order, + /// just as Acrobat and probably most other viewers expect. + /// + /// + /// an + /// + /// of 8 × n numbers specifying the coordinates of n quadrilaterals. + /// + public virtual PdfArray GetQuadPoints() { + return GetPdfObject().GetAsArray(PdfName.QuadPoints); + } + + ///

    + /// Sets n quadrilaterals in default user space by passing an + /// + /// of 8 × n numbers. For more info of what + /// quadrilaterals define see + /// + /// . + ///

    + /// IMPORTANT NOTE: According to Table 179 in ISO 32000-1, the QuadPoints array lists the vertices in counterclockwise + /// order and the text orientation is defined by the first and second vertex. This basically means QuadPoints is + /// specified as lower-left, lower-right, top-right, top-left. HOWEVER, Adobe's interpretation + /// (tested at least with Acrobat 10, Acrobat 11, Reader 11) is top-left, top-right, lower-left, lower-right (Z-shaped order). + /// This means that if the QuadPoints array is specified according to the standard, the rendering is not as expected. + /// Other viewers seem to follow Adobe's interpretation. Hence we recommend to use and expect QuadPoints array in Z-order, + /// just as Acrobat and probably most other viewers expect. + ///

    + /// + /// an + /// + /// of 8 × n numbers specifying the coordinates of n quadrilaterals. + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfAnnotation SetQuadPoints(PdfArray quadPoints) { return Put(PdfName.QuadPoints, quadPoints); } + /// + /// Sets border style dictionary that has more settings than the array specified for the Border entry ( + /// + /// ). + /// See ISO-320001, Table 166 and + /// + /// for more info. + /// + /// + /// a border style dictionary specifying the line width and dash pattern that shall be used + /// in drawing the annotation’s border. + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfAnnotation SetBorderStyle(PdfDictionary borderStyle) { return Put(PdfName.BS, borderStyle); } - /// Setter for the annotation's border style. + /// Setter for the annotation's preset border style. /// - /// Setter for the annotation's border style. Possible values are + /// Setter for the annotation's preset border style. Possible values are ///
      ///
    • /// @@ -502,9 +1534,11 @@ public virtual iText.Kernel.Pdf.Annot.PdfAnnotation SetBorderStyle(PdfDictionary /// /// - A single line along the bottom of the annotation rectangle.
    • ///
    + /// See also ISO-320001, Table 166. ///
    /// The new value for the annotation's border style. /// The annotation which this method was called on. + /// public virtual iText.Kernel.Pdf.Annot.PdfAnnotation SetBorderStyle(PdfName style) { PdfDictionary styleDict = GetBorderStyle(); if (null == styleDict) { @@ -514,6 +1548,24 @@ public virtual iText.Kernel.Pdf.Annot.PdfAnnotation SetBorderStyle(PdfName style return SetBorderStyle(styleDict); } + /// Setter for the annotation's preset dashed border style. + /// + /// Setter for the annotation's preset dashed border style. This property has affect only if + /// + /// style was used for the annotation border style (see + /// + /// . + /// See ISO-320001 8.4.3.6, “Line Dash Pattern” for the format in which dash pattern shall be specified. + /// + /// + /// a dash array defining a pattern of dashes and gaps that + /// shall be used in drawing a dashed border. + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfAnnotation SetDashPattern(PdfArray dashPattern) { PdfDictionary styleDict = GetBorderStyle(); if (null == styleDict) { @@ -523,57 +1575,221 @@ public virtual iText.Kernel.Pdf.Annot.PdfAnnotation SetDashPattern(PdfArray dash return SetBorderStyle(styleDict); } + /// The dictionaries for some annotation types (such as free text and polygon annotations) can include the BS entry. + /// + /// + /// The dictionaries for some annotation types (such as free text and polygon annotations) can include the BS entry. + /// That entry specifies a border style dictionary that has more settings than the array specified for the Border + /// entry (see + /// + /// ). If an annotation dictionary includes the BS entry, then the Border + /// entry is ignored. If annotation includes AP (see + /// + /// ) it takes + /// precedence over the BS entry. For more info on BS entry see ISO-320001, Table 166. + /// + /// + /// + /// + /// which is a border style dictionary or null if it is not specified. + /// public virtual PdfDictionary GetBorderStyle() { return GetPdfObject().GetAsDictionary(PdfName.BS); } - public static iText.Kernel.Pdf.Annot.PdfAnnotation MakeAnnotation(PdfObject pdfObject) { - return MakeAnnotation(pdfObject, null); - } - + /// Sets annotation title. + /// Sets annotation title. This property affects not all annotation types. + /// + /// a + /// + /// which value is to be annotation title. + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfAnnotation SetTitle(PdfString title) { return Put(PdfName.T, title); } + /// Annotation title. + /// + /// Annotation title. For example for markup annotations, the title is the text label that shall be displayed in the + /// title bar of the annotation’s pop-up window when open and active. For movie annotation Movie actions + /// (ISO-320001 12.6.4.9, “Movie Actions”) may use this title to reference the movie annotation. + /// + /// + /// + /// + /// which value is an annotation title or null if it isn't specifed. + /// public virtual PdfString GetTitle() { return GetPdfObject().GetAsString(PdfName.T); } + /// + /// Sets an appearance characteristics dictionary containing additional information for constructing the + /// annotation’s appearance stream. + /// + /// + /// Sets an appearance characteristics dictionary containing additional information for constructing the + /// annotation’s appearance stream. See ISO-320001, Table 189. + /// This property affects + /// + /// and + /// + /// . + /// + /// + /// the + /// + /// with additional information for appearance stream. + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfAnnotation SetAppearanceCharacteristics(PdfDictionary characteristics ) { return Put(PdfName.MK, characteristics); } + /// + /// An appearance characteristics dictionary containing additional information for constructing the + /// annotation’s appearance stream. + /// + /// + /// An appearance characteristics dictionary containing additional information for constructing the + /// annotation’s appearance stream. See ISO-320001, Table 189. + /// This property affects + /// + /// and + /// + /// . + /// + /// an appearance characteristics dictionary or null if it isn't specified. public virtual PdfDictionary GetAppearanceCharacteristics() { return GetPdfObject().GetAsDictionary(PdfName.MK); } + /// + /// An + /// + /// to perform, such as launching an application, playing a sound, + /// changing an annotation’s appearance state etc, when the annotation is activated. + /// + /// + /// + /// + /// which defines the characteristics and behaviour of an action. + /// public virtual PdfDictionary GetAction() { return GetPdfObject().GetAsDictionary(PdfName.A); } + /// An additional actions dictionary that extends the set of events that can trigger the execution of an action. + /// + /// + /// An additional actions dictionary that extends the set of events that can trigger the execution of an action. + /// See ISO-320001 12.6.3 Trigger Events. + /// + /// + /// an additional actions + /// + /// . + /// + /// public virtual PdfDictionary GetAdditionalAction() { return GetPdfObject().GetAsDictionary(PdfName.AA); } + /// The annotation rectangle, defining the location of the annotation on the page in default user space units. + /// + /// + /// a + /// + /// which specifies a rectangle by two diagonally opposite corners. + /// Typically, the array is of form [llx lly urx ury]. + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfAnnotation SetRectangle(PdfArray array) { return Put(PdfName.Rect, array); } + /// The annotation rectangle, defining the location of the annotation on the page in default user space units. + /// + /// + /// a + /// + /// which specifies a rectangle by two diagonally opposite corners. + /// Typically, the array is of form [llx lly urx ury]. + /// public virtual PdfArray GetRectangle() { return GetPdfObject().GetAsArray(PdfName.Rect); } + /// + /// Inserts the value into into the underlying + /// + /// of this + /// + /// and associates it + /// with the specified key. If the key is already present in this + /// + /// , this method will override + /// the old value with the specified one. + /// + /// key to insert or to override + /// the value to associate with the specified key + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfAnnotation Put(PdfName key, PdfObject value) { GetPdfObject().Put(key, value); return this; } + /// + /// Removes the specified key from the underlying + /// + /// of this + /// + /// . + /// + /// key to be removed + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfAnnotation Remove(PdfName key) { GetPdfObject().Remove(key); return this; } + /// + /// To manually flush a + /// PdfObject + /// behind this wrapper, you have to ensure + /// that this object is added to the document, i.e. it has an indirect reference. + /// Basically this means that before flushing you need to explicitly call + /// + /// . + /// For example: wrapperInstance.makeIndirect(document).flush(); + /// Note that not every wrapper require this, only those that have such warning in documentation. + /// + public override void Flush() { + base.Flush(); + } + protected internal override bool IsWrappedObjectMustBeIndirect() { return true; } diff --git a/itext/itext.kernel/itext/kernel/pdf/annot/PdfLineAnnotation.cs b/itext/itext.kernel/itext/kernel/pdf/annot/PdfLineAnnotation.cs index 949da1e132..9bb987e724 100644 --- a/itext/itext.kernel/itext/kernel/pdf/annot/PdfLineAnnotation.cs +++ b/itext/itext.kernel/itext/kernel/pdf/annot/PdfLineAnnotation.cs @@ -41,96 +41,477 @@ source product. For more information, please contact iText Software Corp. at this address: sales@itextpdf.com */ +using System; using iText.Kernel.Geom; using iText.Kernel.Pdf; namespace iText.Kernel.Pdf.Annot { + /// The purpose of a line annotation is to display a single straight line on the page. + /// + /// The purpose of a line annotation is to display a single straight line on the page. + /// When opened, it displays a pop-up window containing the text of the associated note. + /// See also ISO-320001 12.5.6.7 "Line Annotations". + /// public class PdfLineAnnotation : PdfMarkupAnnotation { + /// + /// Creates a + /// + /// instance. + /// + /// + /// the annotation rectangle, defining the location of the annotation on the page + /// in default user space units. See + /// + /// . + /// + /// + /// an array of four numbers, [x1 y1 x2 y2], specifying the starting and ending coordinates + /// of the line in default user space. See also + /// + /// . + /// public PdfLineAnnotation(Rectangle rect, float[] line) : base(rect) { Put(PdfName.L, new PdfArray(line)); } - public PdfLineAnnotation(PdfDictionary pdfObject) - : base(pdfObject) { + /// + /// Creates a + /// + /// instance from the given + /// + /// that represents annotation object. This method is useful for property reading in reading mode or + /// modifying in stamping mode. + /// + /// + /// a + /// + /// that represents existing annotation in the document. + /// + public PdfLineAnnotation(PdfDictionary pdfDictionary) + : base(pdfDictionary) { } + /// public override PdfName GetSubtype() { return PdfName.Line; } + /// + /// An array of four numbers, [x1 y1 x2 y2], specifying the starting and ending coordinates of the line + /// in default user space. + /// + /// + /// An array of four numbers, [x1 y1 x2 y2], specifying the starting and ending coordinates of the line + /// in default user space. If the + /// + /// (see + /// + /// ) entry is present, this value represents + /// the endpoints of the leader lines rather than the endpoints of the line itself. + /// + /// An array of four numbers specifying the starting and ending coordinates of the line in default user space. + /// public virtual PdfArray GetLine() { return GetPdfObject().GetAsArray(PdfName.L); } + /// An array of two names specifying the line ending styles that is used in drawing the line. + /// + /// An array of two names specifying the line ending styles that is used in drawing the line. + /// The first and second elements of the array shall specify the line ending styles for the endpoints defined, + /// respectively, by the first and second pairs of coordinates, (x1, y1) and (x2, y2), in the + /// + /// array + /// (see + /// + /// . For possible values see + /// + /// . + /// + /// + /// An array of two names specifying the line ending styles that is used in drawing the line; or null if line + /// endings style is not explicitly defined, default value is [/None /None]. + /// public virtual PdfArray GetLineEndingStyles() { return GetPdfObject().GetAsArray(PdfName.LE); } + /// Sets the line ending styles that are used in drawing the line. + /// + /// Sets the line ending styles that are used in drawing the line. + /// The first and second elements of the array shall specify the line ending styles for the endpoints defined, + /// respectively, by the first and second pairs of coordinates, (x1, y1) and (x2, y2), in the + /// + /// array + /// (see + /// + /// . Possible values for styles are: + ///
      + ///
    • + /// + /// - A square filled with the annotation's interior color, if any;
    • + ///
    • + /// + /// - A circle filled with the annotation's interior color, if any;
    • + ///
    • + /// + /// - A diamond shape filled with the annotation's interior color, if any;
    • + ///
    • + /// + /// - Two short lines meeting in an acute angle to form an open arrowhead;
    • + ///
    • + /// + /// - Two short lines meeting in an acute angle as in the + /// + /// style and + /// connected by a third line to form a triangular closed arrowhead filled with the annotation's interior color, if any;
    • + ///
    • + /// + /// - No line ending;
    • + ///
    • + /// + /// - A short line at the endpoint perpendicular to the line itself;
    • + ///
    • + /// + /// - Two short lines in the reverse direction from + /// + /// ;
    • + ///
    • + /// + /// - A triangular closed arrowhead in the reverse direction from + /// + /// ;
    • + ///
    • + /// + /// - A short line at the endpoint approximately 30 degrees clockwise from perpendicular to the line itself;
    • + ///
    + /// see also ISO-320001, Table 176 "Line ending styles". + ///
    + /// An array of two names specifying the line ending styles that is used in drawing the line. + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfLineAnnotation SetLineEndingStyles(PdfArray lineEndingStyles) { return (iText.Kernel.Pdf.Annot.PdfLineAnnotation)Put(PdfName.LE, lineEndingStyles); } + /// + /// The length of leader lines in default user space that extend from each endpoint of the line perpendicular + /// to the line itself. + /// + /// + /// The length of leader lines in default user space that extend from each endpoint of the line perpendicular + /// to the line itself. A positive value means that the leader lines appear in the direction that is clockwise + /// when traversing the line from its starting point to its ending point (as specified by + /// + /// (see + /// + /// ); + /// a negative value indicates the opposite direction. + /// + /// a float specifying the length of leader lines in default user space. + [System.ObsoleteAttribute(@"use GetLeaderLineLength() instead.")] public virtual float GetLeaderLine() { - PdfNumber n = GetPdfObject().GetAsNumber(PdfName.LE); + PdfNumber n = GetPdfObject().GetAsNumber(PdfName.LL); return n == null ? 0 : n.FloatValue(); } + /// + /// Sets the length of leader lines in default user space that extend from each endpoint of the line perpendicular + /// to the line itself. + /// + /// + /// Sets the length of leader lines in default user space that extend from each endpoint of the line perpendicular + /// to the line itself. A positive value means that the leader lines appear in the direction that is clockwise + /// when traversing the line from its starting point to its ending point (as specified by + /// + /// (see + /// + /// ); + /// a negative value indicates the opposite direction. + /// + /// a float specifying the length of leader lines in default user space. + /// + /// this + /// + /// instance. + /// + [System.ObsoleteAttribute(@"use SetLeaderLineLength(float) instead.")] public virtual iText.Kernel.Pdf.Annot.PdfLineAnnotation SetLeaderLine(float leaderLine) { - return (iText.Kernel.Pdf.Annot.PdfLineAnnotation)Put(PdfName.LE, new PdfNumber(leaderLine)); + return (iText.Kernel.Pdf.Annot.PdfLineAnnotation)Put(PdfName.LL, new PdfNumber(leaderLine)); } + /// + /// The length of leader lines in default user space that extend from each endpoint of the line perpendicular + /// to the line itself. + /// + /// + /// The length of leader lines in default user space that extend from each endpoint of the line perpendicular + /// to the line itself. A positive value means that the leader lines appear in the direction that is clockwise + /// when traversing the line from its starting point to its ending point (as specified by + /// + /// (see + /// + /// ); + /// a negative value indicates the opposite direction. + /// + /// a float specifying the length of leader lines in default user space. + public virtual float GetLeaderLineLength() { + PdfNumber n = GetPdfObject().GetAsNumber(PdfName.LL); + return n == null ? 0 : n.FloatValue(); + } + + /// + /// Sets the length of leader lines in default user space that extend from each endpoint of the line perpendicular + /// to the line itself. + /// + /// + /// Sets the length of leader lines in default user space that extend from each endpoint of the line perpendicular + /// to the line itself. A positive value means that the leader lines appear in the direction that is clockwise + /// when traversing the line from its starting point to its ending point (as specified by + /// + /// (see + /// + /// ); + /// a negative value indicates the opposite direction. + /// + /// a float specifying the length of leader lines in default user space. + /// + /// this + /// + /// instance. + /// + public virtual iText.Kernel.Pdf.Annot.PdfLineAnnotation SetLeaderLineLength(float leaderLineLength) { + return (iText.Kernel.Pdf.Annot.PdfLineAnnotation)Put(PdfName.LL, new PdfNumber(leaderLineLength)); + } + + /// + /// A non-negative number that represents the length of leader line extensions that extend from the line proper + /// 180 degrees from the leader lines. + /// + /// + /// a non-negative float that represents the length of leader line extensions; or if the leader line extension + /// is not explicitly set, returns the default value, which is 0. + /// public virtual float GetLeaderLineExtension() { PdfNumber n = GetPdfObject().GetAsNumber(PdfName.LLE); return n == null ? 0 : n.FloatValue(); } + /// Sets the length of leader line extensions that extend from the line proper 180 degrees from the leader lines. + /// + /// + /// Sets the length of leader line extensions that extend from the line proper 180 degrees from the leader lines. + /// This value shall not be set unless + /// + /// (see + /// + /// ) is set. + /// + /// a non-negative float that represents the length of leader line extensions. + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfLineAnnotation SetLeaderLineExtension(float leaderLineExtension) { return (iText.Kernel.Pdf.Annot.PdfLineAnnotation)Put(PdfName.LLE, new PdfNumber(leaderLineExtension)); } + /// + /// A non-negative number that represents the length of the leader line offset, which is the amount of empty space + /// between the endpoints of the annotation and the beginning of the leader lines. + /// + /// + /// a non-negative number that represents the length of the leader line offset, + /// or null if leader line offset is not set. + /// public virtual float GetLeaderLineOffset() { PdfNumber n = GetPdfObject().GetAsNumber(PdfName.LLO); return n == null ? 0 : n.FloatValue(); } + /// + /// Sets the length of the leader line offset, which is the amount of empty space between the endpoints of the + /// annotation and the beginning of the leader lines. + /// + /// a non-negative number that represents the length of the leader line offset. + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfLineAnnotation SetLeaderLineOffset(float leaderLineOffset) { return (iText.Kernel.Pdf.Annot.PdfLineAnnotation)Put(PdfName.LLO, new PdfNumber(leaderLineOffset)); } + /// + /// If true, the text specified by the + /// + /// or + /// + /// entries + /// (see + /// + /// and + /// + /// ) + /// is replicated as a caption in the appearance of the line. + /// + /// + /// true, if the annotation text is replicated as a caption, false otherwise. If this property is + /// not set, default value is used which is false. + /// public virtual bool GetContentsAsCaption() { PdfBoolean b = GetPdfObject().GetAsBoolean(PdfName.Cap); return b != null && b.GetValue(); } + /// + /// If set to true, the text specified by the + /// + /// or + /// + /// entries + /// (see + /// + /// and + /// + /// ) + /// will be replicated as a caption in the appearance of the line. + /// + /// true, if the annotation text should be replicated as a caption, false otherwise. + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfLineAnnotation SetContentsAsCaption(bool contentsAsCaption) { return (iText.Kernel.Pdf.Annot.PdfLineAnnotation)Put(PdfName.Cap, new PdfBoolean(contentsAsCaption)); } + /// A name describing the annotation's caption positioning. + /// + /// A name describing the annotation's caption positioning. Valid values are + /// + /// , meaning the caption + /// is centered inside the line, and + /// + /// , meaning the caption is on top of the line. + /// + /// + /// a name describing the annotation's caption positioning, or null if the caption positioning is not + /// explicitly defined (in this case the default value is used, which is + /// + /// ). + /// public virtual PdfName GetCaptionPosition() { return GetPdfObject().GetAsName(PdfName.CP); } + /// Sets annotation's caption positioning. + /// + /// Sets annotation's caption positioning. Valid values are + /// + /// , meaning the caption + /// is centered inside the line, and + /// + /// , meaning the caption is on top of the line. + /// + /// a name describing the annotation's caption positioning. + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfLineAnnotation SetCaptionPosition(PdfName captionPosition) { return (iText.Kernel.Pdf.Annot.PdfLineAnnotation)Put(PdfName.CP, captionPosition); } + /// A measure dictionary (see ISO-320001, Table 261) that specifies the scale and units that apply to the line annotation. + /// + /// + /// a + /// + /// that represents a measure dictionary. + /// public virtual PdfDictionary GetMeasure() { return GetPdfObject().GetAsDictionary(PdfName.Measure); } + /// Sets a measure dictionary that specifies the scale and units that apply to the line annotation. + /// + /// a + /// + /// that represents a measure dictionary, see ISO-320001, Table 261 for valid + /// contents specification. + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfLineAnnotation SetMeasure(PdfDictionary measure) { return (iText.Kernel.Pdf.Annot.PdfLineAnnotation)Put(PdfName.Measure, measure); } + /// An array of two numbers that specifies the offset of the caption text from its normal position. + /// + /// An array of two numbers that specifies the offset of the caption text from its normal position. + /// The first value is the horizontal offset along the annotation line from its midpoint, with a positive value + /// indicating offset to the right and a negative value indicating offset to the left. The second value is the vertical + /// offset perpendicular to the annotation line, with a positive value indicating a shift up and a negative value indicating + /// a shift down. + /// + /// + /// a + /// + /// of two numbers that specifies the offset of the caption text from its normal position, + /// or null if caption offset is not explicitly specified (in this case a default value is used, which is [0, 0]). + /// public virtual PdfArray GetCaptionOffset() { return GetPdfObject().GetAsArray(PdfName.CO); } + /// Sets the offset of the caption text from its normal position. + /// + /// a + /// + /// of two numbers that specifies the offset of the caption text from its + /// normal position. The first value defines the horizontal offset along the annotation line from + /// its midpoint, with a positive value indicating offset to the right and a negative value indicating + /// offset to the left. The second value defines the vertical offset perpendicular to the annotation line, + /// with a positive value indicating a shift up and a negative value indicating a shift down. + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfLineAnnotation SetCaptionOffset(PdfArray captionOffset) { return (iText.Kernel.Pdf.Annot.PdfLineAnnotation)Put(PdfName.CO, captionOffset); } + /// Sets the offset of the caption text from its normal position. + /// + /// an array of two floats that specifies the offset of the caption text from its + /// normal position. The first value defines the horizontal offset along the annotation line from + /// its midpoint, with a positive value indicating offset to the right and a negative value indicating + /// offset to the left. The second value defines the vertical offset perpendicular to the annotation line, + /// with a positive value indicating a shift up and a negative value indicating a shift down. + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfLineAnnotation SetCaptionOffset(float[] captionOffset) { return SetCaptionOffset(new PdfArray(captionOffset)); } diff --git a/itext/itext.kernel/itext/kernel/pdf/annot/PdfMarkupAnnotation.cs b/itext/itext.kernel/itext/kernel/pdf/annot/PdfMarkupAnnotation.cs index 40996719a0..d20f6cb612 100644 --- a/itext/itext.kernel/itext/kernel/pdf/annot/PdfMarkupAnnotation.cs +++ b/itext/itext.kernel/itext/kernel/pdf/annot/PdfMarkupAnnotation.cs @@ -41,11 +41,24 @@ source product. For more information, please contact iText Software Corp. at this address: sales@itextpdf.com */ +using iText.IO; +using iText.IO.Log; using iText.Kernel.Colors; using iText.Kernel.Geom; using iText.Kernel.Pdf; namespace iText.Kernel.Pdf.Annot { + /// + /// This is a super class for the annotations which are defined as markup annotations + /// because they are used primarily to mark up PDF documents. + /// + /// + /// This is a super class for the annotations which are defined as markup annotations + /// because they are used primarily to mark up PDF documents. These annotations have + /// text that appears as part of the annotation and may be displayed in other ways + /// by a conforming reader, such as in a Comments pane. + /// See also ISO-320001 12.5.6.2 "Markup Annotations". + /// public abstract class PdfMarkupAnnotation : PdfAnnotation { protected internal PdfAnnotation inReplyTo = null; @@ -59,113 +72,573 @@ protected internal PdfMarkupAnnotation(PdfDictionary pdfObject) : base(pdfObject) { } + /// + /// The text label that will be displayed in the title bar of the annotation's pop-up window + /// when open and active. + /// + /// + /// The text label that will be displayed in the title bar of the annotation's pop-up window + /// when open and active. This entry shall identify the user who added the annotation. + /// + /// + /// + /// + /// which value is an annotation text label content + /// or null if text is not specified. + /// public virtual PdfString GetText() { return GetPdfObject().GetAsString(PdfName.T); } + /// + /// Sets the text label that will be displayed in the title bar of the annotation's pop-up window + /// when open and active. + /// + /// + /// Sets the text label that will be displayed in the title bar of the annotation's pop-up window + /// when open and active. This entry shall identify the user who added the annotation. + /// + /// + /// + /// + /// which value is an annotation text label content. + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfMarkupAnnotation SetText(PdfString text) { return (iText.Kernel.Pdf.Annot.PdfMarkupAnnotation)Put(PdfName.T, text); } + /// The constant opacity value that will be used in painting the annotation. + /// + /// The constant opacity value that will be used in painting the annotation. + /// This value is applied to all visible elements of the annotation in its closed state + /// (including its background and border) but not to the pop-up window that appears when + /// the annotation is opened. Default value: 1.0. + /// + /// + /// a + /// + /// which value is in range between 0 and 1, which specifies the + /// level of opacity. This method returns null if opacity is not specified; in this case default + /// value is used, which is 1. + /// public virtual PdfNumber GetOpacity() { return GetPdfObject().GetAsNumber(PdfName.CA); } + /// Sets the constant opacity value that will be used in painting the annotation. + /// + /// a + /// + /// which value is in range between 0 and 1, which specifies the + /// level of opacity. + /// + /// + /// this + /// + /// instance. + /// + /// public virtual iText.Kernel.Pdf.Annot.PdfMarkupAnnotation SetOpacity(PdfNumber ca) { return (iText.Kernel.Pdf.Annot.PdfMarkupAnnotation)Put(PdfName.CA, ca); } + /// + /// A rich text string (see ISO-320001 12.7.3.4, “Rich Text Strings”) that + /// shall be displayed in the pop-up window when the annotation is opened. + /// + /// + /// text string or text stream that specifies rich text or null if + /// rich text is not specified. + /// public virtual PdfObject GetRichText() { - return GetPdfObject().GetAsDictionary(PdfName.RC); - } - + return GetPdfObject().Get(PdfName.RC); + } + + /// + /// Sets a rich text string (see ISO-320001 12.7.3.4, “Rich Text Strings”) that + /// shall be displayed in the pop-up window when the annotation is opened. + /// + /// text string or text stream that specifies rich text. + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfMarkupAnnotation SetRichText(PdfObject richText) { return (iText.Kernel.Pdf.Annot.PdfMarkupAnnotation)Put(PdfName.RC, richText); } + /// The date and time when the annotation was created. + /// + /// a + /// + /// which value should be in the date format specified in (ISO-320001 7.9.4, “Dates”). + /// public virtual PdfString GetCreationDate() { return GetPdfObject().GetAsString(PdfName.CreationDate); } + /// Sets the date and time when the annotation was created. + /// + /// + /// + /// which value should be in the date format + /// specified in (ISO-320001 7.9.4, “Dates”). + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfMarkupAnnotation SetCreationDate(PdfString creationDate) { return (iText.Kernel.Pdf.Annot.PdfMarkupAnnotation)Put(PdfName.CreationDate, creationDate); } + /// + /// An annotation object that this annotation is “in reply to.” + /// Both annotations shall be on the same page of the document. + /// + /// + /// An annotation object that this annotation is “in reply to.” + /// Both annotations shall be on the same page of the document. + /// The relationship between the two annotations shall be specified by the RT entry + /// (see + /// + /// ). + /// + /// + /// a + /// + /// that represents an annotation that this annotation is “in reply to.” + /// public virtual PdfDictionary GetInReplyToObject() { return GetPdfObject().GetAsDictionary(PdfName.IRT); } + /// + /// An annotation that this annotation is “in reply to.” + /// Both annotations shall be on the same page of the document. + /// + /// + /// An annotation that this annotation is “in reply to.” + /// Both annotations shall be on the same page of the document. + /// The relationship between the two annotations shall be specified by the RT entry + /// (see + /// + /// ). + /// + /// + /// a + /// + /// that this annotation is “in reply to.” + /// public virtual PdfAnnotation GetInReplyTo() { + if (inReplyTo == null) { + inReplyTo = MakeAnnotation(GetInReplyToObject()); + } return inReplyTo; } + /// + /// Sets an annotation that this annotation is “in reply to.” + /// Both annotations shall be on the same page of the document. + /// + /// + /// Sets an annotation that this annotation is “in reply to.” + /// Both annotations shall be on the same page of the document. + /// The relationship between the two annotations shall be specified by the RT entry + /// (see + /// + /// ). + /// + /// + /// a + /// + /// that this annotation is “in reply to.” + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfMarkupAnnotation SetInReplyTo(PdfAnnotation inReplyTo) { this.inReplyTo = inReplyTo; return (iText.Kernel.Pdf.Annot.PdfMarkupAnnotation)Put(PdfName.IRT, inReplyTo.GetPdfObject()); } + /// Sets a pop-up annotation for entering or editing the text associated with this annotation. + /// + /// Sets a pop-up annotation for entering or editing the text associated with this annotation. + /// Pop-up annotation defines an associated with this annotation pop-up window that may contain text. + /// The Contents (see + /// + /// ) entry of the annotation that has + /// an associated popup specifies the text that shall be displayed when the pop-up window is opened. + /// + /// + /// an + /// + /// that will be associated with this annotation. + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfMarkupAnnotation SetPopup(PdfPopupAnnotation popup) { this.popup = popup; - popup.Put(PdfName.Parent, GetPdfObject()); + popup.SetParent(this); return (iText.Kernel.Pdf.Annot.PdfMarkupAnnotation)Put(PdfName.Popup, popup.GetPdfObject()); } + /// An associated pop-up annotation object. + /// + /// An associated pop-up annotation object. See + /// + /// for more info. + /// + /// + /// a + /// + /// that represents an associated pop-up annotation, + /// or null if popup annotation is not specified. + /// public virtual PdfDictionary GetPopupObject() { return GetPdfObject().GetAsDictionary(PdfName.Popup); } + /// An associated pop-up annotation for entering or editing the text associated with this annotation. + /// + /// + /// An associated pop-up annotation for entering or editing the text associated with this annotation. + /// Pop-up annotation defines an associated with this annotation pop-up window that may contain text. + /// The Contents (see + /// + /// ) entry of the annotation that has + /// an associated popup specifies the text that shall be displayed when the pop-up window is opened. + /// + /// + /// an + /// + /// that is associated with this annotation, or null if there is none. + /// public virtual PdfPopupAnnotation GetPopup() { + if (popup == null) { + PdfAnnotation annotation = MakeAnnotation(GetPopupObject()); + if (!(annotation is PdfPopupAnnotation)) { + ILogger logger = LoggerFactory.GetLogger(typeof(iText.Kernel.Pdf.Annot.PdfMarkupAnnotation)); + logger.Warn(LogMessageConstant.POPUP_ENTRY_IS_NOT_POPUP_ANNOTATION); + return null; + } + popup = (PdfPopupAnnotation)annotation; + } return popup; } + /// Text representing a short description of the subject being addressed by the annotation. + /// + /// a + /// + /// which value is a annotation subject. + /// public virtual PdfString GetSubject() { return GetPdfObject().GetAsString(PdfName.Subj); } + /// Sets the text representing a short description of the subject being addressed by the annotation. + /// + /// a + /// + /// which value is a annotation subject. + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfMarkupAnnotation SetSubject(PdfString subject) { return (iText.Kernel.Pdf.Annot.PdfMarkupAnnotation)Put(PdfName.Subj, subject); } + /// + /// A name specifying the relationship (the “reply type”) between this annotation and one specified by IRT entry + /// (see + /// + /// ). Valid values are: + ///
      + ///
    • + /// + /// - The annotation shall be considered a reply to the annotation specified by IRT. + /// Conforming readers shall not display replies to an annotation individually but together in the form of + /// threaded comments.
    • + ///
    • + /// + /// - The annotation shall be grouped with the annotation specified by IRT.
    • + ///
    + ///
    + /// + /// a + /// + /// specifying relationship with the specified by the IRT entry; or null if reply + /// type is not specified, in this case the default value is + /// + /// . + /// public virtual PdfName GetReplyType() { return GetPdfObject().GetAsName(PdfName.RT); } + /// + /// Sets the relationship (the “reply type”) between this annotation and one specified by IRT entry + /// (see + /// + /// ). For valid values see + /// + /// . + /// + /// + /// a + /// + /// specifying relationship with the specified by the IRT entry. + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfMarkupAnnotation SetReplyType(PdfName replyType) { return (iText.Kernel.Pdf.Annot.PdfMarkupAnnotation)Put(PdfName.RT, replyType); } + /// A name describing the intent of the markup annotation. + /// + /// A name describing the intent of the markup annotation. + /// See + /// + /// for more info. + /// + /// + /// a + /// + /// describing the intent of the markup annotation, or null if not specified. + /// public virtual PdfName GetIntent() { return GetPdfObject().GetAsName(PdfName.IT); } + /// Sets a name describing the intent of the markup annotation. + /// + /// Sets a name describing the intent of the markup annotation. + /// Intents allow conforming readers to distinguish between different uses and behaviors + /// of a single markup annotation type. If this entry is not present or its value is the same as the annotation type, + /// the annotation shall have no explicit intent and should behave in a generic manner in a conforming reader. + ///

    + /// See ISO-320001, free text annotations (Table 174), line annotations (Table 175), polygon annotations (Table 178), + /// and polyline annotations (Table 178) for the specific intent values for those types. + ///

    + ///
    + /// + /// a + /// + /// describing the intent of the markup annotation. + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfMarkupAnnotation SetIntent(PdfName intent) { return (iText.Kernel.Pdf.Annot.PdfMarkupAnnotation)Put(PdfName.IT, intent); } + /// An external data dictionary specifying data that shall be associated with the annotation. + /// + /// An external data dictionary specifying data that shall be associated with the annotation. + /// This dictionary contains the following entries: + ///
      + ///
    • + /// + /// - (optional) If present, shall be + /// + /// .
    • + ///
    • + /// + /// - (required) a name specifying the type of data that the markup annotation + /// shall be associated with. The only defined value is + /// + /// . Table 298 (ISO-320001) + /// lists the values that correspond to a subtype of Markup3D (See also + /// + /// ).
    • + ///
    + ///
    + /// + /// An external data + /// + /// , or null if not specified. + /// public virtual PdfDictionary GetExternalData() { return GetPdfObject().GetAsDictionary(PdfName.ExData); } + /// Sets an external data dictionary specifying data that shall be associated with the annotation. + /// + /// Sets an external data dictionary specifying data that shall be associated with the annotation. + /// This dictionary should contain the following entries: + ///
      + ///
    • + /// + /// - (optional) If present, shall be + /// + /// .
    • + ///
    • + /// + /// - (required) a name specifying the type of data that the markup annotation + /// shall be associated with. The only defined value is + /// + /// . Table 298 (ISO-320001) + /// lists the values that correspond to a subtype of Markup3D (See also + /// + /// ).
    • + ///
    + ///
    + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfMarkupAnnotation SetExternalData(PdfName exData) { return (iText.Kernel.Pdf.Annot.PdfMarkupAnnotation)Put(PdfName.ExData, exData); } + /// + /// A set of four numbers describing the numerical differences between two rectangles: + /// the Rect entry of the annotation and another rectangle within that one, which + /// meaning depends on the type of the annotation: + ///
      + ///
    • for + /// + /// the inner rectangle is where the annotation's text should be displayed;
    • + ///
    • + /// for + /// + /// and + /// + /// the inner rectangle is the actual boundaries + /// of the underlying square or circle; + ///
    • + ///
    • for + /// + /// the inner rectangle is the actual boundaries of the underlying caret.
    • + ///
    + ///
    + /// + /// a + /// + /// with four numbers which correspond to the differences in default user space between + /// the left, top, right, and bottom coordinates of Rect and those of the inner rectangle, respectively. + /// Each value shall be greater than or equal to 0. The sum of the top and bottom differences shall be + /// less than the height of Rect, and the sum of the left and right differences shall be less than + /// the width of Rect. + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfMarkupAnnotation SetRectangleDifferences(PdfArray rect) { return (iText.Kernel.Pdf.Annot.PdfMarkupAnnotation)Put(PdfName.RD, rect); } + /// + /// A set of four numbers describing the numerical differences between two rectangles: + /// the Rect entry of the annotation and another rectangle within that one, which + /// meaning depends on the type of the annotation (see + /// + /// ). + /// + /// + /// null if not specified, otherwise a + /// + /// with four numbers which correspond to the + /// differences in default user space between the left, top, right, and bottom coordinates of Rect and those + /// of the inner rectangle, respectively. + /// public virtual PdfArray GetRectangleDifferences() { return GetPdfObject().GetAsArray(PdfName.RD); } - public virtual PdfDictionary GetBorderEffect() { - return GetPdfObject().GetAsDictionary(PdfName.BE); - } - + /// + /// Some annotations types ( + /// + /// , + /// + /// , + /// + /// and + /// + /// ) may have a + /// + /// entry, which is a border effect dictionary that specifies + /// an effect that shall be applied to the border of the annotations. + /// + /// + /// a + /// + /// which contents shall be specified in accordance to ISO-320001, Table 167. + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfMarkupAnnotation SetBorderEffect(PdfDictionary borderEffect) { return (iText.Kernel.Pdf.Annot.PdfMarkupAnnotation)Put(PdfName.BE, borderEffect); } + /// A border effect dictionary that specifies an effect that shall be applied to the border of the annotations. + /// + /// + /// a + /// + /// , which is a border effect dictionary (see ISO-320001, Table 167). + /// + public virtual PdfDictionary GetBorderEffect() { + return GetPdfObject().GetAsDictionary(PdfName.BE); + } + + /// The interior color which is used to fill areas specific for different types of annotation. + /// + /// The interior color which is used to fill areas specific for different types of annotation. For + /// + /// and polyline annotation ( + /// + /// - the annotation's line endings, for + /// + /// and + /// + /// - the annotation's rectangle or ellipse, for + /// + /// - the redacted + /// region after the affected content has been removed. + /// + /// + /// + /// + /// of either + /// + /// , + /// + /// or + /// + /// type which defines + /// interior color of the annotation, or null if interior color is not specified. + /// public virtual Color GetInteriorColor() { PdfArray color = GetPdfObject().GetAsArray(PdfName.IC); if (color == null) { @@ -192,35 +665,170 @@ public virtual Color GetInteriorColor() { } } + /// + /// An array of numbers in the range 0.0 to 1.0 specifying the interior color which is used to fill areas specific + /// for different types of annotation. + /// + /// + /// An array of numbers in the range 0.0 to 1.0 specifying the interior color which is used to fill areas specific + /// for different types of annotation. For + /// + /// and polyline annotation ( + /// + /// - + /// the annotation's line endings, for + /// + /// and + /// + /// - the annotation's + /// rectangle or ellipse, for + /// + /// - the redacted region after the affected content has been removed. + /// + /// + /// a + /// + /// of numbers in the range 0.0 to 1.0. The number of array elements determines + /// the colour space in which the colour is defined: 0 - No colour, transparent; 1 - DeviceGray, + /// 3 - DeviceRGB, 4 - DeviceCMYK. For the + /// + /// number of elements shall be + /// equal to 3 (which defines DeviceRGB colour space). + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfMarkupAnnotation SetInteriorColor(PdfArray interiorColor) { return (iText.Kernel.Pdf.Annot.PdfMarkupAnnotation)Put(PdfName.IC, interiorColor); } + /// + /// An array of numbers in the range 0.0 to 1.0 specifying the interior color which is used to fill areas specific + /// for different types of annotation. + /// + /// + /// An array of numbers in the range 0.0 to 1.0 specifying the interior color which is used to fill areas specific + /// for different types of annotation. See + /// + /// for more info. + /// + /// an array of floats in the range 0.0 to 1.0. + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfMarkupAnnotation SetInteriorColor(float[] interiorColor) { return SetInteriorColor(new PdfArray(interiorColor)); } + /// The name of an icon that is used in displaying the annotation. + /// + /// The name of an icon that is used in displaying the annotation. Possible values are different for different + /// annotation types. See + /// + /// . + /// + /// + /// a + /// + /// that specifies the icon for displaying annotation, or null if icon name is not specified. + /// public virtual PdfName GetIconName() { return GetPdfObject().GetAsName(PdfName.Name); } + /// The name of an icon that is used in displaying the annotation. + /// + /// a + /// + /// that specifies the icon for displaying annotation. Possible values are different + /// for different annotation types: + ///
      + ///
    • + /// + /// - Comment, Key, Note, Help, NewParagraph, Paragraph, Insert;
    • + ///
    • + /// + /// - Approved, Experimental, NotApproved, AsIs, Expired, NotForPublicRelease, + /// Confidential, Final, Sold, Departmental, ForComment, TopSecret, Draft, ForPublicRelease.
    • + ///
    • + /// + /// - GraphPushPin, PaperclipTag. Additional names may be supported as well.
    • + ///
    • + /// + /// - Speaker and Mic. Additional names may be supported as well.
    • + ///
    + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfMarkupAnnotation SetIconName(PdfName name) { return (iText.Kernel.Pdf.Annot.PdfMarkupAnnotation)Put(PdfName.Name, name); } + /// The default appearance string that shall be used in formatting the text. + /// The default appearance string that shall be used in formatting the text. See ISO-32001 12.7.3.3, “Variable Text”. + /// + /// + /// a + /// + /// that specifies the default appearance. + /// + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfMarkupAnnotation SetDefaultAppearance(PdfString appearanceString) { return (iText.Kernel.Pdf.Annot.PdfMarkupAnnotation)Put(PdfName.DA, appearanceString); } + /// The default appearance string that shall be used in formatting the text. + /// The default appearance string that shall be used in formatting the text. See ISO-32001 12.7.3.3, “Variable Text”. + /// + /// + /// a + /// + /// that specifies the default appearance, or null if default appereance is not specified. + /// public virtual PdfString GetDefaultAppearance() { return GetPdfObject().GetAsString(PdfName.DA); } + /// + /// A code specifying the form of quadding (justification) that is used in displaying the annotation's text: + /// 0 - Left-justified, 1 - Centered, 2 - Right-justified. + /// + /// + /// A code specifying the form of quadding (justification) that is used in displaying the annotation's text: + /// 0 - Left-justified, 1 - Centered, 2 - Right-justified. Default value: 0 (left-justified). + /// + /// a code specifying the form of quadding (justification), returns the default value if not explicitly specified. + /// public virtual int GetJustification() { PdfNumber q = GetPdfObject().GetAsNumber(PdfName.Q); return q == null ? 0 : q.IntValue(); } + /// + /// A code specifying the form of quadding (justification) that is used in displaying the annotation's text: + /// 0 - Left-justified, 1 - Centered, 2 - Right-justified. + /// + /// + /// A code specifying the form of quadding (justification) that is used in displaying the annotation's text: + /// 0 - Left-justified, 1 - Centered, 2 - Right-justified. Default value: 0 (left-justified). + /// + /// a code specifying the form of quadding (justification). + /// + /// this + /// + /// instance. + /// public virtual iText.Kernel.Pdf.Annot.PdfMarkupAnnotation SetJustification(int justification) { return (iText.Kernel.Pdf.Annot.PdfMarkupAnnotation)Put(PdfName.Q, new PdfNumber(justification)); } diff --git a/itext/itext.kernel/itext/kernel/pdf/annot/PdfPopupAnnotation.cs b/itext/itext.kernel/itext/kernel/pdf/annot/PdfPopupAnnotation.cs index 7f991519c0..55eaf302c9 100644 --- a/itext/itext.kernel/itext/kernel/pdf/annot/PdfPopupAnnotation.cs +++ b/itext/itext.kernel/itext/kernel/pdf/annot/PdfPopupAnnotation.cs @@ -65,6 +65,9 @@ public virtual PdfDictionary GetParentObject() { } public virtual PdfAnnotation GetParent() { + if (parent == null) { + parent = MakeAnnotation(GetParentObject()); + } return parent; } diff --git a/itext/itext.kernel/itext/kernel/pdf/annot/PdfTextMarkupAnnotation.cs b/itext/itext.kernel/itext/kernel/pdf/annot/PdfTextMarkupAnnotation.cs index 84436c0ee6..35b7016023 100644 --- a/itext/itext.kernel/itext/kernel/pdf/annot/PdfTextMarkupAnnotation.cs +++ b/itext/itext.kernel/itext/kernel/pdf/annot/PdfTextMarkupAnnotation.cs @@ -65,21 +65,129 @@ public PdfTextMarkupAnnotation(PdfDictionary pdfObject) : base(pdfObject) { } + /// Creates a text markup annotation of highlight style subtype. + /// + /// Creates a text markup annotation of highlight style subtype. + ///

    + /// IMPORTANT NOTE on quadPoints argument: + /// According to Table 179 in ISO 32000-1, the QuadPoints array lists the vertices in counterclockwise + /// order and the text orientation is defined by the first and second vertex. This basically means QuadPoints is + /// specified as lower-left, lower-right, top-right, top-left. HOWEVER, Adobe's interpretation + /// (tested at least with Acrobat 10, Acrobat 11, Reader 11) is top-left, top-right, lower-left, lower-right (Z-shaped order). + /// This means that if the QuadPoints array is specified according to the standard, the rendering is not as expected. + /// Other viewers seem to follow Adobe's interpretation. Hence we recommend to use and expect QuadPoints array in Z-order, + /// just as Acrobat and probably most other viewers expect. + /// + /// + /// the annotation rectangle, defining the location of the annotation on the page + /// in default user space units. + /// + /// + /// An array of 8 × n numbers specifying the coordinates of n quadrilaterals in default user space. + /// Each quadrilateral shall encompasses a word or group of contiguous words in the text underlying + /// the annotation. The text is oriented with respect to the edge connecting first two vertices. + /// + /// + /// created + /// + /// of Highlight type. + /// public static iText.Kernel.Pdf.Annot.PdfTextMarkupAnnotation CreateHighLight(Rectangle rect, float[] quadPoints ) { return new iText.Kernel.Pdf.Annot.PdfTextMarkupAnnotation(rect, MarkupHighlight, quadPoints); } + ///

    Creates a text markup annotation of underline style subtype. + /// + /// Creates a text markup annotation of underline style subtype. + ///

    + /// IMPORTANT NOTE on quadPoints argument: + /// According to Table 179 in ISO 32000-1, the QuadPoints array lists the vertices in counterclockwise + /// order and the text orientation is defined by the first and second vertex. This basically means QuadPoints is + /// specified as lower-left, lower-right, top-right, top-left. HOWEVER, Adobe's interpretation + /// (tested at least with Acrobat 10, Acrobat 11, Reader 11) is top-left, top-right, lower-left, lower-right (Z-shaped order). + /// This means that if the QuadPoints array is specified according to the standard, the rendering is not as expected. + /// Other viewers seem to follow Adobe's interpretation. Hence we recommend to use and expect QuadPoints array in Z-order, + /// just as Acrobat and probably most other viewers expect. + /// + /// + /// the annotation rectangle, defining the location of the annotation on the page + /// in default user space units. + /// + /// + /// An array of 8 × n numbers specifying the coordinates of n quadrilaterals in default user space. + /// Each quadrilateral shall encompasses a word or group of contiguous words in the text underlying + /// the annotation. The text is oriented with respect to the edge connecting first two vertices. + /// + /// + /// created + /// + /// of Underline type. + /// public static iText.Kernel.Pdf.Annot.PdfTextMarkupAnnotation CreateUnderline(Rectangle rect, float[] quadPoints ) { return new iText.Kernel.Pdf.Annot.PdfTextMarkupAnnotation(rect, MarkupUnderline, quadPoints); } + ///

    Creates a text markup annotation of strikeout style subtype. + /// + /// Creates a text markup annotation of strikeout style subtype. + ///

    + /// IMPORTANT NOTE on quadPoints argument: + /// According to Table 179 in ISO 32000-1, the QuadPoints array lists the vertices in counterclockwise + /// order and the text orientation is defined by the first and second vertex. This basically means QuadPoints is + /// specified as lower-left, lower-right, top-right, top-left. HOWEVER, Adobe's interpretation + /// (tested at least with Acrobat 10, Acrobat 11, Reader 11) is top-left, top-right, lower-left, lower-right (Z-shaped order). + /// This means that if the QuadPoints array is specified according to the standard, the rendering is not as expected. + /// Other viewers seem to follow Adobe's interpretation. Hence we recommend to use and expect QuadPoints array in Z-order, + /// just as Acrobat and probably most other viewers expect. + /// + /// + /// the annotation rectangle, defining the location of the annotation on the page + /// in default user space units. + /// + /// + /// An array of 8 × n numbers specifying the coordinates of n quadrilaterals in default user space. + /// Each quadrilateral shall encompasses a word or group of contiguous words in the text underlying + /// the annotation. The text is oriented with respect to the edge connecting first two vertices. + /// + /// + /// created + /// + /// of Strikeout type. + /// public static iText.Kernel.Pdf.Annot.PdfTextMarkupAnnotation CreateStrikeout(Rectangle rect, float[] quadPoints ) { return new iText.Kernel.Pdf.Annot.PdfTextMarkupAnnotation(rect, MarkupStrikeout, quadPoints); } + ///

    Creates a text markup annotation of squiggly-underline type. + /// + /// Creates a text markup annotation of squiggly-underline type. + ///

    + /// IMPORTANT NOTE on quadPoints argument: + /// According to Table 179 in ISO 32000-1, the QuadPoints array lists the vertices in counterclockwise + /// order and the text orientation is defined by the first and second vertex. This basically means QuadPoints is + /// specified as lower-left, lower-right, top-right, top-left. HOWEVER, Adobe's interpretation + /// (tested at least with Acrobat 10, Acrobat 11, Reader 11) is top-left, top-right, lower-left, lower-right (Z-shaped order). + /// This means that if the QuadPoints array is specified according to the standard, the rendering is not as expected. + /// Other viewers seem to follow Adobe's interpretation. Hence we recommend to use and expect QuadPoints array in Z-order, + /// just as Acrobat and probably most other viewers expect. + /// + /// + /// the annotation rectangle, defining the location of the annotation on the page + /// in default user space units. + /// + /// + /// An array of 8 × n numbers specifying the coordinates of n quadrilaterals in default user space. + /// Each quadrilateral shall encompasses a word or group of contiguous words in the text underlying + /// the annotation. The text is oriented with respect to the edge connecting first two vertices. + /// + /// + /// created + /// + /// of squiggly-underline type. + /// public static iText.Kernel.Pdf.Annot.PdfTextMarkupAnnotation CreateSquiggly(Rectangle rect, float[] quadPoints ) { return new iText.Kernel.Pdf.Annot.PdfTextMarkupAnnotation(rect, MarkupSquiggly, quadPoints); diff --git a/itext/itext.kernel/itext/kernel/pdf/canvas/PdfCanvas.cs b/itext/itext.kernel/itext/kernel/pdf/canvas/PdfCanvas.cs index eb56f93807..ba19bccffd 100644 --- a/itext/itext.kernel/itext/kernel/pdf/canvas/PdfCanvas.cs +++ b/itext/itext.kernel/itext/kernel/pdf/canvas/PdfCanvas.cs @@ -362,6 +362,33 @@ public virtual iText.Kernel.Pdf.Canvas.PdfCanvas ConcatMatrix(double a, double b return this; } + ///

    + /// Concatenates the 2x3 affine transformation matrix to the current matrix + /// in the content stream managed by this Canvas. + /// + /// + /// Concatenates the 2x3 affine transformation matrix to the current matrix + /// in the content stream managed by this Canvas. + /// If an array not containing the 6 values of the matrix is passed, + /// The current canvas is returned unchanged. + /// + /// affine transformation stored as a PdfArray with 6 values + /// current canvas + public virtual iText.Kernel.Pdf.Canvas.PdfCanvas ConcatMatrix(PdfArray array) { + if (array.Size() != 6) { + //Throw exception or warning here + return this; + } + for (int i = 0; i < array.Size(); i++) { + if (!array.Get(i).IsNumber()) { + return this; + } + } + return ConcatMatrix(array.GetAsNumber(0).DoubleValue(), array.GetAsNumber(1).DoubleValue(), array.GetAsNumber + (2).DoubleValue(), array.GetAsNumber(3).DoubleValue(), array.GetAsNumber(4).DoubleValue(), array.GetAsNumber + (5).DoubleValue()); + } + /// /// Concatenates the affine transformation matrix to the current matrix /// in the content stream managed by this Canvas. @@ -411,7 +438,7 @@ public virtual iText.Kernel.Pdf.Canvas.PdfCanvas EndVariableText() { /// current canvas. public virtual iText.Kernel.Pdf.Canvas.PdfCanvas SetFontAndSize(PdfFont font, float size) { if (size < 0.0001f && size > -0.0001f) { - throw new PdfException(PdfException.FontSizeTooSmall, size); + throw new PdfException(PdfException.FontSizeIsTooSmall, size); } currentGs.SetFontSize(size); font.MakeIndirect(document); @@ -620,8 +647,38 @@ public virtual iText.Kernel.Pdf.Canvas.PdfCanvas ShowText(GlyphLine text) { float xPlacement = float.NaN; float yPlacement = float.NaN; if (glyph.HasPlacement()) { - xPlacement = -GetSubrangeWidth(text, i + glyph.GetAnchorDelta(), i) + glyph.GetXPlacement() * fontSize; - yPlacement = glyph.GetYAdvance() * fontSize; + { + float xPlacementAddition = 0; + int currentGlyphIndex = i; + Glyph currentGlyph = text.Get(i); + while (currentGlyph != null && currentGlyph.GetXPlacement() != 0) { + xPlacementAddition += currentGlyph.GetXPlacement(); + if (currentGlyph.GetAnchorDelta() == 0) { + break; + } + else { + currentGlyphIndex += currentGlyph.GetAnchorDelta(); + currentGlyph = text.Get(currentGlyphIndex); + } + } + xPlacement = -GetSubrangeWidth(text, currentGlyphIndex, i) + xPlacementAddition * fontSize; + } + { + float yPlacementAddition = 0; + int currentGlyphIndex = i; + Glyph currentGlyph = text.Get(i); + while (currentGlyph != null && currentGlyph.GetYPlacement() != 0) { + yPlacementAddition += currentGlyph.GetYPlacement(); + if (currentGlyph.GetAnchorDelta() == 0) { + break; + } + else { + currentGlyph = text.Get(currentGlyphIndex + currentGlyph.GetAnchorDelta()); + currentGlyphIndex += currentGlyph.GetAnchorDelta(); + } + } + yPlacement = glyph.GetYAdvance() * fontSize + yPlacementAddition * fontSize; + } contentStream.GetOutputStream().WriteFloat(xPlacement, true).WriteSpace().WriteFloat(yPlacement, true).WriteSpace ().WriteBytes(Td); } @@ -1570,7 +1627,6 @@ public virtual PdfXObject AddImage(ImageData image, float a, float b, float c, f /// /// true if to add image as in-line. /// created XObject or null in case of in-line image (asInline = true). - /// public virtual PdfXObject AddImage(ImageData image, iText.Kernel.Geom.Rectangle rect, bool asInline) { return AddImage(image, rect.GetWidth(), 0, 0, rect.GetHeight(), rect.GetX(), rect.GetY(), asInline); } @@ -1581,7 +1637,6 @@ public virtual PdfXObject AddImage(ImageData image, iText.Kernel.Geom.Rectangle /// /// true if to add image as in-line. /// created XObject or null in case of in-line image (asInline = true). - /// public virtual PdfXObject AddImage(ImageData image, float x, float y, bool asInline) { if (image.GetOriginalType() == ImageType.WMF) { WmfImageHelper wmf = new WmfImageHelper(image); @@ -1640,7 +1695,6 @@ public virtual PdfXObject AddImage(ImageData image, float x, float y, float widt /// true if to add image as in-line. /// /// created XObject or null in case of in-line image (asInline = true). - /// public virtual PdfXObject AddImage(ImageData image, float x, float y, float height, bool asInline, bool dummy ) { return AddImage(image, height / image.GetHeight() * image.GetWidth(), 0, 0, height, x, y, asInline); @@ -2001,7 +2055,6 @@ private iText.Kernel.Pdf.Canvas.PdfCanvas AddForm(PdfFormXObject form, float a, /// /// /// current canvas. - /// private iText.Kernel.Pdf.Canvas.PdfCanvas AddForm(PdfFormXObject form, float x, float y) { return AddForm(form, 1, 0, 0, 1, x, y); } @@ -2014,7 +2067,6 @@ private iText.Kernel.Pdf.Canvas.PdfCanvas AddForm(PdfFormXObject form, float x, /// /// /// current canvas. - /// private iText.Kernel.Pdf.Canvas.PdfCanvas AddForm(PdfFormXObject form, iText.Kernel.Geom.Rectangle rect) { return AddForm(form, rect.GetWidth(), 0, 0, rect.GetHeight(), rect.GetX(), rect.GetY()); } @@ -2029,7 +2081,6 @@ private iText.Kernel.Pdf.Canvas.PdfCanvas AddForm(PdfFormXObject form, iText.Ker /// /// /// current canvas. - /// private iText.Kernel.Pdf.Canvas.PdfCanvas AddForm(PdfFormXObject form, float x, float y, float width) { PdfArray bbox = form.GetPdfObject().GetAsArray(PdfName.BBox); if (bbox == null) { diff --git a/itext/itext.kernel/itext/kernel/pdf/canvas/draw/DashedLine.cs b/itext/itext.kernel/itext/kernel/pdf/canvas/draw/DashedLine.cs index 01a00b83ab..7a9bf8de3a 100644 --- a/itext/itext.kernel/itext/kernel/pdf/canvas/draw/DashedLine.cs +++ b/itext/itext.kernel/itext/kernel/pdf/canvas/draw/DashedLine.cs @@ -72,8 +72,8 @@ public DashedLine(float lineWidth) { public virtual void Draw(PdfCanvas canvas, Rectangle drawArea) { canvas.SaveState().SetLineWidth(lineWidth).SetStrokeColor(color).SetLineDash(2, 2).MoveTo(drawArea.GetX(), - drawArea.GetY() + drawArea.GetHeight() / 2).LineTo(drawArea.GetX() + drawArea.GetWidth(), drawArea.GetY - () + drawArea.GetHeight() / 2).Stroke().RestoreState(); + drawArea.GetY() + lineWidth / 2).LineTo(drawArea.GetX() + drawArea.GetWidth(), drawArea.GetY() + lineWidth + / 2).Stroke().RestoreState(); } /// Gets line width in points diff --git a/itext/itext.kernel/itext/kernel/pdf/canvas/draw/DottedLine.cs b/itext/itext.kernel/itext/kernel/pdf/canvas/draw/DottedLine.cs index 399bdf5677..9b45b4b920 100644 --- a/itext/itext.kernel/itext/kernel/pdf/canvas/draw/DottedLine.cs +++ b/itext/itext.kernel/itext/kernel/pdf/canvas/draw/DottedLine.cs @@ -83,8 +83,8 @@ public DottedLine(float lineWidth) { public virtual void Draw(PdfCanvas canvas, Rectangle drawArea) { canvas.SaveState().SetLineWidth(lineWidth).SetStrokeColor(color).SetLineDash(0, gap, gap / 2).SetLineCapStyle - (PdfCanvasConstants.LineCapStyle.ROUND).MoveTo(drawArea.GetX(), drawArea.GetY()).LineTo(drawArea.GetX( - ) + drawArea.GetWidth(), drawArea.GetY()).Stroke().RestoreState(); + (PdfCanvasConstants.LineCapStyle.ROUND).MoveTo(drawArea.GetX(), drawArea.GetY() + lineWidth / 2).LineTo + (drawArea.GetX() + drawArea.GetWidth(), drawArea.GetY() + lineWidth / 2).Stroke().RestoreState(); } /// Getter for the gap between the center of the dots of the dotted line. diff --git a/itext/itext.kernel/itext/kernel/pdf/canvas/draw/SolidLine.cs b/itext/itext.kernel/itext/kernel/pdf/canvas/draw/SolidLine.cs index 65202a2cb1..10eac8bf22 100644 --- a/itext/itext.kernel/itext/kernel/pdf/canvas/draw/SolidLine.cs +++ b/itext/itext.kernel/itext/kernel/pdf/canvas/draw/SolidLine.cs @@ -68,8 +68,9 @@ public SolidLine(float lineWidth) { } public virtual void Draw(PdfCanvas canvas, Rectangle drawArea) { - canvas.SaveState().SetStrokeColor(color).MoveTo(drawArea.GetX(), drawArea.GetY()).LineTo(drawArea.GetX() + - drawArea.GetWidth(), drawArea.GetY()).Stroke().RestoreState(); + canvas.SaveState().SetStrokeColor(color).SetLineWidth(lineWidth).MoveTo(drawArea.GetX(), drawArea.GetY() + + lineWidth / 2).LineTo(drawArea.GetX() + drawArea.GetWidth(), drawArea.GetY() + lineWidth / 2).Stroke( + ).RestoreState(); } /// Gets line width in points diff --git a/itext/itext.kernel/itext/kernel/pdf/canvas/parser/PdfCanvasProcessor.cs b/itext/itext.kernel/itext/kernel/pdf/canvas/parser/PdfCanvasProcessor.cs index ba9b629c03..1b7c1a3483 100644 --- a/itext/itext.kernel/itext/kernel/pdf/canvas/parser/PdfCanvasProcessor.cs +++ b/itext/itext.kernel/itext/kernel/pdf/canvas/parser/PdfCanvasProcessor.cs @@ -113,7 +113,7 @@ public class PdfCanvasProcessor { private Stack markedContentStack = new Stack(); /// - /// Creates a new PDF Content Stream Processor that will send it's output to the + /// Creates a new PDF Content Stream Processor that will send its output to the /// designated render listener. /// /// @@ -131,6 +131,34 @@ public PdfCanvasProcessor(IEventListener eventListener) { Reset(); } + /// + /// Creates a new PDF Content Stream Processor that will send its output to the + /// designated render listener. + /// + /// + /// Creates a new PDF Content Stream Processor that will send its output to the + /// designated render listener. + /// Also allows registration of custom IContentOperators that can influence + /// how (and whether or not) the PDF instructions will be parsed. + /// + /// + /// the + /// + /// that will receive rendering notifications + /// + /// + /// an optional map of custom + /// + /// s for rendering instructions + /// + public PdfCanvasProcessor(IEventListener eventListener, IDictionary additionalContentOperators + ) + : this(eventListener) { + foreach (KeyValuePair entry in additionalContentOperators) { + RegisterContentOperator(entry.Key, entry.Value); + } + } + /// Registers a Do handler that will be called when Do for the provided XObject subtype is encountered during content processing. /// /// diff --git a/itext/itext.kernel/itext/kernel/pdf/canvas/parser/PdfDocumentContentParser.cs b/itext/itext.kernel/itext/kernel/pdf/canvas/parser/PdfDocumentContentParser.cs index d95120c092..93ae300ef2 100644 --- a/itext/itext.kernel/itext/kernel/pdf/canvas/parser/PdfDocumentContentParser.cs +++ b/itext/itext.kernel/itext/kernel/pdf/canvas/parser/PdfDocumentContentParser.cs @@ -62,7 +62,8 @@ public PdfDocumentContentParser(PdfDocument pdfDocument) { /// Processes content from the specified page number using the specified listener. /// /// Processes content from the specified page number using the specified listener. - /// Also allows registration of custom ContentOperators + /// Also allows registration of custom IContentOperators that can influence + /// how (and whether or not) the PDF instructions will be parsed. /// /// /// the page number to process @@ -73,10 +74,7 @@ public PdfDocumentContentParser(PdfDocument pdfDocument) { public virtual E ProcessContent(int pageNumber, E renderListener, IDictionary additionalContentOperators) where E : IEventListener { - PdfCanvasProcessor processor = new PdfCanvasProcessor(renderListener); - foreach (KeyValuePair entry in additionalContentOperators) { - processor.RegisterContentOperator(entry.Key, entry.Value); - } + PdfCanvasProcessor processor = new PdfCanvasProcessor(renderListener, additionalContentOperators); processor.ProcessPageContent(pdfDocument.GetPage(pageNumber)); return renderListener; } diff --git a/itext/itext.kernel/itext/kernel/pdf/canvas/parser/PdfTextExtractor.cs b/itext/itext.kernel/itext/kernel/pdf/canvas/parser/PdfTextExtractor.cs index 960f3bcd7b..dbf2c42572 100644 --- a/itext/itext.kernel/itext/kernel/pdf/canvas/parser/PdfTextExtractor.cs +++ b/itext/itext.kernel/itext/kernel/pdf/canvas/parser/PdfTextExtractor.cs @@ -42,6 +42,7 @@ source product. address: sales@itextpdf.com */ using System; +using System.Collections.Generic; using iText.Kernel.Pdf; using iText.Kernel.Pdf.Canvas.Parser.Listener; @@ -51,15 +52,34 @@ private PdfTextExtractor() { } /// Extract text from a specified page using an extraction strategy. + /// + /// Extract text from a specified page using an extraction strategy. + /// Also allows registration of custom IContentOperators that can influence + /// how (and whether or not) the PDF instructions will be parsed. + /// /// the page for the text to be extracted from /// the strategy to use for extracting text + /// + /// an optional map of custom + /// + /// s for rendering instructions + /// /// the extracted text - public static String GetTextFromPage(PdfPage page, ITextExtractionStrategy strategy) { - PdfCanvasProcessor parser = new PdfCanvasProcessor(strategy); + public static String GetTextFromPage(PdfPage page, ITextExtractionStrategy strategy, IDictionary additionalContentOperators) { + PdfCanvasProcessor parser = new PdfCanvasProcessor(strategy, additionalContentOperators); parser.ProcessPageContent(page); return strategy.GetResultantText(); } + /// Extract text from a specified page using an extraction strategy. + /// the page for the text to be extracted from + /// the strategy to use for extracting text + /// the extracted text + public static String GetTextFromPage(PdfPage page, ITextExtractionStrategy strategy) { + return GetTextFromPage(page, strategy, new Dictionary()); + } + /// Extract text from a specified page using the default strategy. /// /// Extract text from a specified page using the default strategy. @@ -71,7 +91,6 @@ public static String GetTextFromPage(PdfPage page, ITextExtractionStrategy strat /// /// the page for the text to be extracted from /// the extracted text - /// public static String GetTextFromPage(PdfPage page) { return GetTextFromPage(page, new LocationTextExtractionStrategy()); } diff --git a/itext/itext.kernel/itext/kernel/pdf/canvas/parser/clipperlib/ClipperBridge.cs b/itext/itext.kernel/itext/kernel/pdf/canvas/parser/clipperlib/ClipperBridge.cs index 618fdf8b6e..c38e0e9c10 100644 --- a/itext/itext.kernel/itext/kernel/pdf/canvas/parser/clipperlib/ClipperBridge.cs +++ b/itext/itext.kernel/itext/kernel/pdf/canvas/parser/clipperlib/ClipperBridge.cs @@ -272,7 +272,7 @@ public static PolyFillType GetFillType(int fillingRule) { return fillType; } - [Obsolete] + [System.ObsoleteAttribute(@"close will be boolean . Visibility will be changed to internal.")] public static void AddContour(Path path, IList contour, bool? close) { IList floatContour = ConvertToFloatPoints(contour); Point point = floatContour[0]; diff --git a/itext/itext.kernel/itext/kernel/pdf/canvas/parser/data/TextRenderInfo.cs b/itext/itext.kernel/itext/kernel/pdf/canvas/parser/data/TextRenderInfo.cs index 32f4abbe0f..c6ba00829b 100644 --- a/itext/itext.kernel/itext/kernel/pdf/canvas/parser/data/TextRenderInfo.cs +++ b/itext/itext.kernel/itext/kernel/pdf/canvas/parser/data/TextRenderInfo.cs @@ -198,8 +198,7 @@ public virtual LineSegment GetUnscaledBaseline() { /// /// the ascentline line segment public virtual LineSegment GetAscentLine() { - float ascent = gs.GetFont().GetFontProgram().GetFontMetrics().GetTypoAscender() * gs.GetFontSize() / 1000f; - return GetUnscaledBaselineWithOffset(ascent + gs.GetTextRise()).TransformBy(textToUserSpaceTransformMatrix + return GetUnscaledBaselineWithOffset(GetAscentDescent()[0] + gs.GetTextRise()).TransformBy(textToUserSpaceTransformMatrix ); } @@ -212,9 +211,7 @@ public virtual LineSegment GetAscentLine() { /// /// the descentline line segment public virtual LineSegment GetDescentLine() { - // per getFontDescription() API, descent is returned as a negative number, so we apply that as a normal vertical offset - float descent = gs.GetFont().GetFontProgram().GetFontMetrics().GetTypoDescender() * gs.GetFontSize() / 1000f; - return GetUnscaledBaselineWithOffset(descent + gs.GetTextRise()).TransformBy(textToUserSpaceTransformMatrix + return GetUnscaledBaselineWithOffset(GetAscentDescent()[1] + gs.GetTextRise()).TransformBy(textToUserSpaceTransformMatrix ); } @@ -476,5 +473,18 @@ private PdfString[] SplitString(PdfString @string) { } return strings.ToArray(new PdfString[strings.Count]); } + + private float[] GetAscentDescent() { + float ascent = gs.GetFont().GetFontProgram().GetFontMetrics().GetTypoAscender(); + float descent = gs.GetFont().GetFontProgram().GetFontMetrics().GetTypoDescender(); + // If descent is positive, we consider it a bug and fix it + if (descent > 0) { + descent = -descent; + } + float scale = ascent - descent < 700 ? ascent - descent : 1000; + descent = descent / scale * gs.GetFontSize(); + ascent = ascent / scale * gs.GetFontSize(); + return new float[] { ascent, descent }; + } } } diff --git a/itext/itext.kernel/itext/kernel/pdf/canvas/parser/listener/LocationTextExtractionStrategy.cs b/itext/itext.kernel/itext/kernel/pdf/canvas/parser/listener/LocationTextExtractionStrategy.cs index b74f434507..8b7768718a 100644 --- a/itext/itext.kernel/itext/kernel/pdf/canvas/parser/listener/LocationTextExtractionStrategy.cs +++ b/itext/itext.kernel/itext/kernel/pdf/canvas/parser/listener/LocationTextExtractionStrategy.cs @@ -314,7 +314,7 @@ internal virtual bool SameLine(LocationTextExtractionStrategy.TextChunk lastChun } } - private class TextChunkLocationDefaultImp : LocationTextExtractionStrategy.ITextChunkLocation { + public class TextChunkLocationDefaultImp : LocationTextExtractionStrategy.ITextChunkLocation { /// the starting location of the chunk private readonly Vector startLocation; diff --git a/itext/itext.kernel/itext/kernel/pdf/canvas/parser/listener/TextMarginFinder.cs b/itext/itext.kernel/itext/kernel/pdf/canvas/parser/listener/TextMarginFinder.cs index 855a495a83..d57a05dff0 100644 --- a/itext/itext.kernel/itext/kernel/pdf/canvas/parser/listener/TextMarginFinder.cs +++ b/itext/itext.kernel/itext/kernel/pdf/canvas/parser/listener/TextMarginFinder.cs @@ -58,12 +58,12 @@ public virtual void EventOccurred(IEventData data, EventType type) { if (type == EventType.RENDER_TEXT) { TextRenderInfo info = (TextRenderInfo)data; if (textRectangle == null) { - textRectangle = info.GetDescentLine().GetBoundingRectange(); + textRectangle = info.GetDescentLine().GetBoundingRectangle(); } else { - textRectangle = Rectangle.GetCommonRectangle(textRectangle, info.GetDescentLine().GetBoundingRectange()); + textRectangle = Rectangle.GetCommonRectangle(textRectangle, info.GetDescentLine().GetBoundingRectangle()); } - textRectangle = Rectangle.GetCommonRectangle(textRectangle, info.GetAscentLine().GetBoundingRectange()); + textRectangle = Rectangle.GetCommonRectangle(textRectangle, info.GetAscentLine().GetBoundingRectangle()); } else { throw new InvalidOperationException(String.Format("Event type not supported: {0}", type)); diff --git a/itext/itext.kernel/itext/kernel/pdf/canvas/parser/util/PdfCanvasParser.cs b/itext/itext.kernel/itext/kernel/pdf/canvas/parser/util/PdfCanvasParser.cs index d3de559299..63311740d7 100644 --- a/itext/itext.kernel/itext/kernel/pdf/canvas/parser/util/PdfCanvasParser.cs +++ b/itext/itext.kernel/itext/kernel/pdf/canvas/parser/util/PdfCanvasParser.cs @@ -160,7 +160,8 @@ public virtual PdfArray ReadArray() { if (tokeniser.GetTokenType() == PdfTokenizer.TokenType.EndArray) { break; } - if (tokeniser.GetTokenType() == PdfTokenizer.TokenType.EndDic) { + if (tokeniser.GetTokenType() == PdfTokenizer.TokenType.EndDic && obj.GetObjectType() != PdfObject.DICTIONARY + ) { tokeniser.ThrowError(PdfException.UnexpectedGtGt); } array.Add(obj); diff --git a/itext/itext.kernel/itext/kernel/pdf/canvas/wmf/WmfImageData.cs b/itext/itext.kernel/itext/kernel/pdf/canvas/wmf/WmfImageData.cs index 14c907beee..5c33f3e640 100644 --- a/itext/itext.kernel/itext/kernel/pdf/canvas/wmf/WmfImageData.cs +++ b/itext/itext.kernel/itext/kernel/pdf/canvas/wmf/WmfImageData.cs @@ -65,7 +65,7 @@ public WmfImageData(Uri url) : base(url, ImageType.WMF) { byte[] imageType = ReadImageType(url); if (!ImageTypeIs(imageType, wmf)) { - throw new PdfException(PdfException.IsNotWmfImage); + throw new PdfException(PdfException.NotAWmfImage); } } @@ -75,7 +75,7 @@ public WmfImageData(byte[] bytes) : base(bytes, ImageType.WMF) { byte[] imageType = ReadImageType(url); if (!ImageTypeIs(imageType, wmf)) { - throw new PdfException(PdfException.IsNotWmfImage); + throw new PdfException(PdfException.NotAWmfImage); } } diff --git a/itext/itext.kernel/itext/kernel/pdf/canvas/wmf/WmfImageHelper.cs b/itext/itext.kernel/itext/kernel/pdf/canvas/wmf/WmfImageHelper.cs index 7ff5658b20..3afbab4a98 100644 --- a/itext/itext.kernel/itext/kernel/pdf/canvas/wmf/WmfImageHelper.cs +++ b/itext/itext.kernel/itext/kernel/pdf/canvas/wmf/WmfImageHelper.cs @@ -83,7 +83,6 @@ public WmfImageHelper(ImageData wmf) { } /// This method checks if the image is a valid WMF and processes some parameters. - /// private void ProcessParameters() { Stream @is = null; try { diff --git a/itext/itext.kernel/itext/kernel/pdf/collection/PdfCollectionField.cs b/itext/itext.kernel/itext/kernel/pdf/collection/PdfCollectionField.cs index c790de38d6..594d527a93 100644 --- a/itext/itext.kernel/itext/kernel/pdf/collection/PdfCollectionField.cs +++ b/itext/itext.kernel/itext/kernel/pdf/collection/PdfCollectionField.cs @@ -220,7 +220,7 @@ public virtual PdfObject GetValue(String value) { return new PdfNumber(System.Double.Parse(value.Trim(), System.Globalization.CultureInfo.InvariantCulture)); } } - throw new PdfException(PdfException.IsNotAnAcceptableValueForTheField).SetMessageParams(value, GetPdfObject + throw new PdfException(PdfException._1IsNotAnAcceptableValueForTheField2).SetMessageParams(value, GetPdfObject ().GetAsName(PdfName.N).GetValue()); } diff --git a/itext/itext.kernel/itext/kernel/pdf/collection/PdfCollectionSort.cs b/itext/itext.kernel/itext/kernel/pdf/collection/PdfCollectionSort.cs index 17dc703d5a..4b3e691763 100644 --- a/itext/itext.kernel/itext/kernel/pdf/collection/PdfCollectionSort.cs +++ b/itext/itext.kernel/itext/kernel/pdf/collection/PdfCollectionSort.cs @@ -86,7 +86,7 @@ public virtual iText.Kernel.Pdf.Collection.PdfCollectionSort SetSortOrder(bool[] PdfObject obj = GetPdfObject().Get(PdfName.S); if (obj.IsArray()) { if (((PdfArray)obj).Size() != ascending.Length) { - throw new PdfException(PdfException.TheNumberOfBooleansInTheArrayDoesntCorrespondWithTheNumberOfFields); + throw new PdfException(PdfException.NumberOfBooleansInTheArrayDoesntCorrespondWithTheNumberOfFields); } GetPdfObject().Put(PdfName.A, new PdfArray(ascending)); return this; diff --git a/itext/itext.kernel/itext/kernel/pdf/colorspace/PdfCieBasedCs.cs b/itext/itext.kernel/itext/kernel/pdf/colorspace/PdfCieBasedCs.cs index 681d6e06ff..8d08ffb732 100644 --- a/itext/itext.kernel/itext/kernel/pdf/colorspace/PdfCieBasedCs.cs +++ b/itext/itext.kernel/itext/kernel/pdf/colorspace/PdfCieBasedCs.cs @@ -49,6 +49,21 @@ source product. namespace iText.Kernel.Pdf.Colorspace { public abstract class PdfCieBasedCs : PdfColorSpace { + /// + /// To manually flush a + /// PdfObject + /// behind this wrapper, you have to ensure + /// that this object is added to the document, i.e. it has an indirect reference. + /// Basically this means that before flushing you need to explicitly call + /// + /// . + /// For example: wrapperInstance.makeIndirect(document).flush(); + /// Note that not every wrapper require this, only those that have such warning in documentation. + /// + public override void Flush() { + base.Flush(); + } + protected internal override bool IsWrappedObjectMustBeIndirect() { return true; } diff --git a/itext/itext.kernel/itext/kernel/pdf/colorspace/PdfColorSpace.cs b/itext/itext.kernel/itext/kernel/pdf/colorspace/PdfColorSpace.cs index 151e33172a..0124d77149 100644 --- a/itext/itext.kernel/itext/kernel/pdf/colorspace/PdfColorSpace.cs +++ b/itext/itext.kernel/itext/kernel/pdf/colorspace/PdfColorSpace.cs @@ -45,6 +45,7 @@ source product. using iText.Kernel.Pdf; namespace iText.Kernel.Pdf.Colorspace { + /// Represents the most common properties of color spaces. public abstract class PdfColorSpace : PdfObjectWrapper { public static readonly ICollection directColorSpaces = new HashSet(iText.IO.Util.JavaUtil.ArraysAsList (PdfName.DeviceGray, PdfName.DeviceRGB, PdfName.DeviceCMYK, PdfName.Pattern)); diff --git a/itext/itext.kernel/itext/kernel/pdf/colorspace/PdfPattern.cs b/itext/itext.kernel/itext/kernel/pdf/colorspace/PdfPattern.cs index c3cf9f5c77..0f0e24b199 100644 --- a/itext/itext.kernel/itext/kernel/pdf/colorspace/PdfPattern.cs +++ b/itext/itext.kernel/itext/kernel/pdf/colorspace/PdfPattern.cs @@ -73,6 +73,21 @@ public virtual void SetMatrix(PdfArray matrix) { SetModified(); } + /// + /// To manually flush a + /// PdfObject + /// behind this wrapper, you have to ensure + /// that this object is added to the document, i.e. it has an indirect reference. + /// Basically this means that before flushing you need to explicitly call + /// + /// . + /// For example: wrapperInstance.makeIndirect(document).flush(); + /// Note that not every wrapper require this, only those that have such warning in documentation. + /// + public override void Flush() { + base.Flush(); + } + protected internal override bool IsWrappedObjectMustBeIndirect() { return true; } diff --git a/itext/itext.kernel/itext/kernel/pdf/colorspace/PdfShading.cs b/itext/itext.kernel/itext/kernel/pdf/colorspace/PdfShading.cs index 8d6b7222be..df6c62cf4e 100644 --- a/itext/itext.kernel/itext/kernel/pdf/colorspace/PdfShading.cs +++ b/itext/itext.kernel/itext/kernel/pdf/colorspace/PdfShading.cs @@ -47,26 +47,61 @@ source product. using iText.Kernel.Pdf.Function; namespace iText.Kernel.Pdf.Colorspace { + /// The abstract PdfShading class that represents the Shading Dictionary PDF object. public abstract class PdfShading : PdfObjectWrapper { + /// + /// constants of shading type + /// ISO-320001 Table 78 + /// + /// private class ShadingType { + /// The int value of function-based shading type public const int FUNCTION_BASED = 1; + /// The int value of axial shading type public const int AXIAL = 2; + /// The int value of radial shading type public const int RADIAL = 3; + /// The int value of free-form Gouraud-shaded triangle mesh shading type public const int FREE_FORM_GOURAUD_SHADED_TRIANGLE_MESH = 4; + /// The int value of lattice-form Gouraud-shaded triangle mesh shading type public const int LATTICE_FORM_GOURAUD_SHADED_TRIANGLE_MESH = 5; + /// The int value of coons patch meshes shading type public const int COONS_PATCH_MESH = 6; + /// The int value of tensor-product patch meshes shading type public const int TENSOR_PRODUCT_PATCH_MESH = 7; } + /// + /// Creates the + /// + /// object from the existing + /// + /// with corresponding type. + /// + /// + /// + /// + /// from which the + /// + /// object will be created. + /// + /// + /// Created + /// + /// object. + /// public static PdfShading MakeShading(PdfDictionary shadingDictionary) { if (!shadingDictionary.ContainsKey(PdfName.ShadingType)) { - throw new PdfException(PdfException.UnexpectedShadingType); + throw new PdfException(PdfException.ShadingTypeNotFound); + } + if (!shadingDictionary.ContainsKey(PdfName.ColorSpace)) { + throw new PdfException(PdfException.ColorSpaceNotFound); } PdfShading shading; switch (shadingDictionary.GetAsNumber(PdfName.ShadingType).IntValue()) { @@ -128,29 +163,78 @@ protected internal PdfShading(PdfDictionary pdfObject) : base(pdfObject) { } + [System.ObsoleteAttribute(@"Use PdfShading(iText.Kernel.Pdf.PdfDictionary, int, PdfColorSpace) instead.")] protected internal PdfShading(PdfDictionary pdfObject, int type, PdfObject colorSpace) : base(pdfObject) { GetPdfObject().Put(PdfName.ShadingType, new PdfNumber(type)); GetPdfObject().Put(PdfName.ColorSpace, colorSpace); } + protected internal PdfShading(PdfDictionary pdfObject, int type, PdfColorSpace colorSpace) + : base(pdfObject) { + GetPdfObject().Put(PdfName.ShadingType, new PdfNumber(type)); + if (colorSpace is PdfSpecialCs.Pattern) { + throw new ArgumentException("colorSpace"); + } + GetPdfObject().Put(PdfName.ColorSpace, colorSpace.GetPdfObject()); + } + + /// Gets the shading type. + /// + /// int value of + /// + /// . + /// public virtual int GetShadingType() { return (int)GetPdfObject().GetAsInt(PdfName.ShadingType); } + /// Gets the color space in which colour values shall be expressed. + /// + /// + /// + /// Color space + /// public virtual PdfObject GetColorSpace() { return GetPdfObject().Get(PdfName.ColorSpace); } + /// + /// Gets the function PdfObject that represents color transitions + /// across the shading geometry. + /// + /// + /// + /// + /// Function + /// public virtual PdfObject GetFunction() { return GetPdfObject().Get(PdfName.Function); } + /// + /// Sets the function that represents color transitions + /// across the shading geometry as one object. + /// + /// + /// The + /// + /// to set. + /// public virtual void SetFunction(PdfFunction function) { GetPdfObject().Put(PdfName.Function, function.GetPdfObject()); SetModified(); } + /// + /// Sets the function object that represents color transitions + /// across the shading geometry as an array of functions. + /// + /// + /// The array of + /// + /// to be set. + /// public virtual void SetFunction(PdfFunction[] functions) { PdfArray arr = new PdfArray(); foreach (PdfFunction func in functions) { @@ -160,38 +244,135 @@ public virtual void SetFunction(PdfFunction[] functions) { SetModified(); } + /// + /// To manually flush a + /// PdfObject + /// behind this wrapper, you have to ensure + /// that this object is added to the document, i.e. it has an indirect reference. + /// Basically this means that before flushing you need to explicitly call + /// + /// . + /// For example: wrapperInstance.makeIndirect(document).flush(); + /// Note that not every wrapper require this, only those that have such warning in documentation. + /// + public override void Flush() { + base.Flush(); + } + protected internal override bool IsWrappedObjectMustBeIndirect() { return true; } + /// + /// The class that extends + /// + /// class and is in charge of Shading Dictionary with function-based type, + /// that defines color at every point in the domain by a specified mathematical function. + /// public class FunctionBased : PdfShading { - public FunctionBased(PdfDictionary pdfObject) - : base(pdfObject) { + /// + /// Creates the new instance of the class from the existing + /// + /// object. + /// + /// + /// + /// + /// from which the instance is created. + /// + [System.ObsoleteAttribute(@"Intended only for private use. You should use PdfShading.MakeShading(iText.Kernel.Pdf.PdfDictionary) instead." + )] + public FunctionBased(PdfDictionary pdfDictionary) + : base(pdfDictionary) { } + /// Creates the new instance of the class. + /// + /// the + /// + /// object in which colour values shall be expressed. + /// + /// + /// the + /// + /// , that is used to calculate color transitions. + /// public FunctionBased(PdfColorSpace colorSpace, PdfFunction function) : this(colorSpace.GetPdfObject(), function) { } + /// Creates the new instance of the class. + /// + /// the + /// + /// , that represents color space in which colour values shall be expressed. + /// + /// + /// the + /// + /// , that is used to calculate color transitions. + /// public FunctionBased(PdfObject colorSpace, PdfFunction function) - : base(new PdfDictionary(), PdfShading.ShadingType.FUNCTION_BASED, colorSpace) { + : base(new PdfDictionary(), PdfShading.ShadingType.FUNCTION_BASED, PdfColorSpace.MakeColorSpace(colorSpace + )) { SetFunction(function); } + /// + /// Gets the + /// + /// domain rectangle object that establishes an internal coordinate space + /// for the shading that is independent of the target coordinate space in which it shall be painted. + /// + /// + /// + /// + /// domain rectangle. + /// public virtual PdfArray GetDomain() { return GetPdfObject().GetAsArray(PdfName.Domain); } + /// + /// Sets the + /// + /// domain rectangle object that establishes an internal coordinate space + /// for the shading that is independent of the target coordinate space in which it shall be painted. + /// + /// the Xmin coordinate of rectangle. + /// the Xmax coordinate of rectangle. + /// the Ymin coordinate of rectangle. + /// the Ymax coordinate of rectangle. public virtual void SetDomain(float xmin, float xmax, float ymin, float ymax) { GetPdfObject().Put(PdfName.Domain, new PdfArray(new float[] { xmin, xmax, ymin, ymax })); SetModified(); } + /// + /// Sets the + /// + /// domain rectangle object that establishes an internal coordinate space + /// for the shading that is independent of the target coordinate space in which it shall be painted. + /// + /// + /// the + /// + /// domain rectangle object to be set. + /// public virtual void SetDomain(PdfArray domain) { GetPdfObject().Put(PdfName.Domain, domain); SetModified(); } + /// + /// Gets the array of floats that represents the transformation matrix that maps the domain rectangle + /// into a corresponding figure in the target coordinate space. + /// + /// + /// the + /// float[] + /// of transformation matrix (identical matrix by default). + /// public virtual float[] GetMatrix() { PdfArray matrix = GetPdfObject().GetAsArray(PdfName.Matrix); if (matrix == null) { @@ -204,59 +385,197 @@ public virtual float[] GetMatrix() { return result; } + /// + /// Sets the array of floats that represents the transformation matrix that maps the domain rectangle + /// into a corresponding figure in the target coordinate space. + /// + /// + /// the + /// float[] + /// of transformation matrix to be set. + /// public virtual void SetMatrix(float[] matrix) { SetMatrix(new PdfArray(matrix)); } + /// + /// Sets the array of floats that represents the transformation matrix that maps the domain rectangle + /// into a corresponding figure in the target coordinate space. + /// + /// + /// the + /// + /// transformation matrix object to be set. + /// public virtual void SetMatrix(PdfArray matrix) { GetPdfObject().Put(PdfName.Matrix, matrix); SetModified(); } } + /// + /// The class that extends + /// + /// class and is in charge of Shading Dictionary with axial type, + /// that define a colour blend that varies along a linear axis between two endpoints + /// and extends indefinitely perpendicular to that axis. + /// public class Axial : PdfShading { + /// + /// Creates the new instance of the class from the existing + /// + /// object. + /// + /// + /// + /// + /// from which the instance is created. + /// + [System.ObsoleteAttribute(@"Intended only for private use. You should use PdfShading.MakeShading(iText.Kernel.Pdf.PdfDictionary) instead." + )] public Axial(PdfDictionary pdfDictionary) : base(pdfDictionary) { } + /// Creates the new instance of the class. + /// + /// the + /// + /// object in which colour values shall be expressed. + /// The special Pattern space isn't excepted. + /// + /// the start coordinate of X axis expressed in the shading's target coordinate space. + /// the start coordinate of Y axis expressed in the shading's target coordinate space. + /// + /// the + /// float[] + /// that represents the color in the start point. + /// + /// the end coordinate of X axis expressed in the shading's target coordinate space. + /// the end coordinate of Y axis expressed in the shading's target coordinate space. + /// + /// the + /// float[] + /// that represents the color in the end point. + /// public Axial(PdfColorSpace cs, float x0, float y0, float[] color0, float x1, float y1, float[] color1) - : base(new PdfDictionary(), PdfShading.ShadingType.AXIAL, cs.GetPdfObject()) { - if (cs is PdfSpecialCs.Pattern) { - throw new ArgumentException("colorSpace"); - } + : base(new PdfDictionary(), PdfShading.ShadingType.AXIAL, cs) { SetCoords(x0, y0, x1, y1); PdfFunction func = new PdfFunction.Type2(new PdfArray(new float[] { 0, 1 }), null, new PdfArray(color0), new PdfArray(color1), new PdfNumber(1)); SetFunction(func); } + /// Creates the new instance of the class. + /// + /// the + /// + /// object in which colour values shall be expressed. + /// The special Pattern space isn't excepted. + /// + /// the start coordinate of X axis expressed in the shading's target coordinate space. + /// the start coordinate of Y axis expressed in the shading's target coordinate space. + /// + /// the + /// float[] + /// that represents the color in the start point. + /// + /// the end coordinate of X axis expressed in the shading's target coordinate space. + /// the end coordinate of Y axis expressed in the shading's target coordinate space. + /// + /// the + /// float[] + /// that represents the color in the end point. + /// + /// + /// the array of two booleans that specified whether to extend the shading + /// beyond the starting and ending points of the axis, respectively. + /// public Axial(PdfColorSpace cs, float x0, float y0, float[] color0, float x1, float y1, float[] color1, bool [] extend) : this(cs, x0, y0, color0, x1, y1, color1) { - if (extend != null) { - SetExtend(extend[0], extend[1]); + if (extend == null || extend.Length != 2) { + throw new ArgumentException("extend"); } - } - + SetExtend(extend[0], extend[1]); + } + + /// Creates the new instance of the class. + /// + /// the + /// + /// object in which colour values shall be expressed. + /// The special Pattern space isn't excepted. + /// + /// + /// the + /// + /// of four number four numbers [x0 y0 x1 y1] that specified the starting + /// and the endings coordinates of thew axis, expressed in the shading's target coordinate space. + /// + /// + /// the + /// + /// object, that is used to calculate color transitions. + /// public Axial(PdfColorSpace cs, PdfArray coords, PdfFunction function) - : base(new PdfDictionary(), PdfShading.ShadingType.AXIAL, cs.GetPdfObject()) { + : base(new PdfDictionary(), PdfShading.ShadingType.AXIAL, cs) { SetCoords(coords); SetFunction(function); } + /// + /// Gets the Coords object - a + /// + /// of four numbers [x0 y0 x1 y1] that specified the starting + /// and the endings coordinates of thew axis, expressed in the shading's target coordinate space. + /// + /// + /// the + /// + /// Coords object. + /// public virtual PdfArray GetCoords() { return GetPdfObject().GetAsArray(PdfName.Coords); } + /// Sets the Choords object with the four params expressed in the shading's target coordinate space. + /// the start coordinate of X axis to be set. + /// the start coordinate of Y axis to be set. + /// the end coordinate of X axis to be set. + /// the end coordinate of Y axis to be set. public virtual void SetCoords(float x0, float y0, float x1, float y1) { SetCoords(new PdfArray(new float[] { x0, y0, x1, y1 })); } + /// + /// Sets the Choords object with the + /// + /// of four numbers [x0 y0 x1 y1], + /// that specified the starting and the endings coordinates of thew axis, + /// expressed in the shading's target coordinate space. + /// + /// + /// the Chords + /// + /// to be set. + /// public virtual void SetCoords(PdfArray coords) { GetPdfObject().Put(PdfName.Coords, coords); SetModified(); } + /// + /// Gets the array of two + /// float + /// [t0, t1] that represent the limiting values of a parametric + /// variable t, that becomes an input of color function(s). + /// + /// + /// + /// float[] + /// of Domain object ([0.0 1.0] by default) + /// public virtual float[] GetDomain() { PdfArray domain = GetPdfObject().GetAsArray(PdfName.Domain); if (domain == null) { @@ -265,66 +584,270 @@ public virtual float[] GetDomain() { return new float[] { domain.GetAsNumber(0).FloatValue(), domain.GetAsNumber(1).FloatValue() }; } + /// + /// Sets the Domain with the array of two + /// float + /// [t0, t1] that represent the limiting values + /// of a parametric variable t, that becomes an input of color function(s). + /// + /// first limit of variable t + /// second limit of variable t public virtual void SetDomain(float t0, float t1) { GetPdfObject().Put(PdfName.Domain, new PdfArray(new float[] { t0, t1 })); SetModified(); } + /// + /// Gets the array of two + /// boolean + /// that specified whether to extend the shading + /// beyond the starting and ending points of the axis, respectively. + /// + /// + /// + /// boolean[] + /// of Extended object ([false false] by default) + /// public virtual bool[] GetExtend() { PdfArray extend = GetPdfObject().GetAsArray(PdfName.Extend); if (extend == null) { - return new bool[] { true, true }; + return new bool[] { false, false }; } return new bool[] { extend.GetAsBoolean(0).GetValue(), extend.GetAsBoolean(1).GetValue() }; } + /// + /// Sets the Extend object with the two + /// boolean + /// value. + /// + /// if true will extend shading beyond the starting point of Coords + /// if true will extend shading beyond the ending point of Coords public virtual void SetExtend(bool extendStart, bool extendEnd) { GetPdfObject().Put(PdfName.Extend, new PdfArray(new bool[] { extendStart, extendEnd })); SetModified(); } } + /// + /// The class that extends + /// + /// class and is in charge of Shading Dictionary with radial type, + /// that define a colour blend that varies between two circles. + /// This type of shading shall not be used with an Indexed colour space + /// public class Radial : PdfShading { + /// + /// Creates the new instance of the class from the existing + /// + /// object. + /// + /// + /// - + /// + /// from which the instance is created. + /// + [System.ObsoleteAttribute(@"Intended only for private use. You should use PdfShading.MakeShading(iText.Kernel.Pdf.PdfDictionary) instead." + )] public Radial(PdfDictionary pdfDictionary) : base(pdfDictionary) { } + /// Creates the new instance of the class. + /// + /// the + /// + /// object in which colour values shall be expressed. + /// The Indexed color space isn't excepted. + /// + /// the X coordinate of starting circle's centre, expressed in in the shading’s target coordinate space. + /// + /// the Y coordinate of starting circle's centre, expressed in in the shading’s target coordinate space. + /// + /// + /// the radius of starting circle's centre, should be greater or equal to 0. + /// If 0 then starting circle is treated as point. + /// If both radii are 0, nothing shall be painted. + /// + /// + /// the + /// float[] + /// that represents the color in the start circle. + /// + /// the X coordinate of ending circle's centre, expressed in in the shading’s target coordinate space. + /// + /// the Y coordinate of ending circle's centre, expressed in in the shading’s target coordinate space. + /// + /// + /// the radius of ending circle's centre, should be greater or equal to 0. + /// If 0 then ending circle is treated as point. + /// If both radii are 0, nothing shall be painted. + /// + /// + /// the + /// float[] + /// that represents the color in the end circle. + /// public Radial(PdfColorSpace cs, float x0, float y0, float r0, float[] color0, float x1, float y1, float r1 , float[] color1) - : base(new PdfDictionary(), PdfShading.ShadingType.RADIAL, cs.GetPdfObject()) { + : base(new PdfDictionary(), PdfShading.ShadingType.RADIAL, cs) { SetCoords(x0, y0, r0, x1, y1, r1); PdfFunction func = new PdfFunction.Type2(new PdfArray(new float[] { 0, 1 }), null, new PdfArray(color0), new PdfArray(color1), new PdfNumber(1)); SetFunction(func); } + /// Creates the new instance of the class. + /// + /// the + /// + /// object in which colour values shall be expressed. + /// The Indexed color space isn't excepted. + /// + /// the X coordinate of starting circle's centre, expressed in in the shading’s target coordinate space. + /// + /// the Y coordinate of starting circle's centre, expressed in in the shading’s target coordinate space. + /// + /// + /// the radius of starting circle's centre, should be greater or equal to 0. + /// If 0 then starting circle is treated as point. + /// If both radii are 0, nothing shall be painted. + /// + /// + /// the + /// float[] + /// that represents the color in the start circle. + /// + /// the X coordinate of ending circle's centre, expressed in in the shading’s target coordinate space. + /// + /// the Y coordinate of ending circle's centre, expressed in in the shading’s target coordinate space. + /// + /// + /// the radius of ending circle's centre, should be greater or equal to 0. + /// If 0 then ending circle is treated as point. + /// If both radii are 0, nothing shall be painted. + /// + /// + /// the + /// float[] + /// that represents the color in the end circle. + /// + /// + /// the array of two + /// boolean + /// that specified whether to extend the shading + /// beyond the starting and ending points of the axis, respectively. + /// public Radial(PdfColorSpace cs, float x0, float y0, float r0, float[] color0, float x1, float y1, float r1 , float[] color1, bool[] extend) : this(cs, x0, y0, r0, color0, x1, y1, r1, color1) { - if (extend != null) { - SetExtend(extend[0], extend[1]); + if (extend == null || extend.Length != 2) { + throw new ArgumentException("extend"); } - } - + SetExtend(extend[0], extend[1]); + } + + /// Creates the new instance of the class. + /// + /// the + /// + /// object in which colour values shall be expressed. + /// The Indexed color space isn't excepted. + /// + /// + /// the + /// + /// of of six numbers [x0 y0 r0 x1 y1 r1], + /// specifying the centres and radii of the starting and ending circles, + /// expressed in the shading’s target coordinate space. + /// The radii r0 and r1 shall both be greater than or equal to 0. + /// If one radius is 0, the corresponding circle shall be treated as a point; + /// if both are 0, nothing shall be painted. + /// + /// + /// the + /// + /// object, that is used to calculate color transitions. + /// public Radial(PdfColorSpace cs, PdfArray coords, PdfFunction function) - : base(new PdfDictionary(), PdfShading.ShadingType.RADIAL, cs.GetPdfObject()) { + : base(new PdfDictionary(), PdfShading.ShadingType.RADIAL, cs) { SetCoords(coords); SetFunction(function); } + /// + /// Gets the coords + /// + /// object - an array of six numbers [x0 y0 r0 x1 y1 r1], + /// specifying the centres and radii of the starting and ending circles, + /// expressed in the shading’s target coordinate space. + /// The radii r0 and r1 shall both be greater than or equal to 0. + /// If one radius is 0, the corresponding circle shall be treated as a point; + /// if both are 0, nothing shall be painted. + /// + /// + /// the + /// + /// coords object. + /// public virtual PdfArray GetCoords() { return GetPdfObject().GetAsArray(PdfName.Coords); } + /// Sets the coords object. + /// the X coordinate of starting circle's centre, expressed in in the shading’s target coordinate space. + /// + /// the Y coordinate of starting circle's centre, expressed in in the shading’s target coordinate space. + /// + /// + /// the radius of starting circle's centre, should be greater or equal to 0. + /// If 0 then starting circle is treated as point. + /// If both radii are 0, nothing shall be painted. + /// + /// the X coordinate of ending circle's centre, expressed in in the shading’s target coordinate space. + /// + /// the Y coordinate of ending circle's centre, expressed in in the shading’s target coordinate space. + /// + /// + /// the radius of ending circle's centre, should be greater or equal to 0. + /// If 0 then ending circle is treated as point. + /// If both radii are 0, nothing shall be painted. + /// public virtual void SetCoords(float x0, float y0, float r0, float x1, float y1, float r1) { SetCoords(new PdfArray(new float[] { x0, y0, r0, x1, y1, r1 })); } + /// + /// Sets the coords + /// + /// object - an array of six numbers [x0 y0 r0 x1 y1 r1], + /// specifying the centres and radii of the starting and ending circles, + /// expressed in the shading’s target coordinate space. + /// The radii r0 and r1 shall both be greater than or equal to 0. + /// If one radius is 0, the corresponding circle shall be treated as a point; + /// if both are 0, nothing shall be painted. + /// + /// + /// - + /// + /// choords object to be set. + /// public virtual void SetCoords(PdfArray coords) { GetPdfObject().Put(PdfName.Coords, coords); SetModified(); } + /// + /// Gets the array of two + /// float + /// [t0, t1] that represent the limiting values of a parametric + /// variable t, that becomes an input of color function(s). + /// + /// + /// + /// float[] + /// of Domain object ([0.0 1.0] by default) + /// public virtual float[] GetDomain() { PdfArray domain = GetPdfObject().GetAsArray(PdfName.Domain); if (domain == null) { @@ -333,257 +856,864 @@ public virtual float[] GetDomain() { return new float[] { domain.GetAsNumber(0).FloatValue(), domain.GetAsNumber(1).FloatValue() }; } + /// + /// Sets the Domain with the array of two + /// float + /// [t0, t1] that represent the limiting values + /// of a parametric variable t, that becomes an input of color function(s). + /// + /// first limit of variable t + /// second limit of variable t public virtual void SetDomain(float t0, float t1) { GetPdfObject().Put(PdfName.Domain, new PdfArray(new float[] { t0, t1 })); SetModified(); } + /// + /// Gets the array of two + /// boolean + /// that specified whether to extend the shading + /// beyond the starting and ending circles of the axis, respectively. + /// + /// + /// + /// boolean[] + /// of Extended object ([false false] by default) + /// public virtual bool[] GetExtend() { PdfArray extend = GetPdfObject().GetAsArray(PdfName.Extend); if (extend == null) { - return new bool[] { true, true }; + return new bool[] { false, false }; } return new bool[] { extend.GetAsBoolean(0).GetValue(), extend.GetAsBoolean(1).GetValue() }; } + /// + /// Sets the Extend object with the two + /// boolean + /// value. + /// + /// if true will extend shading beyond the starting circle of Coords. + /// if true will extend shading beyond the ending circle of Coords. public virtual void SetExtend(bool extendStart, bool extendEnd) { GetPdfObject().Put(PdfName.Extend, new PdfArray(new bool[] { extendStart, extendEnd })); SetModified(); } } + /// + /// The class that extends + /// + /// class and is in charge of Shading Dictionary with + /// free-form Gouraud-shaded triangle mesh type. + /// The area to be shaded is defined by a path composed entirely of triangles. + /// The colour at each vertex of the triangles is specified, + /// and a technique known as Gouraud interpolation is used to colour the interiors. + /// The object shall be represented as stream containing a sequence of vertex data. + /// Each vertex is specified by the following values, in the order shown: + /// f x y c1 … cn where: + /// f - the vertex’s edge flag, that determines the vertex is connected to other vertices of the triangle mesh. + /// For full description + /// ISO-320001 Paragph 8.7.4.5.5 + /// x, y - vertex’s horizontal and vertical coordinates, expressed in the shading’s target coordinate space. + /// c1…cn - vertex’s colour components. + /// If the shading dictionary includes a Function entry, only a single parametric value, t, + /// shall be specified for each vertex in place of the colour components c1…cn. + /// public class FreeFormGouraudShadedTriangleMesh : PdfShading { + /// + /// Creates the new instance of the class from the existing + /// + /// object. + /// + /// + /// + /// + /// from which the instance is created. + /// + [System.ObsoleteAttribute(@"Intended only for private use. You should use PdfShading.MakeShading(iText.Kernel.Pdf.PdfDictionary) instead." + )] public FreeFormGouraudShadedTriangleMesh(PdfStream pdfStream) : base(pdfStream) { } + /// Creates the new instance of the class. + /// + /// the + /// + /// object in which colour values shall be expressed. + /// The special Pattern space isn't excepted. + /// + /// + /// the number of bits used to represent each vertex coordinate. + /// The value shall be 1, 2, 4, 8, 12, 16, 24, or 32. + /// + /// + /// the number of bits used to represent each colour component. + /// The value shall be 1, 2, 4, 8, 12, or 16. + /// + /// + /// the number of bits used to represent the edge flag for each vertex. + /// The value of BitsPerFlag shall be 2, 4, or 8, + /// but only the least significant 2 bits in each flag value shall be used. + /// The value for the edge flag shall be 0, 1, or 2. + /// + /// + /// the + /// int[] + /// of numbers specifying how to map vertex coordinates and colour components + /// into the appropriate ranges of values. The ranges shall be specified as follows: + /// [x_min x_max y_min y_max c1_min c1_max … cn_min cn_max]. + /// Only one pair of color values shall be specified if a Function entry is present. + /// public FreeFormGouraudShadedTriangleMesh(PdfColorSpace cs, int bitsPerCoordinate, int bitsPerComponent, int bitsPerFlag, float[] decode) : this(cs, bitsPerCoordinate, bitsPerComponent, bitsPerFlag, new PdfArray(decode)) { } + /// Creates the new instance of the class. + /// + /// the + /// + /// object in which colour values shall be expressed. + /// The special Pattern space isn't excepted. + /// + /// + /// the number of bits used to represent each vertex coordinate. + /// The value shall be 1, 2, 4, 8, 12, 16, 24, or 32. + /// + /// + /// the number of bits used to represent each colour component. + /// The value shall be 1, 2, 4, 8, 12, or 16. + /// + /// + /// the number of bits used to represent the edge flag for each vertex. + /// The value of BitsPerFlag shall be 2, 4, or 8, + /// but only the least significant 2 bits in each flag value shall be used. + /// The value for the edge flag shall be 0, 1, or 2. + /// + /// + /// the + /// + /// of numbers specifying how to map vertex coordinates and colour components + /// into the appropriate ranges of values. The ranges shall be specified as follows: + /// [x_min x_max y_min y_max c1_min c1_max … cn_min cn_max]. + /// Only one pair of color values shall be specified if a Function entry is present. + /// public FreeFormGouraudShadedTriangleMesh(PdfColorSpace cs, int bitsPerCoordinate, int bitsPerComponent, int bitsPerFlag, PdfArray decode) - : base(new PdfStream(), PdfShading.ShadingType.FREE_FORM_GOURAUD_SHADED_TRIANGLE_MESH, cs.GetPdfObject()) { + : base(new PdfStream(), PdfShading.ShadingType.FREE_FORM_GOURAUD_SHADED_TRIANGLE_MESH, cs) { SetBitsPerCoordinate(bitsPerCoordinate); SetBitsPerComponent(bitsPerComponent); SetBitsPerFlag(bitsPerFlag); SetDecode(decode); } + /// Gets the number of bits used to represent each vertex coordinate. + /// the number of bits. Can be 1, 2, 4, 8, 12, 16, 24, or 32. public virtual int GetBitsPerCoordinate() { return (int)GetPdfObject().GetAsInt(PdfName.BitsPerCoordinate); } + /// Sets the number of bits used to represent each vertex coordinate. + /// the number of bits to be set. Shall be 1, 2, 4, 8, 12, 16, 24, or 32. public virtual void SetBitsPerCoordinate(int bitsPerCoordinate) { GetPdfObject().Put(PdfName.BitsPerCoordinate, new PdfNumber(bitsPerCoordinate)); SetModified(); } + /// Gets the number of bits used to represent each colour component. + /// the number of bits. Can be 1, 2, 4, 8, 12, or 16. public virtual int GetBitsPerComponent() { return (int)GetPdfObject().GetAsInt(PdfName.BitsPerComponent); } + /// Sets the number of bits used to represent each colour component. + /// the number of bits to be set. Shall be 1, 2, 4, 8, 12, or 16. public virtual void SetBitsPerComponent(int bitsPerComponent) { GetPdfObject().Put(PdfName.BitsPerComponent, new PdfNumber(bitsPerComponent)); SetModified(); } + /// Gets the number of bits used to represent the edge flag for each vertex. + /// + /// Gets the number of bits used to represent the edge flag for each vertex. + /// But only the least significant 2 bits in each flag value shall be used. + /// The valid flag values are 0, 1 or 2. + /// + /// the number of bits. Can be 2, 4 or 8. public virtual int GetBitsPerFlag() { return (int)GetPdfObject().GetAsInt(PdfName.BitsPerFlag); } + /// Sets the number of bits used to represent the edge flag for each vertex. + /// + /// Sets the number of bits used to represent the edge flag for each vertex. + /// But only the least significant 2 bits in each flag value shall be used. + /// The valid flag values are 0, 1 or 2. + /// + /// the number of bits to be set. Shall be 2, 4 or 8. public virtual void SetBitsPerFlag(int bitsPerFlag) { GetPdfObject().Put(PdfName.BitsPerFlag, new PdfNumber(bitsPerFlag)); SetModified(); } + /// + /// Gets the + /// + /// of numbers specifying how to map vertex coordinates and colour components + /// into the appropriate ranges of values. The ranges shall be specified as follows: + /// [x_min x_max y_min y_max c1_min c1_max … cn_min cn_max]. + /// Only one pair of color values shall be specified if a Function entry is present. + /// + /// + /// the + /// + /// Decode object. + /// public virtual PdfArray GetDecode() { return GetPdfObject().GetAsArray(PdfName.Decode); } + /// + /// Sets the + /// float[] + /// of numbers specifying how to map vertex coordinates and colour components + /// into the appropriate ranges of values. The ranges shall be specified as follows: + /// [x_min x_max y_min y_max c1_min c1_max … cn_min cn_max]. + /// Only one pair of color values shall be specified if a Function entry is present. + /// + /// + /// the + /// float[] + /// of Decode object to set. + /// public virtual void SetDecode(float[] decode) { GetPdfObject().Put(PdfName.Decode, new PdfArray(decode)); } + /// + /// Sets the + /// + /// of numbers specifying how to map vertex coordinates and colour components + /// into the appropriate ranges of values. The ranges shall be specified as follows: + /// [x_min x_max y_min y_max c1_min c1_max … cn_min cn_max]. + /// Only one pair of color values shall be specified if a Function entry is present. + /// + /// + /// the + /// + /// Decode object to set. + /// public virtual void SetDecode(PdfArray decode) { GetPdfObject().Put(PdfName.Decode, decode); } } + /// + /// The class that extends + /// + /// class and is in charge of Shading Dictionary with + /// lattice-form Gouraud-shaded triangle mesh type. + /// This type is similar to + /// + /// but instead of using free-form geometry, + /// the vertices are arranged in a pseudorectangular lattice, + /// which is topologically equivalent to a rectangular grid. + /// The vertices are organized into rows, which need not be geometrically linear. + /// The verticals data in stream is similar to + /// + /// , + /// except there is no edge flag. + /// public class LatticeFormGouraudShadedTriangleMesh : PdfShading { + /// + /// Creates the new instance of the class from the existing + /// + /// object. + /// + /// + /// + /// + /// from which the instance is created. + /// + [System.ObsoleteAttribute(@"Intended only for private use. You should use PdfShading.MakeShading(iText.Kernel.Pdf.PdfDictionary) instead." + )] public LatticeFormGouraudShadedTriangleMesh(PdfStream pdfStream) : base(pdfStream) { } + /// Creates the new instance of the class. + /// + /// the + /// + /// object in which colour values shall be expressed. + /// The special Pattern space isn't excepted. + /// + /// + /// the number of bits used to represent each vertex coordinate. + /// The value shall be 1, 2, 4, 8, 12, 16, 24, or 32. + /// + /// + /// the number of bits used to represent each colour component. + /// The value shall be 1, 2, 4, 8, 12, or 16. + /// + /// + /// the number of vertices in each row of the lattice (shall be > 1). + /// The number of rows need not be specified. + /// + /// + /// the + /// int[] + /// of numbers specifying how to map vertex coordinates and colour components + /// into the appropriate ranges of values. The ranges shall be specified as follows: + /// [x_min x_max y_min y_max c1_min c1_max … cn_min cn_max]. + /// Only one pair of color values shall be specified if a Function entry is present. + /// public LatticeFormGouraudShadedTriangleMesh(PdfColorSpace cs, int bitsPerCoordinate, int bitsPerComponent, int verticesPerRow, float[] decode) : this(cs, bitsPerCoordinate, bitsPerComponent, verticesPerRow, new PdfArray(decode)) { } + /// Creates the new instance of the class. + /// + /// the + /// + /// object in which colour values shall be expressed. + /// The special Pattern space isn't excepted. + /// + /// + /// the number of bits used to represent each vertex coordinate. + /// The value shall be 1, 2, 4, 8, 12, 16, 24, or 32. + /// + /// + /// the number of bits used to represent each colour component. + /// The value shall be 1, 2, 4, 8, 12, or 16. + /// + /// + /// the number of vertices in each row of the lattice (shall be > 1). + /// The number of rows need not be specified. + /// + /// + /// the + /// + /// of numbers specifying how to map vertex coordinates and colour components + /// into the appropriate ranges of values. The ranges shall be specified as follows: + /// [x_min x_max y_min y_max c1_min c1_max … cn_min cn_max]. + /// Only one pair of color values shall be specified if a Function entry is present. + /// public LatticeFormGouraudShadedTriangleMesh(PdfColorSpace cs, int bitsPerCoordinate, int bitsPerComponent, int verticesPerRow, PdfArray decode) - : base(new PdfStream(), PdfShading.ShadingType.LATTICE_FORM_GOURAUD_SHADED_TRIANGLE_MESH, cs.GetPdfObject( - )) { + : base(new PdfStream(), PdfShading.ShadingType.LATTICE_FORM_GOURAUD_SHADED_TRIANGLE_MESH, cs) { SetBitsPerCoordinate(bitsPerCoordinate); SetBitsPerComponent(bitsPerComponent); SetVerticesPerRow(verticesPerRow); SetDecode(decode); } + /// Gets the number of bits used to represent each vertex coordinate. + /// the number of bits. Can be 1, 2, 4, 8, 12, 16, 24, or 32. public virtual int GetBitsPerCoordinate() { return (int)GetPdfObject().GetAsInt(PdfName.BitsPerCoordinate); } + /// Sets the number of bits used to represent each vertex coordinate. + /// the number of bits to be set. Shall be 1, 2, 4, 8, 12, 16, 24, or 32. public virtual void SetBitsPerCoordinate(int bitsPerCoordinate) { GetPdfObject().Put(PdfName.BitsPerCoordinate, new PdfNumber(bitsPerCoordinate)); SetModified(); } + /// Gets the number of bits used to represent each colour component. + /// the number of bits. Can be 1, 2, 4, 8, 12, or 16. public virtual int GetBitsPerComponent() { return (int)GetPdfObject().GetAsInt(PdfName.BitsPerComponent); } + /// Sets the number of bits used to represent each colour component. + /// the number of bits to be set. Shall be 1, 2, 4, 8, 12, or 16. public virtual void SetBitsPerComponent(int bitsPerComponent) { GetPdfObject().Put(PdfName.BitsPerComponent, new PdfNumber(bitsPerComponent)); SetModified(); } + /// Gets the number of vertices in each row of the lattice. + /// the number of vertices. Can only be greater than 1. public virtual int GetVerticesPerRow() { return (int)GetPdfObject().GetAsInt(PdfName.VerticesPerRow); } + /// Sets the number of vertices in each row of the lattice. + /// + /// Sets the number of vertices in each row of the lattice. + /// The number of rows need not be specified. + /// + /// the number of vertices to be set. Shall be greater than 1. public virtual void SetVerticesPerRow(int verticesPerRow) { GetPdfObject().Put(PdfName.VerticesPerRow, new PdfNumber(verticesPerRow)); SetModified(); } + /// + /// Gets the + /// + /// of numbers specifying how to map vertex coordinates and colour components + /// into the appropriate ranges of values. The ranges shall be specified as follows: + /// [x_min x_max y_min y_max c1_min c1_max … cn_min cn_max]. + /// Only one pair of color values shall be specified if a Function entry is present. + /// + /// + /// the + /// + /// Decode object. + /// public virtual PdfArray GetDecode() { return GetPdfObject().GetAsArray(PdfName.Decode); } + /// + /// Sets the + /// float[] + /// of numbers specifying how to map vertex coordinates and colour components + /// into the appropriate ranges of values. The ranges shall be specified as follows: + /// [x_min x_max y_min y_max c1_min c1_max … cn_min cn_max]. + /// Only one pair of color values shall be specified if a Function entry is present. + /// + /// + /// the + /// float[] + /// of Decode object to set. + /// public virtual void SetDecode(float[] decode) { GetPdfObject().Put(PdfName.Decode, new PdfArray(decode)); } + /// + /// Sets the + /// + /// of numbers specifying how to map vertex coordinates and colour components + /// into the appropriate ranges of values. The ranges shall be specified as follows: + /// [x_min x_max y_min y_max c1_min c1_max … cn_min cn_max]. + /// Only one pair of color values shall be specified if a Function entry is present. + /// + /// + /// the + /// + /// Decode object to set. + /// public virtual void SetDecode(PdfArray decode) { GetPdfObject().Put(PdfName.Decode, decode); } } + /// + /// The class that extends + /// + /// class and is in charge of Shading Dictionary with + /// Coons Patch mesh type. + /// This type of shading is constructed from one or more colour patches, each bounded by four cubic Bézier curves. + /// Degenerate Bézier curves are allowed and are useful for certain graphical effects. + /// At least one complete patch shall be specified. + /// The shape of patch is defined by 12 control points. + /// Colours are specified for each corner of the unit square, + /// and bilinear interpolation is used to fill in colours over the entire unit square. + /// Coordinates are mapped from the unit square into a four-sided patch whose sides are not necessarily linear. + /// The mapping is continuous: the corners of the unit square map to corners of the patch + /// and the sides of the unit square map to sides of the patch. + /// For the format of data stream, that defines patches + /// ISO-320001 Table 85 + /// . + /// If the shading dictionary contains a Function entry, the colour data for each corner of a patch + /// shall be specified by a single parametric value t rather than by n separate colour components c1…cn. + /// public class CoonsPatchMesh : PdfShading { + /// + /// Creates the new instance of the class from the existing + /// + /// object. + /// + /// + /// + /// + /// from which the instance is created. + /// + [System.ObsoleteAttribute(@"Intended only for private use. You should use PdfShading.MakeShading(iText.Kernel.Pdf.PdfDictionary) instead." + )] public CoonsPatchMesh(PdfStream pdfStream) : base(pdfStream) { } + /// Creates the new instance of the class. + /// + /// the + /// + /// object in which colour values shall be expressed. + /// The special Pattern space isn't excepted. + /// + /// + /// the number of bits used to represent each vertex coordinate. + /// The value shall be 1, 2, 4, 8, 12, 16, 24, or 32. + /// + /// + /// the number of bits used to represent each colour component. + /// The value shall be 1, 2, 4, 8, 12, or 16. + /// + /// + /// the number of bits used to represent the edge flag for each vertex. + /// The value of BitsPerFlag shall be 2, 4, or 8, + /// but only the least significant 2 bits in each flag value shall be used. + /// The value for the edge flag shall be 0, 1, 2 or 3. + /// + /// + /// the + /// int[] + /// of numbers specifying how to map vertex coordinates and colour components + /// into the appropriate ranges of values. The ranges shall be specified as follows: + /// [x_min x_max y_min y_max c1_min c1_max … cn_min cn_max]. + /// Only one pair of color values shall be specified if a Function entry is present. + /// public CoonsPatchMesh(PdfColorSpace cs, int bitsPerCoordinate, int bitsPerComponent, int bitsPerFlag, float [] decode) : this(cs, bitsPerCoordinate, bitsPerComponent, bitsPerFlag, new PdfArray(decode)) { } + /// Creates the new instance of the class. + /// + /// the + /// + /// object in which colour values shall be expressed. + /// The special Pattern space isn't excepted. + /// + /// + /// the number of bits used to represent each vertex coordinate. + /// The value shall be 1, 2, 4, 8, 12, 16, 24, or 32. + /// + /// + /// the number of bits used to represent each colour component. + /// The value shall be 1, 2, 4, 8, 12, or 16. + /// + /// + /// the number of bits used to represent the edge flag for each vertex. + /// The value of BitsPerFlag shall be 2, 4, or 8, + /// but only the least significant 2 bits in each flag value shall be used. + /// The value for the edge flag shall be 0, 1, 2 or 3. + /// + /// + /// the + /// + /// of numbers specifying how to map vertex coordinates and colour components + /// into the appropriate ranges of values. The ranges shall be specified as follows: + /// [x_min x_max y_min y_max c1_min c1_max … cn_min cn_max]. + /// Only one pair of color values shall be specified if a Function entry is present. + /// public CoonsPatchMesh(PdfColorSpace cs, int bitsPerCoordinate, int bitsPerComponent, int bitsPerFlag, PdfArray decode) - : base(new PdfStream(), PdfShading.ShadingType.COONS_PATCH_MESH, cs.GetPdfObject()) { + : base(new PdfStream(), PdfShading.ShadingType.COONS_PATCH_MESH, cs) { SetBitsPerCoordinate(bitsPerCoordinate); SetBitsPerComponent(bitsPerComponent); SetBitsPerFlag(bitsPerFlag); SetDecode(decode); } + /// Gets the number of bits used to represent each vertex coordinate. + /// the number of bits. Can be 1, 2, 4, 8, 12, 16, 24, or 32. public virtual int GetBitsPerCoordinate() { return (int)GetPdfObject().GetAsInt(PdfName.BitsPerCoordinate); } + /// Sets the number of bits used to represent each vertex coordinate. + /// the number of bits to be set. Shall be 1, 2, 4, 8, 12, 16, 24, or 32. public virtual void SetBitsPerCoordinate(int bitsPerCoordinate) { GetPdfObject().Put(PdfName.BitsPerCoordinate, new PdfNumber(bitsPerCoordinate)); SetModified(); } + /// Gets the number of bits used to represent each colour component. + /// the number of bits. Can be 1, 2, 4, 8, 12, or 16. public virtual int GetBitsPerComponent() { return (int)GetPdfObject().GetAsInt(PdfName.BitsPerComponent); } + /// Sets the number of bits used to represent each colour component. + /// the number of bits to be set. Shall be 1, 2, 4, 8, 12, or 16. public virtual void SetBitsPerComponent(int bitsPerComponent) { GetPdfObject().Put(PdfName.BitsPerComponent, new PdfNumber(bitsPerComponent)); SetModified(); } + /// Gets the number of bits used to represent the edge flag for each vertex. + /// + /// Gets the number of bits used to represent the edge flag for each vertex. + /// But only the least significant 2 bits in each flag value shall be used. + /// The valid flag values are 0, 1, 2 or 3. + /// + /// the number of bits. Can be 2, 4 or 8. public virtual int GetBitsPerFlag() { return (int)GetPdfObject().GetAsInt(PdfName.BitsPerFlag); } + /// Sets the number of bits used to represent the edge flag for each vertex. + /// + /// Sets the number of bits used to represent the edge flag for each vertex. + /// But only the least significant 2 bits in each flag value shall be used. + /// The valid flag values are 0, 1, 2 or 3. + /// + /// the number of bits to be set. Shall be 2, 4 or 8. public virtual void SetBitsPerFlag(int bitsPerFlag) { GetPdfObject().Put(PdfName.BitsPerFlag, new PdfNumber(bitsPerFlag)); SetModified(); } + /// + /// Gets the + /// + /// of numbers specifying how to map vertex coordinates and colour components + /// into the appropriate ranges of values. The ranges shall be specified as follows: + /// [x_min x_max y_min y_max c1_min c1_max … cn_min cn_max]. + /// Only one pair of color values shall be specified if a Function entry is present. + /// + /// + /// the + /// + /// Decode object. + /// public virtual PdfArray GetDecode() { return GetPdfObject().GetAsArray(PdfName.Decode); } + /// + /// Sets the + /// float[] + /// of numbers specifying how to map vertex coordinates and colour components + /// into the appropriate ranges of values. The ranges shall be specified as follows: + /// [x_min x_max y_min y_max c1_min c1_max … cn_min cn_max]. + /// Only one pair of color values shall be specified if a Function entry is present. + /// + /// + /// the + /// float[] + /// of Decode object to set. + /// public virtual void SetDecode(float[] decode) { GetPdfObject().Put(PdfName.Decode, new PdfArray(decode)); } + /// + /// Sets the + /// + /// of numbers specifying how to map vertex coordinates and colour components + /// into the appropriate ranges of values. The ranges shall be specified as follows: + /// [x_min x_max y_min y_max c1_min c1_max … cn_min cn_max]. + /// Only one pair of color values shall be specified if a Function entry is present. + /// + /// + /// the + /// + /// Decode object to set. + /// public virtual void SetDecode(PdfArray decode) { GetPdfObject().Put(PdfName.Decode, decode); } } + /// + /// The class that extends + /// + /// class and is in charge of Shading Dictionary with + /// Tensor-Product Patch mesh type. + /// This type of shading is identical to + /// + /// , except that it's based on a + /// bicubic tensor-product patch defined by 16 control points. + /// For the format of data stream, that defines patches + /// ISO-320001 Table 86 + /// . + /// public class TensorProductPatchMesh : PdfShading { + /// + /// Creates the new instance of the class from the existing + /// + /// object. + /// + /// + /// + /// + /// from which the instance is created. + /// + [System.ObsoleteAttribute(@"Intended only for private use. You should use PdfShading.MakeShading(iText.Kernel.Pdf.PdfDictionary) instead." + )] public TensorProductPatchMesh(PdfStream pdfStream) : base(pdfStream) { } + /// Creates the new instance of the class. + /// + /// the + /// + /// object in which colour values shall be expressed. + /// The special Pattern space isn't excepted. + /// + /// + /// the number of bits used to represent each vertex coordinate. + /// The value shall be 1, 2, 4, 8, 12, 16, 24, or 32. + /// + /// + /// the number of bits used to represent each colour component. + /// The value shall be 1, 2, 4, 8, 12, or 16. + /// + /// + /// the number of bits used to represent the edge flag for each vertex. + /// The value of BitsPerFlag shall be 2, 4, or 8, + /// but only the least significant 2 bits in each flag value shall be used. + /// The value for the edge flag shall be 0, 1, 2 or 3. + /// + /// + /// the + /// int[] + /// of numbers specifying how to map vertex coordinates and colour components + /// into the appropriate ranges of values. The ranges shall be specified as follows: + /// [x_min x_max y_min y_max c1_min c1_max … cn_min cn_max]. + /// Only one pair of color values shall be specified if a Function entry is present. + /// public TensorProductPatchMesh(PdfColorSpace cs, int bitsPerCoordinate, int bitsPerComponent, int bitsPerFlag , float[] decode) : this(cs, bitsPerCoordinate, bitsPerComponent, bitsPerFlag, new PdfArray(decode)) { } + /// Creates the new instance of the class. + /// + /// the + /// + /// object in which colour values shall be expressed. + /// The special Pattern space isn't excepted. + /// + /// + /// the number of bits used to represent each vertex coordinate. + /// The value shall be 1, 2, 4, 8, 12, 16, 24, or 32. + /// + /// + /// the number of bits used to represent each colour component. + /// The value shall be 1, 2, 4, 8, 12, or 16. + /// + /// + /// the number of bits used to represent the edge flag for each vertex. + /// The value of BitsPerFlag shall be 2, 4, or 8, + /// but only the least significant 2 bits in each flag value shall be used. + /// The value for the edge flag shall be 0, 1, 2 or 3. + /// + /// + /// the + /// + /// of numbers specifying how to map vertex coordinates and colour components + /// into the appropriate ranges of values. The ranges shall be specified as follows: + /// [x_min x_max y_min y_max c1_min c1_max … cn_min cn_max]. + /// Only one pair of color values shall be specified if a Function entry is present. + /// public TensorProductPatchMesh(PdfColorSpace cs, int bitsPerCoordinate, int bitsPerComponent, int bitsPerFlag , PdfArray decode) - : base(new PdfStream(), PdfShading.ShadingType.TENSOR_PRODUCT_PATCH_MESH, cs.GetPdfObject()) { + : base(new PdfStream(), PdfShading.ShadingType.TENSOR_PRODUCT_PATCH_MESH, cs) { SetBitsPerCoordinate(bitsPerCoordinate); SetBitsPerComponent(bitsPerComponent); SetBitsPerFlag(bitsPerFlag); SetDecode(decode); } + /// Gets the number of bits used to represent each vertex coordinate. + /// the number of bits. Can be 1, 2, 4, 8, 12, 16, 24, or 32. public virtual int GetBitsPerCoordinate() { return (int)GetPdfObject().GetAsInt(PdfName.BitsPerCoordinate); } + /// Sets the number of bits used to represent each vertex coordinate. + /// the number of bits to be set. Shall be 1, 2, 4, 8, 12, 16, 24, or 32. public virtual void SetBitsPerCoordinate(int bitsPerCoordinate) { GetPdfObject().Put(PdfName.BitsPerCoordinate, new PdfNumber(bitsPerCoordinate)); SetModified(); } + /// Gets the number of bits used to represent each colour component. + /// the number of bits. Can be 1, 2, 4, 8, 12, or 16. public virtual int GetBitsPerComponent() { return (int)GetPdfObject().GetAsInt(PdfName.BitsPerComponent); } + /// Sets the number of bits used to represent each colour component. + /// the number of bits to be set. Shall be 1, 2, 4, 8, 12, or 16. public virtual void SetBitsPerComponent(int bitsPerComponent) { GetPdfObject().Put(PdfName.BitsPerComponent, new PdfNumber(bitsPerComponent)); SetModified(); } + /// Gets the number of bits used to represent the edge flag for each vertex. + /// + /// Gets the number of bits used to represent the edge flag for each vertex. + /// But only the least significant 2 bits in each flag value shall be used. + /// The valid flag values are 0, 1, 2 or 3. + /// + /// the number of bits. Can be 2, 4 or 8. public virtual int GetBitsPerFlag() { return (int)GetPdfObject().GetAsInt(PdfName.BitsPerFlag); } + /// Sets the number of bits used to represent the edge flag for each vertex. + /// + /// Sets the number of bits used to represent the edge flag for each vertex. + /// But only the least significant 2 bits in each flag value shall be used. + /// The valid flag values are 0, 1, 2 or 3. + /// + /// the number of bits to be set. Shall be 2, 4 or 8. public virtual void SetBitsPerFlag(int bitsPerFlag) { GetPdfObject().Put(PdfName.BitsPerFlag, new PdfNumber(bitsPerFlag)); SetModified(); } + /// + /// Gets the + /// + /// of numbers specifying how to map vertex coordinates and colour components + /// into the appropriate ranges of values. The ranges shall be specified as follows: + /// [x_min x_max y_min y_max c1_min c1_max … cn_min cn_max]. + /// Only one pair of color values shall be specified if a Function entry is present. + /// + /// + /// the + /// + /// Decode object. + /// public virtual PdfArray GetDecode() { return GetPdfObject().GetAsArray(PdfName.Decode); } + /// + /// Sets the + /// float[] + /// of numbers specifying how to map vertex coordinates and colour components + /// into the appropriate ranges of values. The ranges shall be specified as follows: + /// [x_min x_max y_min y_max c1_min c1_max … cn_min cn_max]. + /// Only one pair of color values shall be specified if a Function entry is present. + /// + /// + /// the + /// float[] + /// of Decode object to set. + /// public virtual void SetDecode(float[] decode) { GetPdfObject().Put(PdfName.Decode, new PdfArray(decode)); } + /// + /// Sets the + /// + /// of numbers specifying how to map vertex coordinates and colour components + /// into the appropriate ranges of values. The ranges shall be specified as follows: + /// [x_min x_max y_min y_max c1_min c1_max … cn_min cn_max]. + /// Only one pair of color values shall be specified if a Function entry is present. + /// + /// + /// the + /// + /// Decode object to set. + /// public virtual void SetDecode(PdfArray decode) { GetPdfObject().Put(PdfName.Decode, decode); } diff --git a/itext/itext.kernel/itext/kernel/pdf/colorspace/PdfSpecialCs.cs b/itext/itext.kernel/itext/kernel/pdf/colorspace/PdfSpecialCs.cs index 7bce84ce70..465bed14e5 100644 --- a/itext/itext.kernel/itext/kernel/pdf/colorspace/PdfSpecialCs.cs +++ b/itext/itext.kernel/itext/kernel/pdf/colorspace/PdfSpecialCs.cs @@ -53,6 +53,21 @@ protected internal PdfSpecialCs(PdfArray pdfObject) : base(pdfObject) { } + /// + /// To manually flush a + /// PdfObject + /// behind this wrapper, you have to ensure + /// that this object is added to the document, i.e. it has an indirect reference. + /// Basically this means that before flushing you need to explicitly call + /// + /// . + /// For example: wrapperInstance.makeIndirect(document).flush(); + /// Note that not every wrapper require this, only those that have such warning in documentation. + /// + public override void Flush() { + base.Flush(); + } + protected internal override bool IsWrappedObjectMustBeIndirect() { return true; } @@ -212,6 +227,21 @@ public override int GetNumberOfComponents() { } public class UncoloredTilingPattern : PdfSpecialCs.Pattern { + /// + /// To manually flush a + /// PdfObject + /// behind this wrapper, you have to ensure + /// that this object is added to the document, i.e. it has an indirect reference. + /// Basically this means that before flushing you need to explicitly call + /// + /// . + /// For example: wrapperInstance.makeIndirect(document).flush(); + /// Note that not every wrapper require this, only those that have such warning in documentation. + /// + public override void Flush() { + base.Flush(); + } + protected internal override bool IsWrappedObjectMustBeIndirect() { return true; } diff --git a/itext/itext.kernel/itext/kernel/pdf/extgstate/PdfExtGState.cs b/itext/itext.kernel/itext/kernel/pdf/extgstate/PdfExtGState.cs index 2de6029cca..4d88460ec3 100644 --- a/itext/itext.kernel/itext/kernel/pdf/extgstate/PdfExtGState.cs +++ b/itext/itext.kernel/itext/kernel/pdf/extgstate/PdfExtGState.cs @@ -41,278 +41,1093 @@ source product. For more information, please contact iText Software Corp. at this address: sales@itextpdf.com */ +using System; using iText.Kernel.Pdf; namespace iText.Kernel.Pdf.Extgstate { + /// Graphics state parameter dictionary wrapper. + /// + /// Graphics state parameter dictionary wrapper. + /// See ISO-320001, 8.4.5 Graphics State Parameter Dictionaries. + /// public class PdfExtGState : PdfObjectWrapper { - /// Blend mode constants + /// Standard separable blend mode. + /// Standard separable blend mode. See ISO-320001, table 136 public static PdfName BM_NORMAL = PdfName.Normal; + /// Standard separable blend mode. + /// Standard separable blend mode. See ISO-320001, table 136 public static PdfName BM_MULTIPLY = PdfName.Multiply; + /// Standard separable blend mode. + /// Standard separable blend mode. See ISO-320001, table 136 public static PdfName BM_SCREEN = PdfName.Screen; + /// Standard separable blend mode. + /// Standard separable blend mode. See ISO-320001, table 136 public static PdfName BM_OVERLAY = PdfName.Overlay; + /// Standard separable blend mode. + /// Standard separable blend mode. See ISO-320001, table 136 public static PdfName BM_DARKEN = PdfName.Darken; + /// Standard separable blend mode. + /// Standard separable blend mode. See ISO-320001, table 136 public static PdfName BM_LIGHTEN = PdfName.Lighten; + /// Standard separable blend mode. + /// Standard separable blend mode. See ISO-320001, table 136 public static PdfName BM_COLOR_DODGE = PdfName.ColorDodge; + /// Standard separable blend mode. + /// Standard separable blend mode. See ISO-320001, table 136 public static PdfName BM_COLOR_BURN = PdfName.ColorBurn; + /// Standard separable blend mode. + /// Standard separable blend mode. See ISO-320001, table 136 public static PdfName BM_HARD_LIGHT = PdfName.HardLight; + /// Standard separable blend mode. + /// Standard separable blend mode. See ISO-320001, table 136 public static PdfName BM_SOFT_LIGHT = PdfName.SoftLight; + /// Standard separable blend mode. + /// Standard separable blend mode. See ISO-320001, table 136 public static PdfName BM_DIFFERENCE = PdfName.Difference; + /// Standard separable blend mode. + /// Standard separable blend mode. See ISO-320001, table 136 public static PdfName BM_EXCLUSION = PdfName.Exclusion; + /// Standard nonseparable blend mode. + /// Standard nonseparable blend mode. See ISO-320001, table 137 public static PdfName BM_HUE = PdfName.Hue; + /// Standard nonseparable blend mode. + /// Standard nonseparable blend mode. See ISO-320001, table 137 public static PdfName BM_SATURATION = PdfName.Saturation; + /// Standard nonseparable blend mode. + /// Standard nonseparable blend mode. See ISO-320001, table 137 public static PdfName BM_COLOR = PdfName.Color; + /// Standard nonseparable blend mode. + /// Standard nonseparable blend mode. See ISO-320001, table 137 public static PdfName BM_LUMINOSITY = PdfName.Luminosity; + /// + /// Create instance of graphics state parameter dictionary wrapper + /// by existed + /// PdfDictionary + /// object + /// + /// instance of graphics state parameter dictionary public PdfExtGState(PdfDictionary pdfObject) : base(pdfObject) { - MarkObjectAsIndirect(GetPdfObject()); } + /// Create default instance of graphics state parameter dictionary public PdfExtGState() : this(new PdfDictionary()) { } + /// + /// Gets line width value, + /// LW + /// key. + /// + /// + /// a + /// float + /// value if exist, otherwise + /// + /// . + /// public virtual float? GetLineWidth() { return GetPdfObject().GetAsFloat(PdfName.LW); } + /// + /// Sets line width value, + /// LW + /// key. + /// + /// + /// a + /// float + /// value. + /// + /// object itself. public virtual iText.Kernel.Pdf.Extgstate.PdfExtGState SetLineWidth(float lineWidth) { return Put(PdfName.LW, new PdfNumber(lineWidth)); } + /// + /// Gets line gap style value, + /// LC + /// key. + /// + /// 0 - butt cap, 1 - round cap, 2 - projecting square cap. public virtual int? GetLineCapStyle() { return GetPdfObject().GetAsInt(PdfName.LC); } + /// + /// Sets line gap style value, + /// LC + /// key. + /// + /// 0 - butt cap, 1 - round cap, 2 - projecting square cap. + /// object itself. + [System.ObsoleteAttribute(@"Use SetLineCapStyle(int) instead.")] public virtual iText.Kernel.Pdf.Extgstate.PdfExtGState SetLineCapStryle(int lineCapStyle) { return Put(PdfName.LC, new PdfNumber(lineCapStyle)); } + /// + /// Sets line gap style value, + /// LC + /// key. + /// + /// 0 - butt cap, 1 - round cap, 2 - projecting square cap. + /// object itself. + public virtual iText.Kernel.Pdf.Extgstate.PdfExtGState SetLineCapStyle(int lineCapStyle) { + return Put(PdfName.LC, new PdfNumber(lineCapStyle)); + } + + /// + /// Gets line join style value, + /// LJ + /// key. + /// + /// 0 - miter join (see also miter limit), 1 - round join, 2 - bevel join. public virtual int? GetLineJoinStyle() { return GetPdfObject().GetAsInt(PdfName.LJ); } + /// + /// Sets line join style value, + /// LJ + /// key. + /// + /// 0 - miter join (see also miter limit), 1 - round join, 2 - bevel join. + /// object itself. public virtual iText.Kernel.Pdf.Extgstate.PdfExtGState SetLineJoinStyle(int lineJoinStyle) { return Put(PdfName.LJ, new PdfNumber(lineJoinStyle)); } + /// + /// Gets miter limit value, + /// ML key + /// . See also line join style. + /// + /// + /// a + /// float + /// value if exist, otherwise + /// + /// . + /// public virtual float? GetMiterLimit() { return GetPdfObject().GetAsFloat(PdfName.ML); } + /// + /// Sets miter limit value, + /// ML key + /// . See also line join style. + /// + /// + /// a + /// float + /// value. + /// + /// object itself. public virtual iText.Kernel.Pdf.Extgstate.PdfExtGState SetMiterLimit(float miterLimit) { return Put(PdfName.ML, new PdfNumber(miterLimit)); } + /// + /// Gets line dash pattern value, + /// D + /// key. + /// + /// + /// a + /// PdfArray + /// , that represents line dash pattern. + /// public virtual PdfArray GetDashPattern() { return GetPdfObject().GetAsArray(PdfName.D); } + /// + /// Sets line dash pattern value, + /// D + /// key. + /// + /// + /// a + /// PdfArray + /// , that represents line dash pattern. + /// + /// object itself. public virtual iText.Kernel.Pdf.Extgstate.PdfExtGState SetDashPattern(PdfArray dashPattern) { return Put(PdfName.D, dashPattern); } + /// + /// Gets rendering intent value, + /// RI + /// key. + /// Valid values are: + /// AbsoluteColorimetric + /// , + /// RelativeColorimetric + /// , + /// Saturation + /// , + /// Perceptual + /// . + /// + /// + /// a + /// PdfName + /// instance. + /// public virtual PdfName GetRenderingIntent() { return GetPdfObject().GetAsName(PdfName.RI); } + /// + /// Sets rendering intent value, + /// RI + /// key. + /// + /// + /// a + /// PdfName + /// instance, Valid values are: + /// AbsoluteColorimetric + /// , + /// RelativeColorimetric + /// , + /// Saturation + /// , + /// Perceptual + /// . + /// + /// object itself. public virtual iText.Kernel.Pdf.Extgstate.PdfExtGState SetRenderingIntent(PdfName renderingIntent) { return Put(PdfName.RI, renderingIntent); } - public virtual int? GetOverprintMode() { - return GetPdfObject().GetAsInt(PdfName.OPM); + /// + /// Get overprint flag value for stroking operations, + /// OP + /// key. + /// + /// + /// a + /// boolean + /// value if exist, otherwise + /// + /// . + /// + public virtual bool? GetStrokeOverprintFlag() { + return GetPdfObject().GetAsBool(PdfName.OP); } - public virtual iText.Kernel.Pdf.Extgstate.PdfExtGState SetOverprintMode(int overprintMode) { - return Put(PdfName.OPM, new PdfNumber(overprintMode)); + /// + /// Set overprint flag value for stroking operations, + /// OP + /// key. + /// + /// + /// + /// + /// , for applying overprint for stroking operations. + /// + /// object itself. + public virtual iText.Kernel.Pdf.Extgstate.PdfExtGState SetStrokeOverPrintFlag(bool strokeOverPrintFlag) { + return Put(PdfName.OP, new PdfBoolean(strokeOverPrintFlag)); } + /// + /// Get overprint flag value for non-stroking operations, + /// op + /// key. + /// + /// + /// a + /// boolean + /// value if exist, otherwise + /// + /// . + /// public virtual bool? GetFillOverprintFlag() { return GetPdfObject().GetAsBool(PdfName.op); } + /// + /// Set overprint flag value for non-stroking operations, + /// op + /// key. + /// + /// + /// + /// + /// , for applying overprint for non-stroking operations. + /// + /// object itself. public virtual iText.Kernel.Pdf.Extgstate.PdfExtGState SetFillOverPrintFlag(bool fillOverprintFlag) { return Put(PdfName.op, new PdfBoolean(fillOverprintFlag)); } - public virtual bool? GetStrokeOverprintFlag() { - return GetPdfObject().GetAsBool(PdfName.OP); + /// + /// Get overprint control mode, + /// OPM + /// key. + /// + /// + /// an + /// int + /// value if exist, otherwise + /// + /// . + /// + public virtual int? GetOverprintMode() { + return GetPdfObject().GetAsInt(PdfName.OPM); } - public virtual iText.Kernel.Pdf.Extgstate.PdfExtGState SetStrokeOverPrintFlag(bool strokeOverPrintFlag) { - return Put(PdfName.OP, new PdfBoolean(strokeOverPrintFlag)); + /// + /// Set overprint control mode, + /// OPM + /// key. + /// + /// + /// an + /// int + /// value, see ISO-320001, 8.6.7 Overprint Control. + /// + /// object itself. + public virtual iText.Kernel.Pdf.Extgstate.PdfExtGState SetOverprintMode(int overprintMode) { + return Put(PdfName.OPM, new PdfNumber(overprintMode)); } + /// + /// Gets font and size, + /// Font + /// key. + /// + /// + /// a + /// + /// of the form + /// [font size] + /// , where + /// font + /// shall be an indirect reference to a font dictionary and + /// size + /// shall be a number expressed in text space units. + /// public virtual PdfArray GetFont() { return GetPdfObject().GetAsArray(PdfName.Font); } + /// + /// Sets font and size, + /// Font + /// key. + /// + /// + /// a + /// + /// of the form + /// [font size] + /// , where + /// + /// shall be an indirect reference to a font dictionary and + /// size + /// shall be a number expressed in text space units. + /// + /// object itself. public virtual iText.Kernel.Pdf.Extgstate.PdfExtGState SetFont(PdfArray font) { return Put(PdfName.Font, font); } + /// + /// Gets the black-generation function value, + /// BG + /// . + /// + /// + /// a + /// + /// , should be + /// + /// . + /// public virtual PdfObject GetBlackGenerationFunction() { return GetPdfObject().Get(PdfName.BG); } + /// + /// Sets the black-generation function value, + /// BG + /// . + /// + /// + /// a + /// + /// , shall be + /// + /// . + /// + /// object itself. public virtual iText.Kernel.Pdf.Extgstate.PdfExtGState SetBlackGenerationFunction(PdfObject blackGenerationFunction ) { return Put(PdfName.BG, blackGenerationFunction); } + /// + /// Gets the black-generation function value or + /// Default + /// , + /// BG2 + /// key. + /// + /// + /// a + /// + /// value, should be either + /// + /// or + /// + /// . + /// public virtual PdfObject GetBlackGenerationFunction2() { return GetPdfObject().Get(PdfName.BG2); } + /// + /// Sets the black-generation function value or + /// Default + /// , + /// BG2 + /// key. + /// Note, if both + /// BG + /// and + /// BG2 + /// are present in the same graphics state parameter dictionary, + /// BG2 + /// takes precedence. + /// + /// + /// a + /// + /// value, shall be either + /// + /// or + /// Default + /// . + /// + /// object itself. public virtual iText.Kernel.Pdf.Extgstate.PdfExtGState SetBlackGenerationFunction2(PdfObject blackGenerationFunction2 ) { return Put(PdfName.BG2, blackGenerationFunction2); } + /// + /// Gets the undercolor-removal function, + /// UCR + /// key. + /// + /// + /// a + /// + /// , should be + /// + /// . + /// public virtual PdfObject GetUndercolorRemovalFunction() { return GetPdfObject().Get(PdfName.UCR); } + /// + /// Sets the undercolor-removal function, + /// UCR + /// key. + /// + /// + /// a + /// + /// , shall be + /// + /// . + /// + /// object itself. public virtual iText.Kernel.Pdf.Extgstate.PdfExtGState SetUndercolorRemovalFunction(PdfObject undercolorRemovalFunction ) { return Put(PdfName.UCR, undercolorRemovalFunction); } + /// + /// Gets the undercolor-removal function value or + /// Default + /// , + /// UCR2 + /// key. + /// + /// + /// a + /// + /// value, should be either + /// + /// or + /// + /// . + /// public virtual PdfObject GetUndercolorRemovalFunction2() { return GetPdfObject().Get(PdfName.UCR2); } + /// + /// Sets the undercolor-removal function value or + /// Default + /// , + /// UCR2 + /// key. + /// Note, if both + /// UCR + /// and + /// UCR2 + /// are present in the same graphics state parameter dictionary, + /// UCR2 + /// takes precedence. + /// + /// + /// a + /// + /// value, shall be either + /// + /// or + /// Default + /// . + /// + /// object itself. public virtual iText.Kernel.Pdf.Extgstate.PdfExtGState SetUndercolorRemovalFunction2(PdfObject undercolorRemovalFunction2 ) { return Put(PdfName.UCR2, undercolorRemovalFunction2); } + /// + /// Gets the transfer function value, + /// TR + /// key. + /// + /// + /// a + /// + /// , should be either + /// + /// , + /// + /// or + /// + /// . + /// public virtual PdfObject GetTransferFunction() { return GetPdfObject().Get(PdfName.TR); } + /// + /// Sets the transfer function value, + /// TR + /// key. + /// + /// + /// a + /// + /// , shall be either + /// + /// , + /// + /// or + /// + /// . + /// + /// object itself. public virtual iText.Kernel.Pdf.Extgstate.PdfExtGState SetTransferFunction(PdfObject transferFunction) { return Put(PdfName.TR, transferFunction); } + /// + /// Gets the transfer function value or + /// Default + /// , + /// TR2 + /// key. + /// + /// + /// a + /// + /// , should be either + /// + /// , + /// + /// or + /// + /// . + /// public virtual PdfObject GetTransferFunction2() { return GetPdfObject().Get(PdfName.TR2); } - public virtual iText.Kernel.Pdf.Extgstate.PdfExtGState SetTransferFunction2(PdfObject transferFunction) { - return Put(PdfName.TR2, transferFunction); + /// + /// Sets the transfer function value or + /// Default + /// , + /// TR2 + /// key. + /// Note, if both + /// TR + /// and + /// TR2 + /// are present in the same graphics state parameter dictionary, + /// TR2 + /// takes precedence. + /// + /// + /// a + /// + /// , shall be either + /// + /// , + /// + /// , + /// + /// or + /// Default + /// . + /// + /// object itself. + public virtual iText.Kernel.Pdf.Extgstate.PdfExtGState SetTransferFunction2(PdfObject transferFunction2) { + return Put(PdfName.TR2, transferFunction2); } + /// + /// Gets the halftone dictionary, stream or + /// Default + /// , + /// HT + /// key. + /// + /// + /// a + /// + /// , should be either + /// + /// , + /// + /// or + /// + /// . + /// public virtual PdfObject GetHalftone() { return GetPdfObject().Get(PdfName.HT); } + /// + /// Sets the halftone or + /// Default + /// , + /// HT + /// key. + /// + /// + /// a + /// + /// , shall be either + /// + /// , + /// + /// or + /// + /// . + /// + /// object itself. public virtual iText.Kernel.Pdf.Extgstate.PdfExtGState SetHalftone(PdfObject halftone) { return Put(PdfName.HT, halftone); } + /// + /// Gets + /// HTP + /// key. + /// + [Obsolete] public virtual PdfObject GetHTP() { return GetPdfObject().Get(PdfName.HTP); } + /// + /// Sets + /// HTP + /// key. + /// + /// + /// a + /// + /// . + /// + /// object itself. + [Obsolete] public virtual iText.Kernel.Pdf.Extgstate.PdfExtGState SetHTP(PdfObject htp) { return Put(PdfName.HTP, htp); } + /// + /// Gets the flatness tolerance value, + /// FL + /// key. + /// + /// + /// a + /// float + /// value if exist, otherwise + /// + /// . + /// public virtual float? GetFlatnessTolerance() { - return GetPdfObject().GetAsFloat(PdfName.FT); + return GetPdfObject().GetAsFloat(PdfName.FL); } + /// + /// Sets the flatness tolerance value, + /// FL + /// key. + /// + /// + /// a + /// float + /// value. + /// + /// object itself. public virtual iText.Kernel.Pdf.Extgstate.PdfExtGState SetFlatnessTolerance(float flatnessTolerance) { - return Put(PdfName.FT, new PdfNumber(flatnessTolerance)); + return Put(PdfName.FL, new PdfNumber(flatnessTolerance)); } + /// + /// Gets the smoothness tolerance value, + /// SM + /// key. + /// + /// + /// a + /// float + /// value if exist, otherwise + /// + /// . + /// public virtual float? GetSmothnessTolerance() { return GetPdfObject().GetAsFloat(PdfName.SM); } + /// + /// Sets the smoothness tolerance value, + /// SM + /// key. + /// + /// + /// a + /// float + /// value. + /// + /// object itself. public virtual iText.Kernel.Pdf.Extgstate.PdfExtGState SetSmoothnessTolerance(float smoothnessTolerance) { return Put(PdfName.SM, new PdfNumber(smoothnessTolerance)); } + /// + /// Gets value of an automatic stroke adjustment flag, + /// SA + /// key. + /// + /// + /// a + /// boolean + /// value if exist, otherwise + /// + /// . + /// public virtual bool? GetAutomaticStrokeAdjustmentFlag() { return GetPdfObject().GetAsBool(PdfName.SA); } + /// + /// Sets value of an automatic stroke adjustment flag, + /// SA + /// key. + /// + /// + /// a + /// boolean + /// value. + /// + /// object itself. public virtual iText.Kernel.Pdf.Extgstate.PdfExtGState SetAutomaticStrokeAdjustmentFlag(bool strokeAdjustment ) { return Put(PdfName.SA, new PdfBoolean(strokeAdjustment)); } + /// + /// Gets the current blend mode for the transparent imaging model, + /// BM + /// key. + /// + /// + /// a + /// + /// , should be either + /// + /// or + /// + /// . + /// public virtual PdfObject GetBlendMode() { return GetPdfObject().Get(PdfName.BM); } + /// + /// Sets the current blend mode for the transparent imaging model, + /// BM + /// key. + /// + /// + /// a + /// + /// , shall be either + /// + /// or + /// + /// . + /// + /// object itself. public virtual iText.Kernel.Pdf.Extgstate.PdfExtGState SetBlendMode(PdfObject blendMode) { return Put(PdfName.BM, blendMode); } + /// + /// Gets the current soft mask, + /// SMask + /// key. + /// + /// + /// a + /// + /// , should be either + /// + /// or + /// + /// . + /// public virtual PdfObject GetSoftMask() { return GetPdfObject().Get(PdfName.SMask); } + /// + /// Sets the current soft mask, + /// SMask + /// key. + /// + /// + /// a + /// + /// , shall be either + /// + /// or + /// + /// . + /// + /// object itself. public virtual iText.Kernel.Pdf.Extgstate.PdfExtGState SetSoftMask(PdfObject sMask) { return Put(PdfName.SMask, sMask); } + /// + /// Gets the current alpha constant, specifying the constant shape or constant opacity value + /// for stroking operations in the transparent imaging model, + /// CA + /// key. + /// + /// + /// a + /// float + /// value if exist, otherwise + /// + /// . + /// public virtual float? GetStrokeOpacity() { return GetPdfObject().GetAsFloat(PdfName.CA); } + /// + /// Sets the current alpha constant, specifying the constant shape or constant opacity value + /// for stroking operations in the transparent imaging model, + /// CA + /// key. + /// + /// + /// a + /// float + /// value. + /// + /// object itself. public virtual iText.Kernel.Pdf.Extgstate.PdfExtGState SetStrokeOpacity(float strokingAlphaConstant) { return Put(PdfName.CA, new PdfNumber(strokingAlphaConstant)); } + /// + /// Gets the current alpha constant, specifying the constant shape or constant opacity value + /// for non-stroking operations in the transparent imaging model, + /// ca + /// key. + /// + /// + /// a + /// float + /// value if exist, otherwise + /// + /// . + /// public virtual float? GetFillOpacity() { return GetPdfObject().GetAsFloat(PdfName.ca); } + /// + /// Sets the current alpha constant, specifying the constant shape or constant opacity value + /// for non-stroking operations in the transparent imaging model, + /// ca + /// key. + /// + /// + /// a + /// float + /// value. + /// + /// object itself. public virtual iText.Kernel.Pdf.Extgstate.PdfExtGState SetFillOpacity(float fillingAlphaConstant) { return Put(PdfName.ca, new PdfNumber(fillingAlphaConstant)); } + /// + /// Gets the alpha source flag (“alpha is shape”), specifying whether the current soft mask and alpha constant + /// shall be interpreted as shape values ( + /// + /// ) or opacity values ( + /// + /// ), + /// AIS + /// key. + /// + /// + /// a + /// boolean + /// value if exist, otherwise + /// + /// . + /// public virtual bool? GetAlphaSourceFlag() { return GetPdfObject().GetAsBool(PdfName.AIS); } + /// + /// Sets the alpha source flag (“alpha is shape”), specifying whether the current soft mask and alpha constant + /// shall be interpreted as shape values ( + /// + /// ) or opacity values ( + /// + /// ), + /// AIS + /// key. + /// + /// + /// if + /// + /// - alpha as shape values, if + /// + /// — as opacity values. + /// + /// object itself. public virtual iText.Kernel.Pdf.Extgstate.PdfExtGState SetAlphaSourceFlag(bool alphaSourceFlag) { return Put(PdfName.AIS, new PdfBoolean(alphaSourceFlag)); } + /// + /// Gets the text knockout flag, which determine the behaviour of overlapping glyphs + /// within a text object in the transparent imaging model, + /// TK + /// key. + /// + /// + /// a + /// boolean + /// value if exist, otherwise + /// + /// . + /// public virtual bool? GetTextKnockoutFlag() { return GetPdfObject().GetAsBool(PdfName.TK); } + /// + /// Sets the text knockout flag, which determine the behaviour of overlapping glyphs + /// within a text object in the transparent imaging model, + /// TK + /// key. + /// + /// + /// + /// + /// if enabled. + /// + /// object itself. public virtual iText.Kernel.Pdf.Extgstate.PdfExtGState SetTextKnockoutFlag(bool textKnockoutFlag) { return Put(PdfName.TK, new PdfBoolean(textKnockoutFlag)); } + /// Puts the value into Graphics state parameter dictionary and associates it with the specified key. + /// + /// + /// Puts the value into Graphics state parameter dictionary and associates it with the specified key. + /// If the key is already present, it will override the old value with the specified one. + /// + /// key to insert or to override + /// the value to associate with the specified key + /// object itself. public virtual iText.Kernel.Pdf.Extgstate.PdfExtGState Put(PdfName key, PdfObject value) { GetPdfObject().Put(key, value); return this; } + /// + /// To manually flush a + /// PdfObject + /// behind this wrapper, you have to ensure + /// that this object is added to the document, i.e. it has an indirect reference. + /// Basically this means that before flushing you need to explicitly call + /// + /// . + /// For example: wrapperInstance.makeIndirect(document).flush(); + /// Note that not every wrapper require this, only those that have such warning in documentation. + /// + public override void Flush() { + base.Flush(); + } + + /// protected internal override bool IsWrappedObjectMustBeIndirect() { return true; } diff --git a/itext/itext.kernel/itext/kernel/pdf/filters/FilterHandlers.cs b/itext/itext.kernel/itext/kernel/pdf/filters/FilterHandlers.cs index 40bd940e0c..78baed5b64 100644 --- a/itext/itext.kernel/itext/kernel/pdf/filters/FilterHandlers.cs +++ b/itext/itext.kernel/itext/kernel/pdf/filters/FilterHandlers.cs @@ -66,7 +66,7 @@ static FilterHandlers() { // it may also be better to split the sub-classes out into a separate package IDictionary map = new Dictionary(); map[PdfName.FlateDecode] = new FlateDecodeFilter(); - map[PdfName.FL] = new FlateDecodeFilter(); + map[PdfName.Fl] = new FlateDecodeFilter(); map[PdfName.ASCIIHexDecode] = new ASCIIHexDecodeFilter(); map[PdfName.AHx] = new ASCIIHexDecodeFilter(); map[PdfName.ASCII85Decode] = new ASCII85DecodeFilter(); diff --git a/itext/itext.kernel/itext/kernel/pdf/function/PdfFunction.cs b/itext/itext.kernel/itext/kernel/pdf/function/PdfFunction.cs index 006902a218..f7a644f069 100644 --- a/itext/itext.kernel/itext/kernel/pdf/function/PdfFunction.cs +++ b/itext/itext.kernel/itext/kernel/pdf/function/PdfFunction.cs @@ -68,6 +68,21 @@ public virtual int GetOutputSize() { return range == null ? 0 : range.Size() / 2; } + /// + /// To manually flush a + /// PdfObject + /// behind this wrapper, you have to ensure + /// that this object is added to the document, i.e. it has an indirect reference. + /// Basically this means that before flushing you need to explicitly call + /// + /// . + /// For example: wrapperInstance.makeIndirect(document).flush(); + /// Note that not every wrapper require this, only those that have such warning in documentation. + /// + public override void Flush() { + base.Flush(); + } + protected internal override bool IsWrappedObjectMustBeIndirect() { return true; } diff --git a/itext/itext.kernel/itext/kernel/pdf/layer/PdfLayer.cs b/itext/itext.kernel/itext/kernel/pdf/layer/PdfLayer.cs index ccea712620..da581a8586 100644 --- a/itext/itext.kernel/itext/kernel/pdf/layer/PdfLayer.cs +++ b/itext/itext.kernel/itext/kernel/pdf/layer/PdfLayer.cs @@ -78,7 +78,6 @@ public class PdfLayer : PdfObjectWrapper, IPdfOCG { /// 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) : base(layerDictionary) { EnsureObjectIsAddedToDocument(layerDictionary); @@ -87,7 +86,6 @@ public PdfLayer(PdfDictionary layerDictionary) /// Creates a new layer by its name and document. /// the layer name /// the PdfDocument which the layer belongs to - /// public PdfLayer(String name, PdfDocument document) : this(document) { SetName(name); @@ -224,7 +222,6 @@ public virtual void SetOnPanel(bool onPanel) { /// resultant colletion if no intents are currently specified. /// /// the collection of intents. - /// public virtual ICollection GetIntents() { PdfObject intent = GetPdfObject().Get(PdfName.Intent); if (intent is PdfName) { @@ -433,7 +430,6 @@ public virtual void SetPageElement(String pe) { /// making it indirect first if necessary. /// /// the indirect reference to the object representing the layer - /// public virtual PdfIndirectReference GetIndirectReference() { GetPdfObject().MakeIndirect(GetDocument()); return GetPdfObject().GetIndirectReference(); @@ -467,7 +463,6 @@ protected internal virtual PdfDocument GetDocument() { /// the title of the layer /// the document this title layer belongs to /// the created layer - /// protected internal static iText.Kernel.Pdf.Layer.PdfLayer CreateTitleSilent(String title, PdfDocument document ) { if (title == null) { @@ -480,7 +475,6 @@ protected internal static iText.Kernel.Pdf.Layer.PdfLayer CreateTitleSilent(Stri /// Gets the /Usage dictionary, creating a new one if necessary. /// the /Usage dictionary - /// protected internal virtual PdfDictionary GetUsage() { PdfDictionary usage = GetPdfObject().GetAsDictionary(PdfName.Usage); if (usage == null) { diff --git a/itext/itext.kernel/itext/kernel/pdf/layer/PdfLayerMembership.cs b/itext/itext.kernel/itext/kernel/pdf/layer/PdfLayerMembership.cs index 43c0b310aa..cd92966ae1 100644 --- a/itext/itext.kernel/itext/kernel/pdf/layer/PdfLayerMembership.cs +++ b/itext/itext.kernel/itext/kernel/pdf/layer/PdfLayerMembership.cs @@ -65,7 +65,6 @@ namespace iText.Kernel.Pdf.Layer { ///
    public class PdfLayerMembership : PdfObjectWrapper, IPdfOCG { /// Creates a new, empty membership layer. - /// public PdfLayerMembership(PdfDocument doc) : base(new PdfDictionary()) { MakeIndirect(doc); @@ -75,7 +74,6 @@ public PdfLayerMembership(PdfDocument doc) /// Creates a new PdfLayerMembership instance by its PdfDictionary, which must be an indirect object. /// /// the membership dictionary, must have an indirect reference. - /// public PdfLayerMembership(PdfDictionary membershipDictionary) : base(membershipDictionary) { EnsureObjectIsAddedToDocument(membershipDictionary); @@ -85,7 +83,6 @@ public PdfLayerMembership(PdfDictionary membershipDictionary) } /// Gets the collection of the layers this layer membership operates with. - /// public virtual ICollection GetLayers() { PdfObject layers = GetPdfObject().Get(PdfName.OCGs); if (layers is PdfDictionary) { @@ -108,7 +105,6 @@ public virtual ICollection GetLayers() { /// Adds a new layer to the current layer membership. /// the layer to be added - /// public virtual void AddLayer(PdfLayer layer) { PdfArray layers = GetPdfObject().GetAsArray(PdfName.OCGs); if (layers == null) { @@ -146,7 +142,6 @@ public virtual void SetVisibilityPolicy(PdfName visibilityPolicy) { /// Gets the visibility policy for content belonging to this /// optional content membership dictionary. ///
    - /// public virtual PdfName GetVisibilityPolicy() { PdfName visibilityPolicy = GetPdfObject().GetAsName(PdfName.P); if (visibilityPolicy == null || !visibilityPolicy.Equals(PdfName.AllOn) && !visibilityPolicy.Equals(PdfName @@ -174,7 +169,6 @@ public virtual void SetVisibilityExpression(PdfVisibilityExpression visibilityEx /// Gets the visibility expression for content belonging to this /// optional content membership dictionary. /// - /// public virtual PdfVisibilityExpression GetVisibilityExpression() { PdfArray ve = GetPdfObject().GetAsArray(PdfName.VE); return ve != null ? new PdfVisibilityExpression(ve) : null; diff --git a/itext/itext.kernel/itext/kernel/pdf/layer/PdfOCProperties.cs b/itext/itext.kernel/itext/kernel/pdf/layer/PdfOCProperties.cs index ab30f8e33a..ebc2cad1ac 100644 --- a/itext/itext.kernel/itext/kernel/pdf/layer/PdfOCProperties.cs +++ b/itext/itext.kernel/itext/kernel/pdf/layer/PdfOCProperties.cs @@ -66,7 +66,6 @@ public class PdfOCProperties : PdfObjectWrapper { /// Creates a new PdfOCProperties instance. /// the document the optional content belongs to - /// public PdfOCProperties(PdfDocument document) : this(((PdfDictionary)new PdfDictionary().MakeIndirect(document))) { } @@ -77,7 +76,6 @@ public PdfOCProperties(PdfDocument document) /// /// the dictionary of optional content properties, must have an indirect reference. /// - /// public PdfOCProperties(PdfDictionary ocPropertiesDict) : base(ocPropertiesDict) { EnsureObjectIsAddedToDocument(ocPropertiesDict); @@ -254,7 +252,6 @@ private static void GetOCGOrder(PdfArray order, PdfLayer layer) { } /// Populates the /AS entry in the /D dictionary. - /// private void AddASEvent(PdfName @event, PdfName category) { PdfArray arr = new PdfArray(); foreach (PdfLayer layer in layers) { @@ -284,7 +281,6 @@ private void AddASEvent(PdfName @event, PdfName category) { } /// Reads the layers from the document to be able to modify them in the future. - /// private void ReadLayersFromDictionary() { PdfArray ocgs = GetPdfObject().GetAsArray(PdfName.OCGs); if (ocgs == null || ocgs.IsEmpty()) { @@ -303,13 +299,15 @@ private void ReadLayersFromDictionary() { if (d != null && !d.IsEmpty()) { PdfArray off = d.GetAsArray(PdfName.OFF); if (off != null) { - foreach (PdfObject offLayer in off) { + for (int i = 0; i < off.Size(); i++) { + PdfObject offLayer = off.Get(i, false); layerMap.Get((PdfIndirectReference)offLayer).on = false; } } PdfArray locked = d.GetAsArray(PdfName.Locked); if (locked != null) { - foreach (PdfObject lockedLayer in locked) { + for (int i = 0; i < locked.Size(); i++) { + PdfObject lockedLayer = locked.Get(i, false); layerMap.Get((PdfIndirectReference)lockedLayer).locked = true; } } @@ -327,7 +325,6 @@ 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) { for (int i = 0; i < orderArray.Size(); i++) { diff --git a/itext/itext.kernel/itext/kernel/pdf/layer/PdfVisibilityExpression.cs b/itext/itext.kernel/itext/kernel/pdf/layer/PdfVisibilityExpression.cs index ccfc7cb6db..b35e880220 100644 --- a/itext/itext.kernel/itext/kernel/pdf/layer/PdfVisibilityExpression.cs +++ b/itext/itext.kernel/itext/kernel/pdf/layer/PdfVisibilityExpression.cs @@ -52,7 +52,6 @@ namespace iText.Kernel.Pdf.Layer { public class PdfVisibilityExpression : PdfObjectWrapper { /// Constructs a new PdfVisibilityExpression instance by its raw PdfArray. /// the array representing the visibility expression - /// public PdfVisibilityExpression(PdfArray visibilityExpressionArray) : base(visibilityExpressionArray) { PdfName @operator = visibilityExpressionArray.GetAsName(0); diff --git a/itext/itext.kernel/itext/kernel/pdf/tagging/ParentTreeHandler.cs b/itext/itext.kernel/itext/kernel/pdf/tagging/ParentTreeHandler.cs index 5b35d52a4b..7f96b30c96 100644 --- a/itext/itext.kernel/itext/kernel/pdf/tagging/ParentTreeHandler.cs +++ b/itext/itext.kernel/itext/kernel/pdf/tagging/ParentTreeHandler.cs @@ -42,6 +42,8 @@ source product. address: sales@itextpdf.com */ using System.Collections.Generic; +using iText.IO; +using iText.IO.Log; using iText.Kernel; using iText.Kernel.Pdf; @@ -138,10 +140,16 @@ public virtual PdfDictionary BuildParentTree() { } public virtual void RegisterMcr(PdfMcr mcr) { - SortedDictionary pageMcrs = pageToPageMcrs.Get(mcr.GetPageObject().GetIndirectReference()); + PdfDictionary mcrPageObject = mcr.GetPageObject(); + if (mcrPageObject == null || (!(mcr is PdfObjRef) && mcr.GetMcid() < 0)) { + ILogger logger = LoggerFactory.GetLogger(typeof(iText.Kernel.Pdf.Tagging.ParentTreeHandler)); + logger.Error(LogMessageConstant.ENCOUNTERED_INVALID_MCR); + return; + } + SortedDictionary pageMcrs = pageToPageMcrs.Get(mcrPageObject.GetIndirectReference()); if (pageMcrs == null) { pageMcrs = new SortedDictionary(); - pageToPageMcrs[mcr.GetPageObject().GetIndirectReference()] = pageMcrs; + pageToPageMcrs[mcrPageObject.GetIndirectReference()] = pageMcrs; } if (mcr is PdfObjRef) { PdfDictionary obj = ((PdfDictionary)mcr.GetPdfObject()).GetAsDictionary(PdfName.Obj); @@ -164,6 +172,10 @@ public virtual void RegisterMcr(PdfMcr mcr) { public virtual void UnregisterMcr(PdfMcr mcrToUnregister) { PdfDictionary pageDict = mcrToUnregister.GetPageObject(); + if (pageDict == null) { + // invalid mcr, ignore + return; + } if (pageDict.IsFlushed()) { throw new PdfException(PdfException.CannotRemoveMarkedContentReferenceBecauseItsPageWasAlreadyFlushed); } @@ -259,6 +271,7 @@ private void UpdateStructParentTreeEntries(int? pageStructParentIndex, IDictiona if (parentsOfPageMcrs.Size() > 0) { parentsOfPageMcrs.MakeIndirect(structTreeRoot.GetDocument()); parentTree.AddEntry(pageStructParentIndex, parentsOfPageMcrs); + structTreeRoot.GetDocument().CheckIsoConformance(parentsOfPageMcrs, IsoKey.TAG_STRUCTURE_ELEMENT); parentsOfPageMcrs.Flush(); } } diff --git a/itext/itext.kernel/itext/kernel/pdf/tagging/PdfMcrDictionary.cs b/itext/itext.kernel/itext/kernel/pdf/tagging/PdfMcrDictionary.cs index 4e2ac794af..157c1f9636 100644 --- a/itext/itext.kernel/itext/kernel/pdf/tagging/PdfMcrDictionary.cs +++ b/itext/itext.kernel/itext/kernel/pdf/tagging/PdfMcrDictionary.cs @@ -58,7 +58,8 @@ public PdfMcrDictionary(PdfPage page, PdfStructElem parent) } public override int GetMcid() { - return ((PdfDictionary)GetPdfObject()).GetAsNumber(PdfName.MCID).IntValue(); + PdfNumber mcidNumber = ((PdfDictionary)GetPdfObject()).GetAsNumber(PdfName.MCID); + return mcidNumber != null ? mcidNumber.IntValue() : -1; } public override PdfDictionary GetPageObject() { diff --git a/itext/itext.kernel/itext/kernel/pdf/tagging/PdfStructElem.cs b/itext/itext.kernel/itext/kernel/pdf/tagging/PdfStructElem.cs index f8c19667e8..ac51ac4e1d 100644 --- a/itext/itext.kernel/itext/kernel/pdf/tagging/PdfStructElem.cs +++ b/itext/itext.kernel/itext/kernel/pdf/tagging/PdfStructElem.cs @@ -144,7 +144,7 @@ public PdfStructElem(PdfDocument document, PdfName role, PdfPage page) public PdfStructElem(PdfDocument document, PdfName role, PdfAnnotation annot) : this(document, role) { if (annot.GetPage() == null) { - throw new PdfException(PdfException.AnnotShallHaveReferenceToPage); + throw new PdfException(PdfException.AnnotationShallHaveReferenceToPage); } GetPdfObject().Put(PdfName.Pg, annot.GetPage().GetPdfObject()); } @@ -172,7 +172,6 @@ public static bool IsStructElem(PdfDictionary dictionary) { /// The attributes dictionary will be stored inside element. /// /// attributes dictionary. - /// public virtual PdfObject GetAttributes(bool createNewIfNull) { PdfObject attributes = GetPdfObject().Get(PdfName.A); if (attributes == null && createNewIfNull) { @@ -369,7 +368,7 @@ public virtual iText.Kernel.Pdf.Tagging.PdfStructElem Put(PdfName key, PdfObject } public override void Flush() { - //TODO log that to prevent undefined behaviour, use StructTreeRoot#flushStructElem method + GetDocument().CheckIsoConformance(GetPdfObject(), IsoKey.TAG_STRUCTURE_ELEMENT); base.Flush(); } @@ -431,9 +430,6 @@ private void AddKidObjectToStructElemList(PdfObject k, IList lis } private IPdfStructElem ConvertPdfObjectToIPdfStructElem(PdfObject obj) { - if (obj.IsIndirectReference()) { - obj = ((PdfIndirectReference)obj).GetRefersTo(); - } IPdfStructElem elem = null; switch (obj.GetObjectType()) { case PdfObject.DICTIONARY: { diff --git a/itext/itext.kernel/itext/kernel/pdf/tagging/PdfStructTreeRoot.cs b/itext/itext.kernel/itext/kernel/pdf/tagging/PdfStructTreeRoot.cs index 46824c491d..8875b2f240 100644 --- a/itext/itext.kernel/itext/kernel/pdf/tagging/PdfStructTreeRoot.cs +++ b/itext/itext.kernel/itext/kernel/pdf/tagging/PdfStructTreeRoot.cs @@ -195,7 +195,6 @@ public override void Flush() { /// /// document to copy structure to. Shall not be current document. /// association between original page and copied page. - /// public virtual void CopyTo(PdfDocument destDocument, IDictionary page2page) { StructureTreeCopier.CopyTo(destDocument, page2page, GetDocument()); } @@ -213,7 +212,6 @@ public virtual void CopyTo(PdfDocument destDocument, IDictionarydocument to copy structure to. /// indicates where the structure to be inserted. /// association between original page and copied page. - /// public virtual void CopyTo(PdfDocument destDocument, int insertBeforePage, IDictionary page2page ) { StructureTreeCopier.CopyTo(destDocument, insertBeforePage, page2page, GetDocument()); diff --git a/itext/itext.kernel/itext/kernel/pdf/tagging/StructureTreeCopier.cs b/itext/itext.kernel/itext/kernel/pdf/tagging/StructureTreeCopier.cs index e4f2334e24..f7ba4a3a72 100644 --- a/itext/itext.kernel/itext/kernel/pdf/tagging/StructureTreeCopier.cs +++ b/itext/itext.kernel/itext/kernel/pdf/tagging/StructureTreeCopier.cs @@ -73,7 +73,6 @@ static StructureTreeCopier() { /// /// document to copy structure to. Shall not be current document. /// association between original page and copied page. - /// public static void CopyTo(PdfDocument destDocument, IDictionary page2page, PdfDocument callingDocument ) { if (!destDocument.IsTagged()) { @@ -98,7 +97,6 @@ public static void CopyTo(PdfDocument destDocument, IDictionarydocument to copy structure to. /// indicates where the structure to be inserted. /// association between original page and copied page. - /// public static void CopyTo(PdfDocument destDocument, int insertBeforePage, IDictionary page2page , PdfDocument callingDocument) { if (!destDocument.IsTagged()) { @@ -161,7 +159,6 @@ public static void CopyTo(PdfDocument destDocument, int insertBeforePage, IDicti /// /// . /// - /// private static void CopyTo(PdfDocument destDocument, IDictionary page2page, PdfDocument callingDocument, bool copyFromDestDocument) { CopyTo(destDocument, page2page, callingDocument, copyFromDestDocument, -1); @@ -273,7 +270,7 @@ private static PdfObject CopyObjectKid(PdfObject kid, PdfDictionary copiedParent return kid; } else { - // TODO do we always copy numbers? + // TODO do we always copy numbers? don't we need to check if it is supposed to be copied like objs in objectsToCopy? if (kid.IsDictionary()) { PdfDictionary kidAsDict = (PdfDictionary)kid; if (objectsToCopy.Contains(kidAsDict)) { diff --git a/itext/itext.kernel/itext/kernel/pdf/tagutils/TagStructureContext.cs b/itext/itext.kernel/itext/kernel/pdf/tagutils/TagStructureContext.cs index a5de70cce7..55c993b93c 100644 --- a/itext/itext.kernel/itext/kernel/pdf/tagutils/TagStructureContext.cs +++ b/itext/itext.kernel/itext/kernel/pdf/tagutils/TagStructureContext.cs @@ -522,7 +522,7 @@ private void FlushParentIfBelongsToPage(PdfStructElem parent, PdfPage currentPag else { if (kid is PdfStructElem) { // If kid is structElem and was already flushed then in kids list there will be null for it instead of - // PdfStructElem. And therefore if we get into this if clause it means that some StructElem wasn't flushed. + // PdfStructElem. And therefore if we get into this if-clause it means that some StructElem wasn't flushed. allKidsBelongToPage = false; break; } diff --git a/itext/itext.kernel/itext/kernel/pdf/tagutils/TagTreePointer.cs b/itext/itext.kernel/itext/kernel/pdf/tagutils/TagTreePointer.cs index 675ca936d6..0b03ee8d11 100644 --- a/itext/itext.kernel/itext/kernel/pdf/tagutils/TagTreePointer.cs +++ b/itext/itext.kernel/itext/kernel/pdf/tagutils/TagTreePointer.cs @@ -55,6 +55,7 @@ namespace iText.Kernel.Pdf.Tagutils { /// it's role and properties, etc. Also, using instance of this class, you can change tag position in the tag structure, /// you can flush current tag or remove it. ///

    + ///

    /// There could be any number of the instances of this class, simultaneously pointing to different (or the same) parts of /// the tag structure. Because of this, you can for example remove the tag at which another instance is currently pointing. /// In this case, this another instance becomes invalid, and invocation of any method on it will result in exception. To make @@ -137,7 +138,7 @@ public TagTreePointer(iText.Kernel.Pdf.Tagutils.TagTreePointer tagPointer) { /// public virtual iText.Kernel.Pdf.Tagutils.TagTreePointer SetPageForTagging(PdfPage page) { if (page.IsFlushed()) { - throw new PdfException(PdfException.PageWasAlreadyFlushed); + throw new PdfException(PdfException.PageAlreadyFlushed); } this.currentPage = page; return this; @@ -337,6 +338,7 @@ public virtual iText.Kernel.Pdf.Tagutils.TagTreePointer AddTag(int index, IAcces /// TagTreePointer /// instance would move to connected kid instead of creating tag twice. /// But if it is added to some other parent, then connection will be removed. + ///

    ///

    /// This call is equivalent of calling sequentially /// @@ -707,6 +709,7 @@ public virtual iText.Kernel.Pdf.Tagutils.TagTreePointer MoveToKid(int n, PdfName /// Moves this /// TagTreePointer /// instance to a tag, which is connected with the given accessible element. + ///

    ///

    /// The connection between the tag and the accessible element instance is used as a sign that tag is not yet finished /// and therefore should not be flushed or removed if page tags are flushed or removed. Also, any @@ -764,6 +767,7 @@ public virtual IList GetKidsRoles() { /// This method call moves this /// TagTreePointer /// to the current tag parent. + ///

    ///

    /// If some of the tags to be flushed are still connected to the accessible elements, then these tags are considered /// as not yet finished ones, and they won't be flushed immediately, but they will be flushed, when the connection diff --git a/itext/itext.kernel/itext/kernel/pdf/xobject/PdfFormXObject.cs b/itext/itext.kernel/itext/kernel/pdf/xobject/PdfFormXObject.cs index d85d3cabef..312da52930 100644 --- a/itext/itext.kernel/itext/kernel/pdf/xobject/PdfFormXObject.cs +++ b/itext/itext.kernel/itext/kernel/pdf/xobject/PdfFormXObject.cs @@ -47,9 +47,13 @@ source product. using iText.Kernel.Pdf.Canvas.Wmf; namespace iText.Kernel.Pdf.Xobject { + ///

    A wrapper for Form XObject. + /// A wrapper for Form XObject. ISO 32000-1, 8.10 FormXObjects. public class PdfFormXObject : PdfXObject { private PdfResources resources = null; + /// Creates a new instance of Form XObject. + /// the form XObject’s bounding box. public PdfFormXObject(Rectangle bBox) : base(new PdfStream()) { GetPdfObject().Put(PdfName.Type, PdfName.XObject); @@ -59,8 +63,22 @@ public PdfFormXObject(Rectangle bBox) } } - public PdfFormXObject(PdfStream pdfObject) - : base(pdfObject) { + /// + /// Create + /// + /// instance by + /// + /// . + /// Note, this constructor doesn't perform any additional checks + /// + /// + /// + /// + /// with Form XObject. + /// + /// + public PdfFormXObject(PdfStream pdfStream) + : base(pdfStream) { } /// Creates form XObject from page content. @@ -68,7 +86,10 @@ public PdfFormXObject(PdfStream pdfObject) /// Creates form XObject from page content. /// The page shall be from the document, to which FormXObject will be added. /// - /// + /// + /// an instance of + /// + /// public PdfFormXObject(PdfPage page) : this(page.GetCropBox()) { GetPdfObject().GetOutputStream().WriteBytes(page.GetContentBytes()); @@ -94,6 +115,17 @@ public PdfFormXObject(WmfImageData image, PdfDocument pdfDocument) : this(new WmfImageHelper(image).CreatePdfForm(pdfDocument).GetPdfObject()) { } + /// + /// Gets + /// + /// of the Form XObject. + /// Note, if there is no resources, a new instance will be created. + /// + /// + /// not null instance of + /// + /// . + /// public virtual PdfResources GetResources() { if (this.resources == null) { PdfDictionary resourcesDict = GetPdfObject().GetAsDictionary(PdfName.Resources); @@ -106,6 +138,83 @@ public virtual PdfResources GetResources() { return resources; } + /// + /// Gets Form XObject's BBox, + /// + /// key. + /// + /// + /// a + /// + /// , that represents + /// + /// . + /// + public virtual PdfArray GetBBox() { + return GetPdfObject().GetAsArray(PdfName.BBox); + } + + /// + /// Sets Form XObject's BBox, + /// + /// key. + /// + /// + /// a + /// + /// , that represents + /// + /// . + /// + /// object itself. + public virtual iText.Kernel.Pdf.Xobject.PdfFormXObject SetBBox(PdfArray bBox) { + return Put(PdfName.BBox, bBox); + } + + /// + /// Sets a group attributes dictionary indicating that the contents of the form XObject + /// shall be treated as a group and specifying the attributes of that group. + /// + /// + /// Sets a group attributes dictionary indicating that the contents of the form XObject + /// shall be treated as a group and specifying the attributes of that group. + /// + /// key. + /// + /// + /// instance of + /// + /// . + /// + /// object itself. + /// + public virtual iText.Kernel.Pdf.Xobject.PdfFormXObject SetGroup(PdfTransparencyGroup transparency) { + return Put(PdfName.Group, transparency.GetPdfObject()); + } + + /// Gets width based on XObject's BBox. + /// float value. + public override float GetWidth() { + return GetBBox() == null ? 0 : GetBBox().GetAsNumber(2).FloatValue(); + } + + /// Gets height based on XObject's BBox. + /// float value. + public override float GetHeight() { + return GetBBox() == null ? 0 : GetBBox().GetAsNumber(3).FloatValue(); + } + + /// + /// To manually flush a + /// PdfObject + /// behind this wrapper, you have to ensure + /// that this object is added to the document, i.e. it has an indirect reference. + /// Basically this means that before flushing you need to explicitly call + /// + /// . + /// For example: wrapperInstance.makeIndirect(document).flush(); + /// Note that not every wrapper require this, only those that have such warning in documentation. + /// public override void Flush() { resources = null; if (GetPdfObject().Get(PdfName.BBox) == null) { @@ -114,68 +223,182 @@ public override void Flush() { base.Flush(); } - //Additional entries in form dictionary for Trap Network annotation + //-----Additional entries in form dictionary for Trap Network annotation + /// + /// Sets process color model for trap network appearance, + /// + /// key. + /// + /// + /// shall be one of the valid values: + /// + /// , + /// + /// , + /// + /// , + /// + /// , + /// + /// , and + /// + /// . + /// + /// object itself. public virtual iText.Kernel.Pdf.Xobject.PdfFormXObject SetProcessColorModel(PdfName model) { return Put(PdfName.PCM, model); } + /// + /// Gets process color model of trap network appearance, + /// + /// key. + /// + /// + /// a + /// + /// instance, possible values: + /// + /// , + /// + /// , + /// + /// , + /// + /// , + /// + /// , and + /// + /// . + /// public virtual PdfName GetProcessColorModel() { return GetPdfObject().GetAsName(PdfName.PCM); } + /// + /// Sets separation color names for the trap network appearance, + /// + /// key. + /// + /// + /// an array of names identifying the colorants that were assumed + /// when the trap network appearance was created. + /// + /// object itself. public virtual iText.Kernel.Pdf.Xobject.PdfFormXObject SetSeparationColorNames(PdfArray colorNames) { return Put(PdfName.SeparationColorNames, colorNames); } + /// + /// Gets separation color names of trap network appearance, + /// + /// key. + /// + /// + /// an + /// + /// of names identifying the colorants. + /// public virtual PdfArray GetSeparationColorNames() { return GetPdfObject().GetAsArray(PdfName.SeparationColorNames); } + /// + /// Sets an array of TrapRegion objects defining the page’s trapping zones + /// and the associated trapping parameters, as described in Adobe Technical Note #5620, + /// Portable Job Ticket Format. + /// + /// + /// Sets an array of TrapRegion objects defining the page’s trapping zones + /// and the associated trapping parameters, as described in Adobe Technical Note #5620, + /// Portable Job Ticket Format. + /// + /// key. + /// + /// + /// A + /// + /// of indirect references to TrapRegion objects. + /// + /// object itself. public virtual iText.Kernel.Pdf.Xobject.PdfFormXObject SetTrapRegions(PdfArray regions) { return Put(PdfName.TrapRegions, regions); } + /// + /// Gets an array of TrapRegion objects defining the page’s trapping zones + /// and the associated trapping parameters, as described in Adobe Technical Note #5620, + /// Portable Job Ticket Format. + /// + /// + /// Gets an array of TrapRegion objects defining the page’s trapping zones + /// and the associated trapping parameters, as described in Adobe Technical Note #5620, + /// Portable Job Ticket Format. + /// + /// key. + /// + /// + /// A + /// + /// of indirect references to TrapRegion objects. + /// public virtual PdfArray GetTrapRegions() { return GetPdfObject().GetAsArray(PdfName.TrapRegions); } + /// Sets a human-readable text string that described this trap network to the user. + /// + /// Sets a human-readable text string that described this trap network to the user. + /// + /// key. + /// + /// + /// a + /// + /// value. + /// + /// object itself. public virtual iText.Kernel.Pdf.Xobject.PdfFormXObject SetTrapStyles(PdfString trapStyles) { return Put(PdfName.TrapStyles, trapStyles); } + /// Gets a human-readable text string that described this trap network to the user. + /// + /// Gets a human-readable text string that described this trap network to the user. + /// + /// key. + /// + /// + /// a + /// + /// value. + /// public virtual PdfString GetTrapStyles() { return GetPdfObject().GetAsString(PdfName.TrapStyles); } - //Additional entries in form dictionary for Printer Mark annotation + //-----Additional entries in form dictionary for Printer Mark annotation + /// Sets a text string representing the printer’s mark in human-readable form. + /// a string value. + /// object itself. public virtual iText.Kernel.Pdf.Xobject.PdfFormXObject SetMarkStyle(PdfString markStyle) { return Put(PdfName.MarkStyle, markStyle); } + /// Gets a text string representing the printer’s mark in human-readable form. + /// a string value. public virtual PdfString GetMarkStyle() { return GetPdfObject().GetAsString(PdfName.MarkStyle); } - public virtual PdfArray GetBBox() { - return GetPdfObject().GetAsArray(PdfName.BBox); - } - - public virtual iText.Kernel.Pdf.Xobject.PdfFormXObject SetBBox(PdfArray bBox) { - return Put(PdfName.BBox, bBox); - } - - public virtual iText.Kernel.Pdf.Xobject.PdfFormXObject SetGroup(PdfTransparencyGroup transparency) { - return Put(PdfName.Group, transparency.GetPdfObject()); - } - - public override float GetWidth() { - return GetBBox() == null ? 0 : GetBBox().GetAsNumber(2).FloatValue(); - } - - public override float GetHeight() { - return GetBBox() == null ? 0 : GetBBox().GetAsNumber(3).FloatValue(); - } - + /// Puts the value into Image XObject dictionary and associates it with the specified key. + /// + /// Puts the value into Image XObject dictionary and associates it with the specified key. + /// If the key is already present, it will override the old value with the specified one. + /// + /// key to insert or to override + /// the value to associate with the specified key + /// object itself. public virtual iText.Kernel.Pdf.Xobject.PdfFormXObject Put(PdfName key, PdfObject value) { GetPdfObject().Put(key, value); return this; diff --git a/itext/itext.kernel/itext/kernel/pdf/xobject/PdfImageXObject.cs b/itext/itext.kernel/itext/kernel/pdf/xobject/PdfImageXObject.cs index 9b7227cc0b..8615e492bd 100644 --- a/itext/itext.kernel/itext/kernel/pdf/xobject/PdfImageXObject.cs +++ b/itext/itext.kernel/itext/kernel/pdf/xobject/PdfImageXObject.cs @@ -52,6 +52,8 @@ source product. using iText.Kernel.Pdf.Filters; namespace iText.Kernel.Pdf.Xobject { + /// A wrapper for Image XObject. + /// A wrapper for Image XObject. ISO 32000-1, 8.9 Images. public class PdfImageXObject : PdfXObject { private float width; @@ -73,20 +75,57 @@ public class PdfImageXObject : PdfXObject { private int stride; + /// Creates Image XObject by image. + /// + /// + /// + /// with actual image data. + /// public PdfImageXObject(ImageData image) : this(image, null) { } + /// Creates Image XObject by image. + /// + /// + /// + /// with actual image data. + /// + /// + /// + /// + /// with image mask. + /// public PdfImageXObject(ImageData image, iText.Kernel.Pdf.Xobject.PdfImageXObject imageMask) : this(CreatePdfStream(CheckImageType(image), imageMask)) { mask = image.IsMask(); softMask = image.IsSoftMask(); } - public PdfImageXObject(PdfStream pdfObject) - : base(pdfObject) { + /// + /// Create + /// + /// instance by + /// + /// . + /// Note, this constructor doesn't perform any additional checks + /// + /// + /// + /// + /// with Image XObject. + /// + /// + public PdfImageXObject(PdfStream pdfStream) + : base(pdfStream) { } + /// + /// Gets width of image, + /// Width + /// key. + /// + /// float value. public override float GetWidth() { if (!IsFlushed()) { return GetPdfObject().GetAsNumber(PdfName.Width).FloatValue(); @@ -96,6 +135,12 @@ public override float GetWidth() { } } + /// + /// Gets height of image, + /// Height + /// key. + /// + /// float value. public override float GetHeight() { if (!IsFlushed()) { return GetPdfObject().GetAsNumber(PdfName.Height).FloatValue(); @@ -105,6 +150,17 @@ public override float GetHeight() { } } + /// + /// To manually flush a + /// PdfObject + /// behind this wrapper, you have to ensure + /// that this object is added to the document, i.e. it has an indirect reference. + /// Basically this means that before flushing you need to explicitly call + /// + /// . + /// For example: wrapperInstance.makeIndirect(document).flush(); + /// Note, that not every wrapper require this, only those that have such warning in documentation. + /// public override void Flush() { if (!IsFlushed()) { width = GetPdfObject().GetAsNumber(PdfName.Width).FloatValue(); @@ -113,6 +169,13 @@ public override void Flush() { } } + /// Copy Image XObject to the specified document. + /// target document + /// + /// just created instance of + /// + /// . + /// public virtual iText.Kernel.Pdf.Xobject.PdfImageXObject CopyTo(PdfDocument document) { iText.Kernel.Pdf.Xobject.PdfImageXObject image = new iText.Kernel.Pdf.Xobject.PdfImageXObject(((PdfStream) GetPdfObject().CopyTo(document))); @@ -123,10 +186,29 @@ public virtual iText.Kernel.Pdf.Xobject.PdfImageXObject CopyTo(PdfDocument docum return image; } + /// Gets decoded image bytes. + /// byte array. public virtual byte[] GetImageBytes() { return GetImageBytes(true); } + /// Gets image bytes. + /// + /// Gets image bytes. + /// Note, + /// + /// , + /// + /// and + /// + /// filters will be ignored. + /// + /// + /// if + /// + /// , decodes stream bytes. + /// + /// byte array. public virtual byte[] GetImageBytes(bool decoded) { byte[] bytes; bytes = GetPdfObject().GetBytes(false); @@ -150,11 +232,126 @@ public virtual byte[] GetImageBytes(bool decoded) { return bytes; } + /// + /// Identifies the type of the image that is stored in the bytes of this + /// + /// . + /// Note that this has nothing to do with the original type of the image. For instance, the return value + /// of this method will never be + /// + /// as we loose this information when converting a + /// PNG image into something that can be put into a PDF file. + /// The possible values are: + /// + /// , + /// + /// , + /// + /// , + /// + /// , + /// + /// + /// the identified type of image + public virtual ImageType IdentifyImageType() { + PdfObject filter = GetPdfObject().Get(PdfName.Filter); + PdfArray filters = new PdfArray(); + if (filter != null) { + if (filter.GetObjectType() == PdfObject.NAME) { + filters.Add(filter); + } + else { + if (filter.GetObjectType() == PdfObject.ARRAY) { + filters = ((PdfArray)filter); + } + } + } + for (int i = filters.Size() - 1; i >= 0; i--) { + PdfName filterName = (PdfName)filters.Get(i); + if (PdfName.DCTDecode.Equals(filterName)) { + return ImageType.JPEG; + } + else { + if (PdfName.JBIG2Decode.Equals(filterName)) { + return ImageType.JBIG2; + } + else { + if (PdfName.JPXDecode.Equals(filterName)) { + return ImageType.JPEG2000; + } + } + } + } + // None of the previous types match + PdfObject colorspace = GetPdfObject().Get(PdfName.ColorSpace); + PrepareAndFindColorspace(colorspace); + if (pngColorType < 0) { + return ImageType.TIFF; + } + else { + return ImageType.PNG; + } + } + + /// + /// Identifies recommended file extension to store the bytes of this + /// + /// . + /// Possible values are: 'png', 'jpg', 'jp2', 'tif', 'jbig2'. + /// This extension can later be used together with the result of + /// + /// . + /// + /// + /// a + /// + /// with recommended file extension + /// + /// + public virtual String IdentifyImageFileExtension() { + ImageType bytesType = IdentifyImageType(); + switch (bytesType) { + case ImageType.PNG: { + return "png"; + } + + case ImageType.JPEG: { + return "jpg"; + } + + case ImageType.JPEG2000: { + return "jp2"; + } + + case ImageType.TIFF: { + return "tif"; + } + + case ImageType.JBIG2: { + return "jbig2"; + } + + default: { + throw new InvalidOperationException("Should have never happened. This type of image is not allowed for ImageXObject" + ); + } + } + } + + /// Puts the value into Image XObject dictionary and associates it with the specified key. + /// + /// Puts the value into Image XObject dictionary and associates it with the specified key. + /// If the key is already present, it will override the old value with the specified one. + /// + /// key to insert or to override + /// the value to associate with the specified key + /// object itself. public virtual iText.Kernel.Pdf.Xobject.PdfImageXObject Put(PdfName key, PdfObject value) { GetPdfObject().Put(key, value); return this; } + [Obsolete] protected internal static PdfStream CreatePdfStream(ImageData image, iText.Kernel.Pdf.Xobject.PdfImageXObject imageMask) { PdfStream stream; @@ -336,8 +533,13 @@ private static PdfArray CreateArray(PdfStream stream, Object[] objects) { array.Add(new PdfNumber((float)obj)); } else { - //TODO instance of was removed due to autoport - array.Add(CreateDictionaryFromMap(stream, (IDictionary)obj)); + if (obj is Object[]) { + array.Add(CreateArray(stream, (Object[])obj)); + } + else { + //TODO instance of was removed due to autoport + array.Add(CreateDictionaryFromMap(stream, (IDictionary)obj)); + } } } } @@ -345,19 +547,22 @@ private static PdfArray CreateArray(PdfStream stream, Object[] objects) { return array; } - /// - private byte[] DecodeTiffAndPngBytes(byte[] imageBytes) { + private void PrepareAndFindColorspace(PdfObject colorspace) { pngColorType = -1; - PdfArray decode = GetPdfObject().GetAsArray(PdfName.Decode); width = GetPdfObject().GetAsNumber(PdfName.Width).IntValue(); height = GetPdfObject().GetAsNumber(PdfName.Height).IntValue(); bpc = GetPdfObject().GetAsNumber(PdfName.BitsPerComponent).IntValue(); pngBitDepth = bpc; - PdfObject colorspace = GetPdfObject().Get(PdfName.ColorSpace); palette = null; icc = null; stride = 0; FindColorspace(colorspace, true); + } + + /// + private byte[] DecodeTiffAndPngBytes(byte[] imageBytes) { + PdfObject colorspace = GetPdfObject().Get(PdfName.ColorSpace); + PrepareAndFindColorspace(colorspace); MemoryStream ms = new MemoryStream(); if (pngColorType < 0) { if (bpc != 8) { @@ -413,6 +618,7 @@ private byte[] DecodeTiffAndPngBytes(byte[] imageBytes) { } else { PngWriter png = new PngWriter(ms); + PdfArray decode = GetPdfObject().GetAsArray(PdfName.Decode); if (decode != null) { if (pngBitDepth == 1) { // if the decode array is 1,0, then we need to invert the image diff --git a/itext/itext.kernel/itext/kernel/pdf/xobject/PdfXObject.cs b/itext/itext.kernel/itext/kernel/pdf/xobject/PdfXObject.cs index 1bb90160fc..5a7b4c5df0 100644 --- a/itext/itext.kernel/itext/kernel/pdf/xobject/PdfXObject.cs +++ b/itext/itext.kernel/itext/kernel/pdf/xobject/PdfXObject.cs @@ -42,42 +42,84 @@ source product. address: sales@itextpdf.com */ using System; +using iText.Kernel; using iText.Kernel.Pdf; using iText.Kernel.Pdf.Layer; namespace iText.Kernel.Pdf.Xobject { + /// An abstract wrapper for supported types of XObject. + /// + /// public class PdfXObject : PdfObjectWrapper { + [Obsolete] public PdfXObject() : this(new PdfStream()) { } + [Obsolete] public PdfXObject(PdfStream pdfObject) : base(pdfObject) { } + /// + /// Create + /// + /// or + /// + /// by + /// + /// . + /// + /// + /// + /// + /// with either + /// + /// or + /// + /// + /// + /// + /// + /// either + /// + /// or + /// + /// . + /// public static iText.Kernel.Pdf.Xobject.PdfXObject MakeXObject(PdfStream stream) { - if (PdfName.Form.Equals(stream.GetAsName(PdfName.Subtype)) || stream.ContainsKey(PdfName.BBox)) { + if (PdfName.Form.Equals(stream.GetAsName(PdfName.Subtype))) { return new PdfFormXObject(stream); } else { - return new PdfImageXObject(stream); + if (PdfName.Image.Equals(stream.GetAsName(PdfName.Subtype))) { + return new PdfImageXObject(stream); + } + else { + throw new NotSupportedException(PdfException.UnsupportedXObjectType); + } } } /// Sets the layer this XObject belongs to. - /// the layer this XObject belongs to + /// the layer this XObject belongs to. public virtual void SetLayer(IPdfOCG layer) { GetPdfObject().Put(PdfName.OC, layer.GetIndirectReference()); } + /// Gets width of XObject. + /// float value. public virtual float GetWidth() { throw new NotSupportedException(); } + /// Gets height of XObject. + /// float value. public virtual float GetHeight() { throw new NotSupportedException(); } + /// protected internal override bool IsWrappedObjectMustBeIndirect() { return true; } diff --git a/itext/itext.kernel/itext/kernel/utils/CompareTool.cs b/itext/itext.kernel/itext/kernel/utils/CompareTool.cs index f5023659a1..9fb4caed73 100644 --- a/itext/itext.kernel/itext/kernel/utils/CompareTool.cs +++ b/itext/itext.kernel/itext/kernel/utils/CompareTool.cs @@ -41,2165 +41,2312 @@ source product. For more information, please contact iText Software Corp. at this address: sales@itextpdf.com */ - using System; using System.Collections; using System.Collections.Generic; -using System.Diagnostics; using System.IO; -using System.Linq; using System.Text; using System.Xml; -using System.Xml.Linq; using iText.IO.Font; -using iText.IO.Source; using iText.IO.Util; using iText.Kernel.Geom; using iText.Kernel.Pdf; using iText.Kernel.Pdf.Annot; +using iText.Kernel.Pdf.Canvas; using iText.Kernel.XMP; using iText.Kernel.XMP.Options; -using Path = System.IO.Path; -namespace iText.Kernel.Utils -{ - public class CompareTool - { - private const String cannotOpenOutputDirectory = "Cannot open output directory for ."; +namespace iText.Kernel.Utils { + /// + /// This class provides means to compare two PDF files both by content and visually + /// and gives the report of their differences. + /// + /// + /// This class provides means to compare two PDF files both by content and visually + /// and gives the report of their differences. + ///

    + /// For visual comparison it uses external tools: Ghostscript and ImageMagick, which + /// should be installed on your machine. To allow CompareTool to use them, you need + /// to pass either java properties or environment variables with names "gsExec" and + /// "compareExec", which would contain the paths to the executables of correspondingly + /// Ghostscript and ImageMagick tools. + ///

    + /// CompareTool class was mainly designed for the testing purposes of iText in order to + /// ensure that the same code produces the same PDF document. For this reason you will + /// often encounter such parameter names as "outDoc" and "cmpDoc" which stand for output + /// document and document-for-comparison. The first one is viewed as the current result, + /// and the second one is referred as normal or ideal result. OutDoc is compared to the + /// ideal cmpDoc. Therefore all reports of the comparison are in the form: "Expected ..., + /// but was ...". This should be interpreted in the following way: "expected" part stands + /// for the content of the cmpDoc and "but was" part stands for the content of the outDoc. + ///
    + public class CompareTool { + private const String cannotOpenOutputDirectory = "Cannot open output directory for ."; + + private const String gsFailed = "GhostScript failed for ."; + + private const String unexpectedNumberOfPages = "Unexpected number of pages for ."; + + private const String differentPages = "File differs on page ."; + + private const String undefinedGsPath = "Path to GhostScript is not specified. Please use -DgsExec= (e.g. -DgsExec=\"C:/Program Files/gs/gs9.14/bin/gswin32c.exe\")"; + + private const String ignoredAreasPrefix = "ignored_areas_"; + + private const String gsParams = " -dNOPAUSE -dBATCH -sDEVICE=png16m -r150 -sOutputFile= "; + + private const String compareParams = " \"\" \"\" \"\""; + + private String gsExec; + + private String compareExec; + + private String cmpPdf; + + private String cmpPdfName; + + private String cmpImage; + + private String outPdf; + + private String outPdfName; + + private String outImage; + + private ReaderProperties outProps; + + private ReaderProperties cmpProps; + + private IList outPagesRef; + + private IList cmpPagesRef; + + private int compareByContentErrorsLimit = 1; + + private bool generateCompareByContentXmlReport = false; + + private bool encryptionCompareEnabled = false; + + private bool useCachedPagesForComparison = true; + + /// Creates an instance of the CompareTool. + public CompareTool() { + gsExec = iText.IO.Util.SystemUtil.GetEnvironmentVariable("gsExec"); + compareExec = iText.IO.Util.SystemUtil.GetEnvironmentVariable("compareExec"); + } + + /// + /// Compares two PDF documents by content starting from Catalog dictionary and then recursively comparing + /// corresponding objects which are referenced from it. + /// + /// + /// Compares two PDF documents by content starting from Catalog dictionary and then recursively comparing + /// corresponding objects which are referenced from it. You can roughly imagine it as depth-first traversal + /// of the two trees that represent pdf objects structure of the documents. + ///

    + /// The main difference between this method and the + /// + /// methods is the return value. This method returns a + /// + /// class instance, which could be used + /// in code, however compareByContent methods in case of the differences simply return String value, which could + /// only be printed. Also, keep in mind that this method doesn't perform visual comparison of the documents. + ///

    + /// For more explanations about what is outDoc and cmpDoc see last paragraph of the + /// + /// class description. + ///
    + /// the absolute path to the output file, which is to be compared to cmp-file. + /// the absolute path to the cmp-file, which is to be compared to output file. + /// + /// the report of comparison of two files in the form of the custom class instance. + /// See + /// + /// for more info. + /// + /// + public virtual CompareTool.CompareResult CompareByCatalog(PdfDocument outDocument, PdfDocument cmpDocument + ) { + CompareTool.CompareResult compareResult = null; + compareResult = new CompareTool.CompareResult(this, compareByContentErrorsLimit); + CompareTool.ObjectPath catalogPath = new CompareTool.ObjectPath(cmpDocument.GetCatalog().GetPdfObject().GetIndirectReference + (), outDocument.GetCatalog().GetPdfObject().GetIndirectReference()); + ICollection ignoredCatalogEntries = new LinkedHashSet(iText.IO.Util.JavaUtil.ArraysAsList + (PdfName.Metadata)); + CompareDictionariesExtended(outDocument.GetCatalog().GetPdfObject(), cmpDocument.GetCatalog().GetPdfObject + (), catalogPath, compareResult, ignoredCatalogEntries); + return compareResult; + } + + /// Disables the default logic of pages comparison. + /// + /// Disables the default logic of pages comparison. + /// This option makes sense only for + /// + /// method. + ///

    + /// By default, pages are treated as special objects and if they are met in the process of comparison, then they are + /// not checked as objects, but rather simply checked that they has same page numbers in both documents. + /// This behaviour is intended for the + /// + /// set of methods, because in them documents are compared in page by page basis. Thus, we don't need to check if pages + /// are of the same content when they are met in comparison process, we are sure that we will compare their content or + /// we have already compared them. + ///

    + /// However, if you would use + /// + /// with default behaviour + /// of pages comparison, pages won't be checked at all, every time when reference to the page dictionary is met, + /// only page numbers will be compared for both documents. You can say that in this case, comparison will be performed + /// for all document's catalog entries except /Pages (However in fact, document's page tree structures will be compared, + /// but pages themselves - won't). + /// + /// + /// this + /// + /// instance. + /// + public virtual iText.Kernel.Utils.CompareTool DisableCachedPagesComparison() { + this.useCachedPagesForComparison = false; + return this; + } + + ///

    Sets the maximum errors count which will be returned as the result of the comparison. + /// the errors count. + /// this CompareTool instance. + public virtual iText.Kernel.Utils.CompareTool SetCompareByContentErrorsLimit(int compareByContentMaxErrorCount + ) { + this.compareByContentErrorsLimit = compareByContentMaxErrorCount; + return this; + } + + /// Enables or disables the generation of the comparison report in the form of the xml document. + /// + /// Enables or disables the generation of the comparison report in the form of the xml document. + ///
    + /// IMPORTANT NOTE: this flag affect only the comparison made by compareByContent methods! + ///
    + /// true to enable xml report generation, false - to disable. + /// this CompareTool instance. + public virtual iText.Kernel.Utils.CompareTool SetGenerateCompareByContentXmlReport(bool generateCompareByContentXmlReport + ) { + this.generateCompareByContentXmlReport = generateCompareByContentXmlReport; + return this; + } + + /// Enables the comparison of the encryption properties of the documents. + /// + /// Enables the comparison of the encryption properties of the documents. Encryption properties comparison + /// results are returned along with all other comparison results. + ///
    + /// IMPORTANT NOTE: this flag affect only the comparison made by compareByContent methods! + ///
    + /// this CompareTool instance. + public virtual iText.Kernel.Utils.CompareTool EnableEncryptionCompare() { + this.encryptionCompareEnabled = true; + return this; + } + + /// Documents for comparison are opened in reader mode. + /// + /// Documents for comparison are opened in reader mode. This method is intended to alter + /// + /// which are used to open output document. This is particularly useful for comparison of encrypted documents. + ///

    + /// For more explanations about what is outDoc and cmpDoc see last paragraph of the + /// + /// class description. + /// + /// + /// + /// + /// instance which will be later passed to the output document + /// + /// . + /// + public virtual ReaderProperties GetOutReaderProperties() { + if (outProps == null) { + outProps = new ReaderProperties(); + } + return outProps; + } + + ///

    Documents for comparison are opened in reader mode. + /// + /// Documents for comparison are opened in reader mode. This method is intended to alter + /// + /// which are used to open cmp document. This is particularly useful for comparison of encrypted documents. + ///

    + /// For more explanations about what is outDoc and cmpDoc see last paragraph of the + /// + /// class description. + /// + /// + /// + /// + /// instance which will be later passed to the cmp document + /// + /// . + /// + public virtual ReaderProperties GetCmpReaderProperties() { + if (cmpProps == null) { + cmpProps = new ReaderProperties(); + } + return cmpProps; + } + + ///

    Compares two documents visually. + /// + /// Compares two documents visually. For the comparison two external tools are used: Ghostscript and ImageMagick. + /// For more info about needed configuration for visual comparison process see + /// + /// class description. + ///
    + /// During comparison for every page of two documents an image file will be created in the folder specified by + /// outPath absolute path. Then those page images will be compared and if there are any differences for some pages, + /// another image file will be created with marked differences on it. + ///
    + /// the absolute path to the output file, which is to be compared to cmp-file. + /// the absolute path to the cmp-file, which is to be compared to output file. + /// the absolute path to the folder, which will be used to store image files for visual comparison. + /// + /// file name prefix for image files with marked differences if there is any. + /// + /// string containing list of the pages that are visually different, or null if there are no visual differences. + /// + /// + /// + public virtual String CompareVisually(String outPdf, String cmpPdf, String outPath, String differenceImagePrefix + ) { + return CompareVisually(outPdf, cmpPdf, outPath, differenceImagePrefix, null); + } + + /// Compares two documents visually. + /// + /// Compares two documents visually. For the comparison two external tools are used: Ghostscript and ImageMagick. + /// For more info about needed configuration for visual comparison process see + /// + /// class description. + ///
    + /// During comparison for every page of two documents an image file will be created in the folder specified by + /// outPath absolute path. Then those page images will be compared and if there are any differences for some pages, + /// another image file will be created with marked differences on it. + ///
    + /// It is possible to ignore certain areas of the document pages during visual comparison. This is useful for example + /// in case if documents should be the same except certain page area with date on it. In this case, in the folder + /// specified by the outPath, new pdf documents will be created with the black rectangles at the specified ignored + /// areas, and visual comparison will be performed on these new documents. + ///
    + /// the absolute path to the output file, which is to be compared to cmp-file. + /// the absolute path to the cmp-file, which is to be compared to output file. + /// the absolute path to the folder, which will be used to store image files for visual comparison. + /// + /// file name prefix for image files with marked differences if there is any. + /// + /// a map with one-based page numbers as keys and lists of ignored rectangles as values. + /// + /// string containing list of the pages that are visually different, or null if there are no visual differences. + /// + /// + /// + public virtual String CompareVisually(String outPdf, String cmpPdf, String outPath, String differenceImagePrefix + , IDictionary> ignoredAreas) { + Init(outPdf, cmpPdf); + return CompareVisually(outPath, differenceImagePrefix, ignoredAreas); + } + + /// + /// Compares two PDF documents by content starting from page dictionaries and then recursively comparing + /// corresponding objects which are referenced from them. + /// + /// + /// Compares two PDF documents by content starting from page dictionaries and then recursively comparing + /// corresponding objects which are referenced from them. You can roughly imagine it as depth-first traversal + /// of the two trees that represent pdf objects structure of the documents. + ///

    + /// Unlike + /// + /// this method performs content comparison page by page + /// and doesn't compare the tag structure, acroforms and all other things that doesn't belong to specific pages. + ///
    + /// When comparison by content is finished, if any differences were found, visual comparison is automatically started. + /// For more info see + /// + /// . + ///

    + /// For more explanations about what is outPdf and cmpPdf see last paragraph of the + /// + /// class description. + ///
    + /// the absolute path to the output file, which is to be compared to cmp-file. + /// the absolute path to the cmp-file, which is to be compared to output file. + /// the absolute path to the folder, which will be used to store image files for visual comparison. + /// + /// file name prefix for image files with marked visual differences if there is any. + /// + /// + /// string containing text report of the encountered content differences and also list of the pages that are + /// visually different, or null if there are no content and therefore no visual differences. + /// + /// + /// + public virtual String CompareByContent(String outPdf, String cmpPdf, String outPath, String differenceImagePrefix + ) { + return CompareByContent(outPdf, cmpPdf, outPath, differenceImagePrefix, null, null, null); + } + + /// This method overload is used to compare two encrypted PDF documents. + /// + /// This method overload is used to compare two encrypted PDF documents. Document passwords are passed with + /// outPass and cmpPass parameters. + ///

    + /// Compares two PDF documents by content starting from page dictionaries and then recursively comparing + /// corresponding objects which are referenced from them. You can roughly imagine it as depth-first traversal + /// of the two trees that represent pdf objects structure of the documents. + ///

    + /// Unlike + /// + /// this method performs content comparison page by page + /// and doesn't compare the tag structure, acroforms and all other things that doesn't belong to specific pages. + ///
    + /// When comparison by content is finished, if any differences were found, visual comparison is automatically started. + /// For more info see + /// + /// . + ///

    + /// For more explanations about what is outPdf and cmpPdf see last paragraph of the + /// + /// class description. + ///
    + /// the absolute path to the output file, which is to be compared to cmp-file. + /// the absolute path to the cmp-file, which is to be compared to output file. + /// the absolute path to the folder, which will be used to store image files for visual comparison. + /// + /// file name prefix for image files with marked visual differences if there is any. + /// + /// password for the encrypted document specified by the outPdf absolute path. + /// password for the encrypted document specified by the cmpPdf absolute path. + /// + /// string containing text report of the encountered content differences and also list of the pages that are + /// visually different, or null if there are no content and therefore no visual differences. + /// + /// + /// + public virtual String CompareByContent(String outPdf, String cmpPdf, String outPath, String differenceImagePrefix + , byte[] outPass, byte[] cmpPass) { + return CompareByContent(outPdf, cmpPdf, outPath, differenceImagePrefix, null, outPass, cmpPass); + } + + /// + /// Compares two PDF documents by content starting from page dictionaries and then recursively comparing + /// corresponding objects which are referenced from them. + /// + /// + /// Compares two PDF documents by content starting from page dictionaries and then recursively comparing + /// corresponding objects which are referenced from them. You can roughly imagine it as depth-first traversal + /// of the two trees that represent pdf objects structure of the documents. + ///

    + /// Unlike + /// + /// this method performs content comparison page by page + /// and doesn't compare the tag structure, acroforms and all other things that doesn't belong to specific pages. + ///
    + /// When comparison by content is finished, if any differences were found, visual comparison is automatically started. + /// For more info see + /// + /// . + ///

    + /// For more explanations about what is outPdf and cmpPdf see last paragraph of the + /// + /// class description. + ///
    + /// the absolute path to the output file, which is to be compared to cmp-file. + /// the absolute path to the cmp-file, which is to be compared to output file. + /// the absolute path to the folder, which will be used to store image files for visual comparison. + /// + /// file name prefix for image files with marked visual differences if there is any. + /// + /// a map with one-based page numbers as keys and lists of ignored rectangles as values. + /// + /// + /// string containing text report of the encountered content differences and also list of the pages that are + /// visually different, or null if there are no content and therefore no visual differences. + /// + /// + /// + public virtual String CompareByContent(String outPdf, String cmpPdf, String outPath, String differenceImagePrefix + , IDictionary> ignoredAreas) { + Init(outPdf, cmpPdf); + return CompareByContent(outPath, differenceImagePrefix, ignoredAreas); + } + + /// This method overload is used to compare two encrypted PDF documents. + /// + /// This method overload is used to compare two encrypted PDF documents. Document passwords are passed with + /// outPass and cmpPass parameters. + ///

    + /// Compares two PDF documents by content starting from page dictionaries and then recursively comparing + /// corresponding objects which are referenced from them. You can roughly imagine it as depth-first traversal + /// of the two trees that represent pdf objects structure of the documents. + ///

    + /// Unlike + /// + /// this method performs content comparison page by page + /// and doesn't compare the tag structure, acroforms and all other things that doesn't belong to specific pages. + ///
    + /// When comparison by content is finished, if any differences were found, visual comparison is automatically started. + /// For more info see + /// + /// . + ///

    + /// For more explanations about what is outPdf and cmpPdf see last paragraph of the + /// + /// class description. + ///
    + /// the absolute path to the output file, which is to be compared to cmp-file. + /// the absolute path to the cmp-file, which is to be compared to output file. + /// the absolute path to the folder, which will be used to store image files for visual comparison. + /// + /// file name prefix for image files with marked visual differences if there is any. + /// + /// a map with one-based page numbers as keys and lists of ignored rectangles as values. + /// + /// password for the encrypted document specified by the outPdf absolute path. + /// password for the encrypted document specified by the cmpPdf absolute path. + /// + /// string containing text report of the encountered content differences and also list of the pages that are + /// visually different, or null if there are no content and therefore no visual differences. + /// + /// + /// + public virtual String CompareByContent(String outPdf, String cmpPdf, String outPath, String differenceImagePrefix + , IDictionary> ignoredAreas, byte[] outPass, byte[] cmpPass) { + Init(outPdf, cmpPdf); + SetPassword(outPass, cmpPass); + return CompareByContent(outPath, differenceImagePrefix, ignoredAreas); + } + + /// Simple method that compares two given PdfDictionaries by content. + /// + /// Simple method that compares two given PdfDictionaries by content. This is "deep" comparing, which means that all + /// nested objects are also compared by content. + /// + /// dictionary to compare. + /// dictionary to compare. + /// true if dictionaries are equal by content, otherwise false. + /// + public virtual bool CompareDictionaries(PdfDictionary outDict, PdfDictionary cmpDict) { + return CompareDictionariesExtended(outDict, cmpDict, null, null); + } + + /// Simple method that compares two given PdfStreams by content. + /// + /// Simple method that compares two given PdfStreams by content. This is "deep" comparing, which means that all + /// nested objects are also compared by content. + /// + /// stream to compare. + /// stream to compare. + /// true if stream are equal by content, otherwise false. + /// + public virtual bool CompareStreams(PdfStream outStream, PdfStream cmpStream) { + return CompareStreamsExtended(outStream, cmpStream, null, null); + } + + /// Simple method that compares two given PdfArrays by content. + /// + /// Simple method that compares two given PdfArrays by content. This is "deep" comparing, which means that all + /// nested objects are also compared by content. + /// + /// array to compare. + /// array to compare. + /// true if arrays are equal by content, otherwise false. + /// + public virtual bool CompareArrays(PdfArray outArray, PdfArray cmpArray) { + return CompareArraysExtended(outArray, cmpArray, null, null); + } + + /// Simple method that compares two given PdfNames. + /// name to compare. + /// name to compare. + /// true if names are equal, otherwise false. + public virtual bool CompareNames(PdfName outName, PdfName cmpName) { + return cmpName.Equals(outName); + } + + /// Simple method that compares two given PdfNumbers. + /// number to compare. + /// number to compare. + /// true if numbers are equal, otherwise false. + public virtual bool CompareNumbers(PdfNumber outNumber, PdfNumber cmpNumber) { + return cmpNumber.GetValue() == outNumber.GetValue(); + } - private const String gsFailed = "GhostScript failed for ."; + /// Simple method that compares two given PdfStrings. + /// string to compare. + /// string to compare. + /// true if strings are equal, otherwise false. + public virtual bool CompareStrings(PdfString outString, PdfString cmpString) { + return cmpString.GetValue().Equals(outString.GetValue()); + } - private const String unexpectedNumberOfPages = "Unexpected number of pages for ."; + /// Simple method that compares two given PdfBooleans. + /// boolean to compare. + /// boolean to compare. + /// true if booleans are equal, otherwise false. + public virtual bool CompareBooleans(PdfBoolean outBoolean, PdfBoolean cmpBoolean) { + return cmpBoolean.GetValue() == outBoolean.GetValue(); + } - private const String differentPages = "File differs on page ."; + /// Compares xmp metadata of the two given PDF documents. + /// the absolute path to the output file, which xmp is to be compared to cmp-file. + /// the absolute path to the cmp-file, which xmp is to be compared to output file. + /// text report of the xmp differences, or null if there are no differences. + public virtual String CompareXmp(String outPdf, String cmpPdf) { + return CompareXmp(outPdf, cmpPdf, false); + } - private const String undefinedGsPath = "Path to GhostScript is not specified. Please use -DgsExec= (e.g. -DgsExec=\"C:/Program Files/gs/gs9.14/bin/gswin32c.exe\")"; + /// Compares xmp metadata of the two given PDF documents. + /// the absolute path to the output file, which xmp is to be compared to cmp-file. + /// the absolute path to the cmp-file, which xmp is to be compared to output file. + /// + /// true, if to ignore differences in date or producer xmp metadata + /// properties. + /// + /// text report of the xmp differences, or null if there are no differences. + public virtual String CompareXmp(String outPdf, String cmpPdf, bool ignoreDateAndProducerProperties) { + Init(outPdf, cmpPdf); + PdfDocument cmpDocument = null; + PdfDocument outDocument = null; + try { + cmpDocument = new PdfDocument(new PdfReader(this.cmpPdf)); + outDocument = new PdfDocument(new PdfReader(this.outPdf)); + byte[] cmpBytes = cmpDocument.GetXmpMetadata(); + byte[] outBytes = outDocument.GetXmpMetadata(); + if (ignoreDateAndProducerProperties) { + XMPMeta xmpMeta = XMPMetaFactory.ParseFromBuffer(cmpBytes); + XMPUtils.RemoveProperties(xmpMeta, XMPConst.NS_XMP, PdfConst.CreateDate, true, true); + XMPUtils.RemoveProperties(xmpMeta, XMPConst.NS_XMP, PdfConst.ModifyDate, true, true); + XMPUtils.RemoveProperties(xmpMeta, XMPConst.NS_XMP, PdfConst.MetadataDate, true, true); + XMPUtils.RemoveProperties(xmpMeta, XMPConst.NS_PDF, PdfConst.Producer, true, true); + cmpBytes = XMPMetaFactory.SerializeToBuffer(xmpMeta, new SerializeOptions(SerializeOptions.SORT)); + xmpMeta = XMPMetaFactory.ParseFromBuffer(outBytes); + XMPUtils.RemoveProperties(xmpMeta, XMPConst.NS_XMP, PdfConst.CreateDate, true, true); + XMPUtils.RemoveProperties(xmpMeta, XMPConst.NS_XMP, PdfConst.ModifyDate, true, true); + XMPUtils.RemoveProperties(xmpMeta, XMPConst.NS_XMP, PdfConst.MetadataDate, true, true); + XMPUtils.RemoveProperties(xmpMeta, XMPConst.NS_PDF, PdfConst.Producer, true, true); + outBytes = XMPMetaFactory.SerializeToBuffer(xmpMeta, new SerializeOptions(SerializeOptions.SORT)); + } + if (!CompareXmls(cmpBytes, outBytes)) { + return "The XMP packages different!"; + } + } + catch (Exception) { + return "XMP parsing failure!"; + } + finally { + if (cmpDocument != null) { + cmpDocument.Close(); + } + if (outDocument != null) { + outDocument.Close(); + } + } + return null; + } - private const String ignoredAreasPrefix = "ignored_areas_"; + /// Utility method that provides simple comparison of the two xml files stored in byte arrays. + /// first xml file data to compare. + /// second xml file data to compare. + /// true if xml structures are identical, false otherwise. + /// + /// + /// + public virtual bool CompareXmls(byte[] xml1, byte[] xml2) { + return XmlUtils.CompareXmls(new MemoryStream(xml1), new MemoryStream(xml2)); + } - private const String gsParams = " -dNOPAUSE -dBATCH -sDEVICE=png16m -r150 -sOutputFile= "; + /// Utility method that provides simple comparison of the two xml files. + /// absolute path to the first xml file to compare. + /// absolute path to the second xml file to compare. + /// true if xml structures are identical, false otherwise. + /// + /// + /// + public virtual bool CompareXmls(String xmlFilePath1, String xmlFilePath2) { + return XmlUtils.CompareXmls(new FileStream(xmlFilePath1, FileMode.Open, FileAccess.Read), new FileStream(xmlFilePath2 + , FileMode.Open, FileAccess.Read)); + } - private const String compareParams = " \"\" \"\" \"\""; + /// This method overload is used to compare two encrypted PDF documents. + /// + /// This method overload is used to compare two encrypted PDF documents. Document passwords are passed with + /// outPass and cmpPass parameters. + ///

    + /// Compares document info dictionaries of two pdf documents. + ///
    + /// the absolute path to the output file, which info is to be compared to cmp-file info. + /// the absolute path to the cmp-file, which info is to be compared to output file info. + /// password for the encrypted document specified by the outPdf absolute path. + /// password for the encrypted document specified by the cmpPdf absolute path. + /// text report of the differences in documents infos. + /// + public virtual String CompareDocumentInfo(String outPdf, String cmpPdf, byte[] outPass, byte[] cmpPass) { + System.Console.Out.Write("[itext] INFO Comparing document info......."); + String message = null; + SetPassword(outPass, cmpPass); + PdfDocument outDocument = new PdfDocument(new PdfReader(outPdf, GetOutReaderProperties())); + PdfDocument cmpDocument = new PdfDocument(new PdfReader(cmpPdf, GetCmpReaderProperties())); + String[] cmpInfo = ConvertInfo(cmpDocument.GetDocumentInfo()); + String[] outInfo = ConvertInfo(outDocument.GetDocumentInfo()); + for (int i = 0; i < cmpInfo.Length; ++i) { + if (!cmpInfo[i].Equals(outInfo[i])) { + message = "Document info fail"; + break; + } + } + outDocument.Close(); + cmpDocument.Close(); + if (message == null) { + System.Console.Out.WriteLine("OK"); + } + else { + System.Console.Out.WriteLine("Fail"); + } + System.Console.Out.Flush(); + return message; + } - private String gsExec; + /// Compares document info dictionaries of two pdf documents. + /// the absolute path to the output file, which info is to be compared to cmp-file info. + /// the absolute path to the cmp-file, which info is to be compared to output file info. + /// text report of the differences in documents infos. + /// + public virtual String CompareDocumentInfo(String outPdf, String cmpPdf) { + return CompareDocumentInfo(outPdf, cmpPdf, null, null); + } - private String compareExec; + /// Compares if two documents has identical link annotations on corresponding pages. + /// the absolute path to the output file, which links are to be compared to cmp-file links. + /// + /// the absolute path to the cmp-file, which links are to be compared to output file links. + /// + /// text report of the differences in documents links. + /// + public virtual String CompareLinkAnnotations(String outPdf, String cmpPdf) { + System.Console.Out.Write("[itext] INFO Comparing link annotations...."); + String message = null; + PdfDocument outDocument = new PdfDocument(new PdfReader(outPdf)); + PdfDocument cmpDocument = new PdfDocument(new PdfReader(cmpPdf)); + for (int i = 0; i < outDocument.GetNumberOfPages() && i < cmpDocument.GetNumberOfPages(); i++) { + IList outLinks = GetLinkAnnotations(i + 1, outDocument); + IList cmpLinks = GetLinkAnnotations(i + 1, cmpDocument); + if (cmpLinks.Count != outLinks.Count) { + message = String.Format("Different number of links on page {0}.", i + 1); + break; + } + for (int j = 0; j < cmpLinks.Count; j++) { + if (!CompareLinkAnnotations(cmpLinks[j], outLinks[j], cmpDocument, outDocument)) { + message = String.Format("Different links on page {0}.\n{1}\n{2}", i + 1, cmpLinks[j].ToString(), outLinks[ + j].ToString()); + break; + } + } + } + outDocument.Close(); + cmpDocument.Close(); + if (message == null) { + System.Console.Out.WriteLine("OK"); + } + else { + System.Console.Out.WriteLine("Fail"); + } + System.Console.Out.Flush(); + return message; + } - private String cmpPdf; - - private String cmpPdfName; + /// Compares tag structures of the two PDF documents. + /// + /// Compares tag structures of the two PDF documents. + ///
    + /// This method creates xml files in the same folder with outPdf file. These xml files contain documents tag structures + /// converted into the xml structure. These xml files are compared if they are equal. + ///
    + /// the absolute path to the output file, which tags are to be compared to cmp-file tags. + /// + /// the absolute path to the cmp-file, which tags are to be compared to output file tags. + /// + /// text report of the differences in documents tags. + /// + /// + /// + public virtual String CompareTagStructures(String outPdf, String cmpPdf) { + System.Console.Out.Write("[itext] INFO Comparing tag structures......"); + String outXmlPath = outPdf.Replace(".pdf", ".xml"); + String cmpXmlPath = outPdf.Replace(".pdf", ".cmp.xml"); + String message = null; + PdfReader readerOut = new PdfReader(outPdf); + PdfDocument docOut = new PdfDocument(readerOut); + FileStream xmlOut = new FileStream(outXmlPath, FileMode.Create); + new TaggedPdfReaderTool(docOut).SetRootTag("root").ConvertToXml(xmlOut); + docOut.Close(); + xmlOut.Close(); + PdfReader readerCmp = new PdfReader(cmpPdf); + PdfDocument docCmp = new PdfDocument(readerCmp); + FileStream xmlCmp = new FileStream(cmpXmlPath, FileMode.Create); + new TaggedPdfReaderTool(docCmp).SetRootTag("root").ConvertToXml(xmlCmp); + docCmp.Close(); + xmlCmp.Close(); + if (!CompareXmls(outXmlPath, cmpXmlPath)) { + message = "The tag structures are different."; + } + if (message == null) { + System.Console.Out.WriteLine("OK"); + } + else { + System.Console.Out.WriteLine("Fail"); + } + System.Console.Out.Flush(); + return message; + } - private String cmpImage; - - private String outPdf; - - private String outPdfName; - - private String outImage; - - private IList outPagesRef; - - private IList cmpPagesRef; - - private int compareByContentErrorsLimit = 1; - - private bool generateCompareByContentXmlReport = false; - - private bool encryptionCompareEnabled = false; - - private bool useCachedPagesForComparison = true; - - public CompareTool() - { - gsExec = System.Environment.GetEnvironmentVariable("gsExec"); - compareExec = System.Environment.GetEnvironmentVariable("compareExec"); - } - - /// - public virtual CompareTool.CompareResult CompareByCatalog(PdfDocument outDocument - , PdfDocument cmpDocument) - { - CompareTool.CompareResult compareResult = null; - compareResult = new CompareTool.CompareResult(this, compareByContentErrorsLimit); - CompareTool.ObjectPath catalogPath = new CompareTool.ObjectPath(cmpDocument - .GetCatalog().GetPdfObject().GetIndirectReference(), outDocument.GetCatalog().GetPdfObject - ().GetIndirectReference()); - ICollection ignoredCatalogEntries = new LinkedHashSet(iText.IO.Util.JavaUtil.ArraysAsList - (PdfName.Metadata)); - CompareDictionariesExtended(outDocument.GetCatalog().GetPdfObject(), cmpDocument. - GetCatalog().GetPdfObject(), catalogPath, compareResult, ignoredCatalogEntries); - return compareResult; - } - - public virtual iText.Kernel.Utils.CompareTool DisableCachedPagesComparison() - { - this.useCachedPagesForComparison = false; - return this; - } - - /// Sets the maximum errors count which will be returned as the result of the comparison. - /// - /// the errors count. - /// Returns this. - public virtual iText.Kernel.Utils.CompareTool SetCompareByContentErrorsLimit - (int compareByContentMaxErrorCount) - { - this.compareByContentErrorsLimit = compareByContentMaxErrorCount; - return this; - } - - public virtual iText.Kernel.Utils.CompareTool SetGenerateCompareByContentXmlReport - (bool generateCompareByContentXmlReport) - { - this.generateCompareByContentXmlReport = generateCompareByContentXmlReport; - return this; - } - - public virtual iText.Kernel.Utils.CompareTool EnableEncryptionCompare() - { - this.encryptionCompareEnabled = true; - return this; - } - - /// - /// - public virtual String CompareVisually(String outPdf, String cmpPdf, String outPath - , String differenceImagePrefix) - { - return CompareVisually(outPdf, cmpPdf, outPath, differenceImagePrefix, null); - } - - /// - /// - public virtual String CompareVisually(String outPdf, String cmpPdf, String outPath - , String differenceImagePrefix, IDictionary> ignoredAreas - ) - { - Init(outPdf, cmpPdf); - return CompareVisually(outPath, differenceImagePrefix, ignoredAreas); - } - - /// - /// - public virtual String CompareByContent(String outPdf, String cmpPdf, String outPath - , String differenceImagePrefix) - { - return CompareByContent(outPdf, cmpPdf, outPath, differenceImagePrefix, null, null - , null); - } - - /// - /// - public virtual String CompareByContent(String outPdf, String cmpPdf, String outPath - , String differenceImagePrefix, byte[] outPass, byte[] cmpPass) - { - return CompareByContent(outPdf, cmpPdf, outPath, differenceImagePrefix, null, outPass - , cmpPass); - } - - /// - /// - public virtual String CompareByContent(String outPdf, String cmpPdf, String outPath - , String differenceImagePrefix, IDictionary> ignoredAreas - ) - { - Init(outPdf, cmpPdf); - return CompareByContent(outPath, differenceImagePrefix, ignoredAreas, null, null); - } - - /// - /// - public virtual String CompareByContent(String outPdf, String cmpPdf, String outPath - , String differenceImagePrefix, IDictionary> ignoredAreas - , byte[] outPass, byte[] cmpPass) - { - Init(outPdf, cmpPdf); - return CompareByContent(outPath, differenceImagePrefix, ignoredAreas, outPass, cmpPass - ); - } - - /// - public virtual bool CompareDictionaries(PdfDictionary outDict, PdfDictionary cmpDict - ) - { - return CompareDictionariesExtended(outDict, cmpDict, null, null); - } - - /// - public virtual bool CompareStreams(PdfStream outStream, PdfStream cmpStream) - { - return CompareStreamsExtended(outStream, cmpStream, null, null); - } - - /// - public virtual bool CompareArrays(PdfArray outArray, PdfArray cmpArray) - { - return CompareArraysExtended(outArray, cmpArray, null, null); - } - - public virtual bool CompareNames(PdfName outName, PdfName cmpName) - { - return cmpName.Equals(outName); - } - - public virtual bool CompareNumbers(PdfNumber outNumber, PdfNumber cmpNumber) { - return 0 == cmpNumber.GetValue().CompareTo(outNumber.GetValue()); - } - - public virtual bool CompareStrings(PdfString outString, PdfString cmpString) - { - return cmpString.GetValue().Equals(outString.GetValue()); - } - - public virtual bool CompareBooleans(PdfBoolean outBoolean, PdfBoolean cmpBoolean) - { - return cmpBoolean.GetValue() == outBoolean.GetValue(); - } - - public virtual String CompareXmp(String outPdf, String cmpPdf) - { - return CompareXmp(outPdf, cmpPdf, false); - } - - public virtual String CompareXmp(String outPdf, String cmpPdf, bool ignoreDateAndProducerProperties - ) - { - Init(outPdf, cmpPdf); - PdfDocument cmpDocument = null; - PdfDocument outDocument = null; - try - { - cmpDocument = new PdfDocument(new PdfReader(this.cmpPdf)); - outDocument = new PdfDocument(new PdfReader(this.outPdf)); - byte[] cmpBytes = cmpDocument.GetXmpMetadata(); - byte[] outBytes = outDocument.GetXmpMetadata(); - if (ignoreDateAndProducerProperties) - { - XMPMeta xmpMeta = XMPMetaFactory.ParseFromBuffer(cmpBytes); - XMPUtils.RemoveProperties(xmpMeta, XMPConst.NS_XMP, PdfConst.CreateDate, true, true - ); - XMPUtils.RemoveProperties(xmpMeta, XMPConst.NS_XMP, PdfConst.ModifyDate, true, true - ); - XMPUtils.RemoveProperties(xmpMeta, XMPConst.NS_XMP, PdfConst.MetadataDate, true, - true); - XMPUtils.RemoveProperties(xmpMeta, XMPConst.NS_PDF, PdfConst.Producer, true, true - ); - cmpBytes = XMPMetaFactory.SerializeToBuffer(xmpMeta, new SerializeOptions(SerializeOptions - .SORT)); - xmpMeta = XMPMetaFactory.ParseFromBuffer(outBytes); - XMPUtils.RemoveProperties(xmpMeta, XMPConst.NS_XMP, PdfConst.CreateDate, true, true - ); - XMPUtils.RemoveProperties(xmpMeta, XMPConst.NS_XMP, PdfConst.ModifyDate, true, true - ); - XMPUtils.RemoveProperties(xmpMeta, XMPConst.NS_XMP, PdfConst.MetadataDate, true, - true); - XMPUtils.RemoveProperties(xmpMeta, XMPConst.NS_PDF, PdfConst.Producer, true, true - ); - outBytes = XMPMetaFactory.SerializeToBuffer(xmpMeta, new SerializeOptions(SerializeOptions - .SORT)); - } - if (!CompareXmls(cmpBytes, outBytes)) - { - return "The XMP packages different!"; - } - } - catch (XMPException) - { - return "XMP parsing failure!"; - } - catch (System.IO.IOException) - { - return "XMP parsing failure!"; - } - finally - { - if (cmpDocument != null) - { - cmpDocument.Close(); - } - if (outDocument != null) - { - outDocument.Close(); - } - } - return null; - } - - /// - /// - /// - public virtual bool CompareXmls(byte[] xml1, byte[] xml2) - { - return CompareXmls(new MemoryStream(xml1), new MemoryStream(xml2)); - } - - /// - /// - /// - public virtual bool CompareXmls(String xmlFilePath1, String xmlFilePath2) - { - return CompareXmls(new FileStream(xmlFilePath1, FileMode.Open, FileAccess.Read), new FileStream(xmlFilePath2 - , FileMode.Open, FileAccess.Read)); - } - - /// - public virtual String CompareDocumentInfo(String outPdf, String cmpPdf, byte[] outPass - , byte[] cmpPass) - { - System.Console.Out.Write("[itext] INFO Comparing document info......."); - String message = null; - PdfDocument outDocument = new PdfDocument(new PdfReader(outPdf, new ReaderProperties - ().SetPassword(outPass))); - PdfDocument cmpDocument = new PdfDocument(new PdfReader(cmpPdf, new ReaderProperties - ().SetPassword(cmpPass))); - String[] cmpInfo = ConvertInfo(cmpDocument.GetDocumentInfo()); - String[] outInfo = ConvertInfo(outDocument.GetDocumentInfo()); - for (int i = 0; i < cmpInfo.Length; ++i) - { - if (!cmpInfo[i].Equals(outInfo[i])) - { - message = "Document info fail"; - break; - } - } - outDocument.Close(); - cmpDocument.Close(); - if (message == null) - { - System.Console.Out.WriteLine("OK"); - } - else - { - System.Console.Out.WriteLine("Fail"); - } - System.Console.Out.Flush(); - return message; - } - - /// - public virtual String CompareDocumentInfo(String outPdf, String cmpPdf) - { - return CompareDocumentInfo(outPdf, cmpPdf, null, null); - } - - /// - public virtual String CompareLinkAnnotations(String outPdf, String cmpPdf) - { - System.Console.Out.Write("[itext] INFO Comparing link annotations...."); - String message = null; - PdfDocument outDocument = new PdfDocument(new PdfReader(outPdf)); - PdfDocument cmpDocument = new PdfDocument(new PdfReader(cmpPdf)); - for (int i = 0; i < outDocument.GetNumberOfPages() && i < cmpDocument.GetNumberOfPages - (); i++) - { - IList outLinks = GetLinkAnnotations(i + 1, outDocument); - IList cmpLinks = GetLinkAnnotations(i + 1, cmpDocument); - if (cmpLinks.Count != outLinks.Count) - { - message = String.Format("Different number of links on page {0}.", i + 1); - break; - } - for (int j = 0; j < cmpLinks.Count; j++) - { - if (!CompareLinkAnnotations(cmpLinks[j], outLinks[j], cmpDocument, outDocument)) - { - message = String.Format("Different links on page {0}.\n{1}\n{2}", i + 1, cmpLinks - [j].ToString(), outLinks[j].ToString()); - break; - } - } - } - outDocument.Close(); - cmpDocument.Close(); - if (message == null) - { - System.Console.Out.WriteLine("OK"); - } - else - { - System.Console.Out.WriteLine("Fail"); - } - System.Console.Out.Flush(); - return message; - } - - /// - /// - /// - public virtual String CompareTagStructures(String outPdf, String cmpPdf) - { - System.Console.Out.Write("[itext] INFO Comparing tag structures......"); - String outXmlPath = outPdf.Replace(".pdf", ".xml"); - String cmpXmlPath = outPdf.Replace(".pdf", ".cmp.xml"); - String message = null; - PdfReader readerOut = new PdfReader(outPdf); - PdfDocument docOut = new PdfDocument(readerOut); - FileStream xmlOut = new FileStream(outXmlPath, FileMode.Create); - new TaggedPdfReaderTool(docOut).SetRootTag("root").ConvertToXml(xmlOut); - docOut.Close(); - xmlOut.Close(); - PdfReader readerCmp = new PdfReader(cmpPdf); - PdfDocument docCmp = new PdfDocument(readerCmp); - FileStream xmlCmp = new FileStream(cmpXmlPath, FileMode.Create); - new TaggedPdfReaderTool(docCmp).SetRootTag("root").ConvertToXml(xmlCmp); - docCmp.Close(); - xmlCmp.Close(); - if (!CompareXmls(outXmlPath, cmpXmlPath)) - { - message = "The tag structures are different."; - } - if (message == null) - { - System.Console.Out.WriteLine("OK"); - } - else - { - System.Console.Out.WriteLine("Fail"); - } - System.Console.Out.Flush(); - return message; - } - - private void Init(String outPdf, String cmpPdf) - { - this.outPdf = outPdf; - this.cmpPdf = cmpPdf; - outPdfName = new FileInfo(outPdf).Name; + private void Init(String outPdf, String cmpPdf) { + this.outPdf = outPdf; + this.cmpPdf = cmpPdf; + outPdfName = new FileInfo(outPdf).Name; cmpPdfName = new FileInfo(cmpPdf).Name; - outImage = outPdfName + "-%03d.png"; - if (cmpPdfName.StartsWith("cmp_")) - { - cmpImage = cmpPdfName + "-%03d.png"; - } - else - { - cmpImage = "cmp_" + cmpPdfName + "-%03d.png"; - } - } - - /// - /// - private String CompareVisually(String outPath, String differenceImagePrefix, IDictionary - > ignoredAreas) - { - return CompareVisually(outPath, differenceImagePrefix, ignoredAreas, null); - } - - /// - /// - private String CompareVisually(String outPath, String differenceImagePrefix, IDictionary - > ignoredAreas, IList equalPages) - { - if (gsExec == null) - { - return undefinedGsPath; - } - if (!FileUtil.FileExists(gsExec)) - { - return Path.GetFullPath(gsExec) + " does not exist"; - } - if (!outPath.EndsWith("/")) - { - outPath = outPath + "/"; - } - PrepareOutputDirs(outPath, differenceImagePrefix); - if (ignoredAreas != null && ignoredAreas.Count > 0) - { - CreateIgnoredAreasPdfs(outPath, ignoredAreas); - } - String imagesGenerationResult = RunGhostScriptImageGeneration(outPath); - if (imagesGenerationResult != null) - { - return imagesGenerationResult; - } - return CompareImagesOfPdfs(outPath, differenceImagePrefix, equalPages); - } - - /// - /// - private String CompareImagesOfPdfs(String outPath, String differenceImagePrefix, - IList equalPages) - { - String[] imageFiles = FileUtil.ListFilesInDirectoryByFilter(outPath, false, new PngFileFilter(this)); - String[] cmpImageFiles = FileUtil.ListFilesInDirectoryByFilter(outPath, false, new CmpPngFileFilter(this)); - - bool bUnexpectedNumberOfPages = false; - if (imageFiles.Length != cmpImageFiles.Length) - { - bUnexpectedNumberOfPages = true; - } - int cnt = Math.Min(imageFiles.Length, cmpImageFiles.Length); - if (cnt < 1) - { - return "No files for comparing.\nThe result or sample pdf file is not processed by GhostScript."; - } - System.Array.Sort(imageFiles, new CompareTool.ImageNameComparator(this)); - System.Array.Sort(cmpImageFiles, new CompareTool.ImageNameComparator(this)); - String differentPagesFail = null; - bool compareExecIsOk = compareExec != null && FileUtil.FileExists(compareExec); - IList diffPages = new List(); - for (int i = 0; i < cnt; i++) - { - if (equalPages != null && equalPages.Contains(i)) - { - continue; - } - System.Console.Out.Write("Comparing page " + iText.IO.Util.JavaUtil.IntegerToString - (i + 1) + " (" + imageFiles[i] + ")..."); - FileStream is1 = new FileStream(imageFiles[i], FileMode.Open, FileAccess.Read); - FileStream is2 = new FileStream(cmpImageFiles[i], FileMode.Open, FileAccess.Read); - bool cmpResult = CompareStreams(is1, is2); - is1.Close(); - is2.Close(); - if (!cmpResult) - { - differentPagesFail = " Page is different!"; - diffPages.Add(i + 1); - if (compareExecIsOk) - { - String currCompareParams = compareParams.Replace("", imageFiles[i]) - .Replace("", cmpImageFiles[i]).Replace("" - , outPath + differenceImagePrefix + iText.IO.Util.JavaUtil.IntegerToString( - i + 1) + ".png"); - if (RunProcessAndWait(compareExec, currCompareParams)) - { - differentPagesFail += "\nPlease, examine " + outPath + differenceImagePrefix + iText.IO.Util.JavaUtil.IntegerToString - (i + 1) + ".png for more details."; - } - } - System.Console.Out.WriteLine(differentPagesFail); - } - else - { - System.Console.Out.WriteLine(" done."); - } - } - if (differentPagesFail != null) - { - String errorMessage = differentPages.Replace("", outPdf).Replace("" - , diffPages.ToString()); - if (!compareExecIsOk) - { - errorMessage += "\nYou can optionally specify path to ImageMagick compare tool (e.g. -DcompareExec=\"C:/Program Files/ImageMagick-6.5.4-2/compare.exe\") to visualize differences."; - } - return errorMessage; - } - else - { - if (bUnexpectedNumberOfPages) - { - return unexpectedNumberOfPages.Replace("", outPdf); - } - } - return null; - } - - /// - private void CreateIgnoredAreasPdfs(String outPath, IDictionary> ignoredAreas) - { - PdfWriter outWriter = new PdfWriter(new FileStream(outPath + ignoredAreasPrefix + - outPdfName, FileMode.Create)); - PdfWriter cmpWriter = new PdfWriter(new FileStream(outPath + ignoredAreasPrefix + - cmpPdfName, FileMode.Create)); - PdfDocument pdfOutDoc = new PdfDocument(new PdfReader(outPdf), outWriter); - PdfDocument pdfCmpDoc = new PdfDocument(new PdfReader(cmpPdf), cmpWriter); - foreach (KeyValuePair> entry in ignoredAreas) - { - int pageNumber = (int) entry.Key; - IList rectangles = entry.Value; - if (rectangles != null && rectangles.Count > 0) - { - //drawing rectangles manually, because we don't want to create dependency on itextpdf.canvas module for itextpdf.kernel - PdfStream outStream = GetPageContentStream(pdfOutDoc.GetPage(pageNumber)); - PdfStream cmpStream = GetPageContentStream(pdfCmpDoc.GetPage(pageNumber)); - outStream.GetOutputStream().WriteBytes(ByteUtils.GetIsoBytes("q\n")); - outStream.GetOutputStream().WriteFloats(new float[] { 0.0f, 0.0f, 0.0f }).WriteSpace - ().WriteBytes(ByteUtils.GetIsoBytes("rg\n")); - cmpStream.GetOutputStream().WriteBytes(ByteUtils.GetIsoBytes("q\n")); - cmpStream.GetOutputStream().WriteFloats(new float[] { 0.0f, 0.0f, 0.0f }).WriteSpace - ().WriteBytes(ByteUtils.GetIsoBytes("rg\n")); - foreach (Rectangle rect in rectangles) - { - outStream.GetOutputStream().WriteFloats(new float[] { rect.GetX(), rect.GetY(), rect - .GetWidth(), rect.GetHeight() }).WriteSpace().WriteBytes(ByteUtils.GetIsoBytes("re\n" - )).WriteBytes(ByteUtils.GetIsoBytes("f\n")); - cmpStream.GetOutputStream().WriteFloats(new float[] { rect.GetX(), rect.GetY(), rect - .GetWidth(), rect.GetHeight() }).WriteSpace().WriteBytes(ByteUtils.GetIsoBytes("re\n" - )).WriteBytes(ByteUtils.GetIsoBytes("f\n")); - } - outStream.GetOutputStream().WriteBytes(ByteUtils.GetIsoBytes("Q\n")); - cmpStream.GetOutputStream().WriteBytes(ByteUtils.GetIsoBytes("Q\n")); - } - } - pdfOutDoc.Close(); - pdfCmpDoc.Close(); - Init(outPath + ignoredAreasPrefix + outPdfName, outPath + ignoredAreasPrefix + cmpPdfName - ); - } - - private PdfStream GetPageContentStream(PdfPage page) - { - PdfStream stream = page.GetContentStream(page.GetContentStreamCount() - 1); - return stream.GetOutputStream() == null ? page.NewContentStreamAfter() : stream; - } - - private void PrepareOutputDirs(String outPath, String differenceImagePrefix) - { - String[] imageFiles; - String[] cmpImageFiles; - String[] diffFiles; - if (FileUtil.DirectoryExists(outPath)) { - Directory.CreateDirectory(outPath); - } - else - { - imageFiles = FileUtil.ListFilesInDirectoryByFilter(outPath, false, new CompareTool.PngFileFilter(this)); - foreach (String file in imageFiles) - { - File.Delete(file); - } - cmpImageFiles = FileUtil.ListFilesInDirectoryByFilter(outPath, false, new CompareTool.CmpPngFileFilter(this)); - foreach (String file in cmpImageFiles) - { - File.Delete(file); - } - diffFiles = FileUtil.ListFilesInDirectoryByFilter(outPath, false, new CompareTool.DiffPngFileFilter(this, differenceImagePrefix - )); - foreach (String file in diffFiles) - { - File.Delete(file); - } - } - } - - /// Runs ghostscript to create images of pdfs. - /// Path to the output folder. - /// Returns null if result is successful, else returns error message. - /// - /// - private String RunGhostScriptImageGeneration(String outPath) - { - if (!FileUtil.DirectoryExists(outPath)) - { - return cannotOpenOutputDirectory.Replace("", outPdf); - } - String currGsParams = gsParams.Replace("", outPath + cmpImage).Replace - ("", cmpPdf); - if (!RunProcessAndWait(gsExec, currGsParams)) - { - return gsFailed.Replace("", cmpPdf); - } - currGsParams = gsParams.Replace("", outPath + outImage).Replace("" - , outPdf); - if (!RunProcessAndWait(gsExec, currGsParams)) - { - return gsFailed.Replace("", outPdf); - } - return null; - } - - /// - /// - private bool RunProcessAndWait(String execPath, String @params) - { - StringTokenizer st = new StringTokenizer(@params); - String[] cmdArray = new String[st.CountTokens() + 1]; - cmdArray[0] = execPath; - for (int i = 1; st.HasMoreTokens(); ++i) - { - cmdArray[i] = st.NextToken(); - } - Process p = new Process(); - p.StartInfo = new ProcessStartInfo(execPath, @params); - p.StartInfo.RedirectStandardOutput = true; - p.StartInfo.RedirectStandardError = true; - p.StartInfo.UseShellExecute = false; - p.StartInfo.CreateNoWindow = true; - p.Start(); - - PrintProcessOutput(p); - p.WaitForExit(); - return true; - } - - /// - private void PrintProcessOutput(Process p) { - StringBuilder bri = new StringBuilder(); - StringBuilder bre = new StringBuilder(); - while (!p.HasExited) { - bri.Append(p.StandardOutput.ReadToEnd()); - bre.Append(p.StandardError.ReadToEnd()); - } - System.Console.Out.WriteLine(bri.ToString()); - System.Console.Out.WriteLine(bre.ToString()); - } - - /// - /// - private String CompareByContent(String outPath, String differenceImagePrefix, IDictionary - > ignoredAreas) - { - return CompareByContent(outPath, differenceImagePrefix, ignoredAreas, null, null); - } - - /// - /// - private String CompareByContent(String outPath, String differenceImagePrefix, IDictionary - > ignoredAreas, byte[] outPass, byte[] cmpPass) - { - System.Console.Out.Write("[itext] INFO Comparing by content.........."); - PdfDocument outDocument; - try - { - outDocument = new PdfDocument(new PdfReader(outPdf, new ReaderProperties().SetPassword - (outPass))); - } - catch (System.IO.IOException e) - { - throw new System.IO.IOException("File \"" + outPdf + "\" not found", e); - } - IList outPages = new List(); - outPagesRef = new List(); - LoadPagesFromReader(outDocument, outPages, outPagesRef); - PdfDocument cmpDocument; - try - { - cmpDocument = new PdfDocument(new PdfReader(cmpPdf, new ReaderProperties().SetPassword - (cmpPass))); - } - catch (System.IO.IOException e) - { - throw new System.IO.IOException("File \"" + cmpPdf + "\" not found", e); - } - IList cmpPages = new List(); - cmpPagesRef = new List(); - LoadPagesFromReader(cmpDocument, cmpPages, cmpPagesRef); - if (outPages.Count != cmpPages.Count) - { - return CompareVisually(outPath, differenceImagePrefix, ignoredAreas); - } - CompareTool.CompareResult compareResult = new CompareTool.CompareResult(this, compareByContentErrorsLimit - ); - IList equalPages = new List(cmpPages.Count); - for (int i = 0; i < cmpPages.Count; i++) - { - CompareTool.ObjectPath currentPath = new CompareTool.ObjectPath(cmpPagesRef - [i], outPagesRef[i]); - if (CompareDictionariesExtended(outPages[i], cmpPages[i], currentPath, compareResult - )) - { - equalPages.Add(i); - } - } - CompareTool.ObjectPath catalogPath = new CompareTool.ObjectPath(cmpDocument - .GetCatalog().GetPdfObject().GetIndirectReference(), outDocument.GetCatalog().GetPdfObject - ().GetIndirectReference()); - ICollection ignoredCatalogEntries = new LinkedHashSet(iText.IO.Util.JavaUtil.ArraysAsList - (PdfName.Pages, PdfName.Metadata)); - CompareDictionariesExtended(outDocument.GetCatalog().GetPdfObject(), cmpDocument. - GetCatalog().GetPdfObject(), catalogPath, compareResult, ignoredCatalogEntries); - if (encryptionCompareEnabled) - { - CompareDocumentsEncryption(outDocument, cmpDocument, compareResult); - } - outDocument.Close(); - cmpDocument.Close(); - if (generateCompareByContentXmlReport) - { - try - { - String filename = Path.GetFileName(outPdf); - FileStream xml = new FileStream(outPath + "/" + filename.Substring(0, filename.Length - 3) + "report.xml", - FileMode.Create - ); - compareResult.WriteReportToXml(xml); + outImage = outPdfName + "-%03d.png"; + if (cmpPdfName.StartsWith("cmp_")) { + cmpImage = cmpPdfName + "-%03d.png"; + } + else { + cmpImage = "cmp_" + cmpPdfName + "-%03d.png"; + } + } + + private void SetPassword(byte[] outPass, byte[] cmpPass) { + if (outPass != null) { + GetOutReaderProperties().SetPassword(outPass); + } + if (cmpPass != null) { + GetCmpReaderProperties().SetPassword(outPass); + } + } + + /// + /// + private String CompareVisually(String outPath, String differenceImagePrefix, IDictionary> ignoredAreas) { + return CompareVisually(outPath, differenceImagePrefix, ignoredAreas, null); + } + + /// + /// + private String CompareVisually(String outPath, String differenceImagePrefix, IDictionary> ignoredAreas, IList equalPages) { + if (gsExec == null) { + return undefinedGsPath; + } + if (!(new FileInfo(gsExec).Exists)) { + return new FileInfo(gsExec).FullName + " does not exist"; + } + if (!outPath.EndsWith("/")) { + outPath = outPath + "/"; + } + PrepareOutputDirs(outPath, differenceImagePrefix); + if (ignoredAreas != null && !ignoredAreas.IsEmpty()) { + CreateIgnoredAreasPdfs(outPath, ignoredAreas); + } + String imagesGenerationResult = RunGhostScriptImageGeneration(outPath); + if (imagesGenerationResult != null) { + return imagesGenerationResult; + } + return CompareImagesOfPdfs(outPath, differenceImagePrefix, equalPages); + } + + /// + /// + private String CompareImagesOfPdfs(String outPath, String differenceImagePrefix, IList equalPages) { + FileInfo[] imageFiles = FileUtil.ListFilesInDirectoryByFilter(outPath, new CompareTool.PngFileFilter(this) + ); + FileInfo[] cmpImageFiles = FileUtil.ListFilesInDirectoryByFilter(outPath, new CompareTool.CmpPngFileFilter + (this)); + bool bUnexpectedNumberOfPages = false; + if (imageFiles.Length != cmpImageFiles.Length) { + bUnexpectedNumberOfPages = true; + } + int cnt = Math.Min(imageFiles.Length, cmpImageFiles.Length); + if (cnt < 1) { + return "No files for comparing.\nThe result or sample pdf file is not processed by GhostScript."; + } + iText.IO.Util.JavaUtil.Sort(imageFiles, new CompareTool.ImageNameComparator(this)); + iText.IO.Util.JavaUtil.Sort(cmpImageFiles, new CompareTool.ImageNameComparator(this)); + String differentPagesFail = null; + bool compareExecIsOk = compareExec != null && new FileInfo(compareExec).Exists; + IList diffPages = new List(); + for (int i = 0; i < cnt; i++) { + if (equalPages != null && equalPages.Contains(i)) { + continue; + } + System.Console.Out.Write("Comparing page " + iText.IO.Util.JavaUtil.IntegerToString(i + 1) + " (" + imageFiles + [i].FullName + ")..."); + FileStream is1 = new FileStream(imageFiles[i].FullName, FileMode.Open, FileAccess.Read); + FileStream is2 = new FileStream(cmpImageFiles[i].FullName, FileMode.Open, FileAccess.Read); + bool cmpResult = CompareStreams(is1, is2); + is1.Close(); + is2.Close(); + if (!cmpResult) { + differentPagesFail = " Page is different!"; + diffPages.Add(i + 1); + if (compareExecIsOk) { + String currCompareParams = compareParams.Replace("", imageFiles[i].FullName).Replace("", cmpImageFiles + [i].FullName).Replace("", outPath + differenceImagePrefix + iText.IO.Util.JavaUtil.IntegerToString + (i + 1) + ".png"); + if (SystemUtil.RunProcessAndWait(compareExec, currCompareParams)) { + differentPagesFail += "\nPlease, examine " + outPath + differenceImagePrefix + iText.IO.Util.JavaUtil.IntegerToString + (i + 1) + ".png for more details."; + } + } + System.Console.Out.WriteLine(differentPagesFail); + } + else { + System.Console.Out.WriteLine(" done."); + } + } + if (differentPagesFail != null) { + String errorMessage = differentPages.Replace("", outPdf).Replace("", ListDiffPagesAsString + (diffPages)); + if (!compareExecIsOk) { + errorMessage += "\nYou can optionally specify path to ImageMagick compare tool (e.g. -DcompareExec=\"C:/Program Files/ImageMagick-6.5.4-2/compare.exe\") to visualize differences."; + } + return errorMessage; + } + else { + if (bUnexpectedNumberOfPages) { + return unexpectedNumberOfPages.Replace("", outPdf); + } + } + return null; + } + + private String ListDiffPagesAsString(IList diffPages) { + StringBuilder sb = new StringBuilder("["); + for (int i = 0; i < diffPages.Count; i++) { + sb.Append(diffPages[i]); + if (i < diffPages.Count - 1) { + sb.Append(", "); + } + } + sb.Append("]"); + return sb.ToString(); + } + + /// + private void CreateIgnoredAreasPdfs(String outPath, IDictionary> ignoredAreas) { + PdfWriter outWriter = new PdfWriter(outPath + ignoredAreasPrefix + outPdfName); + PdfWriter cmpWriter = new PdfWriter(outPath + ignoredAreasPrefix + cmpPdfName); + PdfDocument pdfOutDoc = new PdfDocument(new PdfReader(outPdf), outWriter); + PdfDocument pdfCmpDoc = new PdfDocument(new PdfReader(cmpPdf), cmpWriter); + foreach (KeyValuePair> entry in ignoredAreas) { + int pageNumber = entry.Key; + IList rectangles = entry.Value; + if (rectangles != null && !rectangles.IsEmpty()) { + PdfCanvas outCanvas = new PdfCanvas(pdfOutDoc.GetPage(pageNumber)); + PdfCanvas cmpCanvas = new PdfCanvas(pdfCmpDoc.GetPage(pageNumber)); + outCanvas.SaveState(); + cmpCanvas.SaveState(); + foreach (Rectangle rect in rectangles) { + outCanvas.Rectangle(rect).Fill(); + cmpCanvas.Rectangle(rect).Fill(); + } + outCanvas.RestoreState(); + cmpCanvas.RestoreState(); + } + } + pdfOutDoc.Close(); + pdfCmpDoc.Close(); + Init(outPath + ignoredAreasPrefix + outPdfName, outPath + ignoredAreasPrefix + cmpPdfName); + } + + private void PrepareOutputDirs(String outPath, String differenceImagePrefix) { + FileInfo[] imageFiles; + FileInfo[] cmpImageFiles; + FileInfo[] diffFiles; + if (!FileUtil.DirectoryExists(outPath)) { + FileUtil.CreateDirectories(outPath); + } + else { + imageFiles = FileUtil.ListFilesInDirectoryByFilter(outPath, new CompareTool.PngFileFilter(this)); + foreach (FileInfo file in imageFiles) { + file.Delete(); + } + cmpImageFiles = FileUtil.ListFilesInDirectoryByFilter(outPath, new CompareTool.CmpPngFileFilter(this)); + foreach (FileInfo file_1 in cmpImageFiles) { + file_1.Delete(); + } + diffFiles = FileUtil.ListFilesInDirectoryByFilter(outPath, new CompareTool.DiffPngFileFilter(this, differenceImagePrefix + )); + foreach (FileInfo file_2 in diffFiles) { + file_2.Delete(); + } + } + } + + /// Runs ghostscript to create images of pdfs. + /// Path to the output folder. + /// Returns null if result is successful, else returns error message. + /// + /// + private String RunGhostScriptImageGeneration(String outPath) { + if (!FileUtil.DirectoryExists(outPath)) { + return cannotOpenOutputDirectory.Replace("", outPdf); + } + String currGsParams = gsParams.Replace("", outPath + cmpImage).Replace("", cmpPdf); + if (!SystemUtil.RunProcessAndWait(gsExec, currGsParams)) { + return gsFailed.Replace("", cmpPdf); + } + currGsParams = gsParams.Replace("", outPath + outImage).Replace("", outPdf); + if (!SystemUtil.RunProcessAndWait(gsExec, currGsParams)) { + return gsFailed.Replace("", outPdf); + } + return null; + } + + /// + /// + private String CompareByContent(String outPath, String differenceImagePrefix, IDictionary> ignoredAreas) { + System.Console.Out.Write("[itext] INFO Comparing by content.........."); + PdfDocument outDocument; + try { + outDocument = new PdfDocument(new PdfReader(outPdf, GetOutReaderProperties())); + } + catch (System.IO.IOException e) { + throw new System.IO.IOException("File \"" + outPdf + "\" not found", e); + } + IList outPages = new List(); + outPagesRef = new List(); + LoadPagesFromReader(outDocument, outPages, outPagesRef); + PdfDocument cmpDocument; + try { + cmpDocument = new PdfDocument(new PdfReader(cmpPdf, GetCmpReaderProperties())); + } + catch (System.IO.IOException e) { + throw new System.IO.IOException("File \"" + cmpPdf + "\" not found", e); + } + IList cmpPages = new List(); + cmpPagesRef = new List(); + LoadPagesFromReader(cmpDocument, cmpPages, cmpPagesRef); + if (outPages.Count != cmpPages.Count) { + return CompareVisually(outPath, differenceImagePrefix, ignoredAreas); + } + CompareTool.CompareResult compareResult = new CompareTool.CompareResult(this, compareByContentErrorsLimit); + IList equalPages = new List(cmpPages.Count); + for (int i = 0; i < cmpPages.Count; i++) { + CompareTool.ObjectPath currentPath = new CompareTool.ObjectPath(cmpPagesRef[i], outPagesRef[i]); + if (CompareDictionariesExtended(outPages[i], cmpPages[i], currentPath, compareResult)) { + equalPages.Add(i); + } + } + CompareTool.ObjectPath catalogPath = new CompareTool.ObjectPath(cmpDocument.GetCatalog().GetPdfObject().GetIndirectReference + (), outDocument.GetCatalog().GetPdfObject().GetIndirectReference()); + ICollection ignoredCatalogEntries = new LinkedHashSet(iText.IO.Util.JavaUtil.ArraysAsList + (PdfName.Pages, PdfName.Metadata)); + CompareDictionariesExtended(outDocument.GetCatalog().GetPdfObject(), cmpDocument.GetCatalog().GetPdfObject + (), catalogPath, compareResult, ignoredCatalogEntries); + if (encryptionCompareEnabled) { + CompareDocumentsEncryption(outDocument, cmpDocument, compareResult); + } + outDocument.Close(); + cmpDocument.Close(); + if (generateCompareByContentXmlReport) { + String outPdfName = new FileInfo(outPdf).Name; + FileStream xml = new FileStream(outPath + "/" + outPdfName.JSubstring(0, outPdfName.Length - 3) + "report.xml" + , FileMode.Create); + try { + compareResult.WriteReportToXml(xml); + } + catch (Exception e) { + throw new Exception(e.Message, e); + } + finally { xml.Close(); - } - catch (Exception) - { - } - } - if (equalPages.Count == cmpPages.Count && compareResult.IsOk()) - { - System.Console.Out.WriteLine("OK"); - System.Console.Out.Flush(); - return null; - } - else - { - System.Console.Out.WriteLine("Fail"); - System.Console.Out.Flush(); - String compareByContentReport = "Compare by content report:\n" + compareResult.GetReport - (); - System.Console.Out.WriteLine(compareByContentReport); - System.Console.Out.Flush(); - String message = CompareVisually(outPath, differenceImagePrefix, ignoredAreas, equalPages - ); - if (message == null || message.Length == 0) - { - return "Compare by content fails. No visual differences"; - } - return message; - } - } - - private void LoadPagesFromReader(PdfDocument doc, IList pages, IList - pagesRef) - { - int numOfPages = doc.GetNumberOfPages(); - for (int i = 0; i < numOfPages; ++i) - { - pages.Add(doc.GetPage(i + 1).GetPdfObject()); - pagesRef.Add(pages[i].GetIndirectReference()); - } - } - - /// - private void CompareDocumentsEncryption(PdfDocument outDocument, PdfDocument cmpDocument - , CompareTool.CompareResult compareResult) - { - PdfDictionary outEncrypt = outDocument.GetTrailer().GetAsDictionary(PdfName.Encrypt - ); - PdfDictionary cmpEncrypt = cmpDocument.GetTrailer().GetAsDictionary(PdfName.Encrypt - ); - if (outEncrypt == null && cmpEncrypt == null) - { - return; - } - CompareTool.TrailerPath trailerPath = new CompareTool.TrailerPath(cmpDocument - , outDocument); - if (outEncrypt == null) - { - compareResult.AddError(trailerPath, "Expected encrypted document."); - return; - } - if (cmpEncrypt == null) - { - compareResult.AddError(trailerPath, "Expected not encrypted document."); - return; - } - ICollection ignoredEncryptEntries = new LinkedHashSet(iText.IO.Util.JavaUtil.ArraysAsList - (PdfName.O, PdfName.U, PdfName.OE, PdfName.UE, PdfName.Perms)); - CompareTool.ObjectPath objectPath = new CompareTool.ObjectPath(outEncrypt.GetIndirectReference - (), cmpEncrypt.GetIndirectReference()); - CompareDictionariesExtended(outEncrypt, cmpEncrypt, objectPath, compareResult, ignoredEncryptEntries - ); - } - - /// - private bool CompareStreams(Stream is1, Stream is2) - { - byte[] buffer1 = new byte[64 * 1024]; - byte[] buffer2 = new byte[64 * 1024]; - int len1; - int len2; - for (; ; ) - { - len1 = is1.Read(buffer1); - len2 = is2.Read(buffer2); - if (len1 != len2) - { - return false; - } - if (!iText.IO.Util.JavaUtil.ArraysEquals(buffer1, buffer2)) - { - return false; - } - if (len1 == -1) - { - break; - } - } - return true; - } - - /// - private bool CompareDictionariesExtended(PdfDictionary outDict, PdfDictionary cmpDict - , CompareTool.ObjectPath currentPath, CompareTool.CompareResult compareResult) - { - return CompareDictionariesExtended(outDict, cmpDict, currentPath, compareResult, - null); - } - - /// - private bool CompareDictionariesExtended(PdfDictionary outDict, PdfDictionary cmpDict - , CompareTool.ObjectPath currentPath, CompareTool.CompareResult compareResult, ICollection - excludedKeys) - { - if (cmpDict != null && outDict == null || outDict != null && cmpDict == null) - { - compareResult.AddError(currentPath, "One of the dictionaries is null, the other is not." - ); - return false; - } - bool dictsAreSame = true; - // Iterate through the union of the keys of the cmp and out dictionaries - ICollection mergedKeys = new SortedSet(cmpDict.KeySet()); - mergedKeys.AddAll(outDict.KeySet()); - foreach (PdfName key in mergedKeys) - { - if (excludedKeys != null && excludedKeys.Contains(key)) - { - continue; - } - if (key.Equals(PdfName.Parent) || key.Equals(PdfName.P) || key.Equals(PdfName.ModDate - )) - { - continue; - } - if (outDict.IsStream() && cmpDict.IsStream() && (key.Equals(PdfName.Filter) || key - .Equals(PdfName.Length))) - { - continue; - } - if (key.Equals(PdfName.BaseFont) || key.Equals(PdfName.FontName)) - { - PdfObject cmpObj = cmpDict.Get(key); - if (cmpObj.IsName() && cmpObj.ToString().IndexOf('+') > 0) - { - PdfObject outObj = outDict.Get(key); - if (!outObj.IsName() || outObj.ToString().IndexOf('+') == -1) - { - if (compareResult != null && currentPath != null) - { - compareResult.AddError(currentPath, String.Format("PdfDictionary {0} entry: Expected: {1}. Found: {2}" - , key.ToString(), cmpObj.ToString(), outObj.ToString())); - } - dictsAreSame = false; - } - else - { - String cmpName = cmpObj.ToString().Substring(cmpObj.ToString().IndexOf('+')); - String outName = outObj.ToString().Substring(outObj.ToString().IndexOf('+')); - if (!cmpName.Equals(outName)) - { - if (compareResult != null && currentPath != null) - { - compareResult.AddError(currentPath, String.Format("PdfDictionary {0} entry: Expected: {1}. Found: {2}" - , key.ToString(), cmpObj.ToString(), outObj.ToString())); - } - dictsAreSame = false; - } - } - continue; - } - } - if (currentPath != null) - { - currentPath.PushDictItemToPath(key); - } - dictsAreSame = CompareObjects(outDict.Get(key, false), cmpDict.Get(key, false), currentPath - , compareResult) && dictsAreSame; - if (currentPath != null) - { - currentPath.Pop(); - } - if (!dictsAreSame && (currentPath == null || compareResult == null || compareResult - .IsMessageLimitReached())) - { - return false; - } - } - return dictsAreSame; - } - - /// - private bool CompareObjects(PdfObject outObj, PdfObject cmpObj, CompareTool.ObjectPath - currentPath, CompareTool.CompareResult compareResult) - { - PdfObject outDirectObj = null; - PdfObject cmpDirectObj = null; - if (outObj != null) - { - outDirectObj = outObj.IsIndirectReference() ? ((PdfIndirectReference)outObj).GetRefersTo - (false) : outObj; - } - if (cmpObj != null) - { - cmpDirectObj = cmpObj.IsIndirectReference() ? ((PdfIndirectReference)cmpObj).GetRefersTo - (false) : cmpObj; - } - if (cmpDirectObj == null && outDirectObj == null) - { - return true; - } - if (outDirectObj == null) - { - compareResult.AddError(currentPath, "Expected object was not found."); - return false; - } - else - { - if (cmpDirectObj == null) - { - compareResult.AddError(currentPath, "Found object which was not expected to be found." - ); - return false; - } - else - { - if (cmpDirectObj.GetObjectType() != outDirectObj.GetObjectType()) - { - compareResult.AddError(currentPath, String.Format("Types do not match. Expected: {0}. Found: {1}." - , cmpDirectObj.GetType().Name, outDirectObj.GetType().Name - )); - return false; - } - else - { - if (cmpObj.IsIndirectReference() && !outObj.IsIndirectReference()) - { - compareResult.AddError(currentPath, "Expected indirect object."); - return false; - } - else - { - if (!cmpObj.IsIndirectReference() && outObj.IsIndirectReference()) - { - compareResult.AddError(currentPath, "Expected direct object."); - return false; - } - } - } - } - } - if (currentPath != null && cmpObj.IsIndirectReference() && outObj.IsIndirectReference - ()) - { - if (currentPath.IsComparing((PdfIndirectReference)cmpObj, (PdfIndirectReference)outObj - )) - { - return true; - } - currentPath = currentPath.ResetDirectPath((PdfIndirectReference)cmpObj, (PdfIndirectReference - )outObj); - } - if (cmpDirectObj.IsDictionary() && PdfName.Page.Equals(((PdfDictionary)cmpDirectObj - ).GetAsName(PdfName.Type)) && useCachedPagesForComparison) - { - if (!outDirectObj.IsDictionary() || !PdfName.Page.Equals(((PdfDictionary)outDirectObj - ).GetAsName(PdfName.Type))) - { - if (compareResult != null && currentPath != null) - { - compareResult.AddError(currentPath, "Expected a page. Found not a page."); - } - return false; - } - PdfIndirectReference cmpRefKey = cmpObj.IsIndirectReference() ? (PdfIndirectReference - )cmpObj : cmpObj.GetIndirectReference(); - PdfIndirectReference outRefKey = outObj.IsIndirectReference() ? (PdfIndirectReference - )outObj : outObj.GetIndirectReference(); - // References to the same page - if (cmpPagesRef == null) - { - cmpPagesRef = new List(); - for (int i = 1; i <= cmpObj.GetIndirectReference().GetDocument().GetNumberOfPages - (); ++i) - { - cmpPagesRef.Add(cmpObj.GetIndirectReference().GetDocument().GetPage(i).GetPdfObject - ().GetIndirectReference()); - } - } - if (outPagesRef == null) - { - outPagesRef = new List(); - for (int i = 1; i <= outObj.GetIndirectReference().GetDocument().GetNumberOfPages - (); ++i) - { - outPagesRef.Add(outObj.GetIndirectReference().GetDocument().GetPage(i).GetPdfObject - ().GetIndirectReference()); - } - } - if (cmpPagesRef.Contains(cmpRefKey) && cmpPagesRef.IndexOf(cmpRefKey) == outPagesRef - .IndexOf(outRefKey)) - { - return true; - } - if (compareResult != null && currentPath != null) - { - compareResult.AddError(currentPath, String.Format("The dictionaries refer to different pages. Expected page number: {0}. Found: {1}" - , cmpPagesRef.IndexOf(cmpRefKey), outPagesRef.IndexOf(outRefKey))); - } - return false; - } - if (cmpDirectObj.IsDictionary()) - { - if (!CompareDictionariesExtended((PdfDictionary)outDirectObj, (PdfDictionary)cmpDirectObj - , currentPath, compareResult)) - { - return false; - } - } - else - { - if (cmpDirectObj.IsStream()) - { - if (!CompareStreamsExtended((PdfStream)outDirectObj, (PdfStream)cmpDirectObj, currentPath - , compareResult)) - { - return false; - } - } - else - { - if (cmpDirectObj.IsArray()) - { - if (!CompareArraysExtended((PdfArray)outDirectObj, (PdfArray)cmpDirectObj, currentPath - , compareResult)) - { - return false; - } - } - else - { - if (cmpDirectObj.IsName()) - { - if (!CompareNamesExtended((PdfName)outDirectObj, (PdfName)cmpDirectObj, currentPath - , compareResult)) - { - return false; - } - } - else - { - if (cmpDirectObj.IsNumber()) - { - if (!CompareNumbersExtended((PdfNumber)outDirectObj, (PdfNumber)cmpDirectObj, currentPath - , compareResult)) - { - return false; - } - } - else - { - if (cmpDirectObj.IsString()) - { - if (!CompareStringsExtended((PdfString)outDirectObj, (PdfString)cmpDirectObj, currentPath - , compareResult)) - { - return false; - } - } - else - { - if (cmpDirectObj.IsBoolean()) - { - if (!CompareBooleansExtended((PdfBoolean)outDirectObj, (PdfBoolean)cmpDirectObj, - currentPath, compareResult)) - { - return false; - } - } - else - { - if (outDirectObj.IsNull() && cmpDirectObj.IsNull()) - { - } - else - { - throw new NotSupportedException(); - } - } - } - } - } - } - } - } - return true; - } - - /// - private bool CompareStreamsExtended(PdfStream outStream, PdfStream cmpStream, CompareTool.ObjectPath - currentPath, CompareTool.CompareResult compareResult) - { - bool toDecode = PdfName.FlateDecode.Equals(outStream.Get(PdfName.Filter)); - byte[] outStreamBytes = outStream.GetBytes(toDecode); - byte[] cmpStreamBytes = cmpStream.GetBytes(toDecode); - if (iText.IO.Util.JavaUtil.ArraysEquals(outStreamBytes, cmpStreamBytes)) - { - return CompareDictionariesExtended(outStream, cmpStream, currentPath, compareResult - ); - } - else - { - String errorMessage = ""; - if (cmpStreamBytes.Length != outStreamBytes.Length) - { - errorMessage += String.Format("PdfStream. Lengths are different. Expected: {0}. Found: {1}" - , cmpStreamBytes.Length, outStreamBytes.Length) + "\n"; - } - else - { - errorMessage += "PdfStream. Bytes are different.\n"; - } - String bytesDifference = FindBytesDifference(outStreamBytes, cmpStreamBytes); - if (bytesDifference != null) - { - errorMessage += bytesDifference; - } - if (compareResult != null && currentPath != null) - { - // currentPath.pushOffsetToPath(firstDifferenceOffset); - compareResult.AddError(currentPath, errorMessage); - } - // currentPath.pop(); - return false; - } - } - - private String FindBytesDifference(byte[] outStreamBytes, byte[] cmpStreamBytes) - { - int numberOfDifferentBytes = 0; - int firstDifferenceOffset = 0; - int minLength = Math.Min(cmpStreamBytes.Length, outStreamBytes.Length); - for (int i = 0; i < minLength; i++) - { - if (cmpStreamBytes[i] != outStreamBytes[i]) - { - ++numberOfDifferentBytes; - if (numberOfDifferentBytes == 1) - { - firstDifferenceOffset = i; - } - } - } - String errorMessage = null; - if (numberOfDifferentBytes > 0) - { - int diffBytesAreaL = 10; - int diffBytesAreaR = 10; - int lCmp = Math.Max(0, firstDifferenceOffset - diffBytesAreaL); - int rCmp = Math.Min(cmpStreamBytes.Length, firstDifferenceOffset + diffBytesAreaR - ); - int lOut = Math.Max(0, firstDifferenceOffset - diffBytesAreaL); - int rOut = Math.Min(outStreamBytes.Length, firstDifferenceOffset + diffBytesAreaR - ); - String cmpByte = iText.IO.Util.JavaUtil.GetStringForBytes(new byte[] { cmpStreamBytes - [firstDifferenceOffset] }); - String cmpByteNeighbours = iText.IO.Util.StringUtil.ReplaceAll(iText.IO.Util.JavaUtil.GetStringForBytes - (cmpStreamBytes, lCmp, rCmp - lCmp), "\\r|\\n", " "); - String outByte = iText.IO.Util.JavaUtil.GetStringForBytes(new byte[] { outStreamBytes - [firstDifferenceOffset] }); - String outBytesNeighbours = iText.IO.Util.StringUtil.ReplaceAll(iText.IO.Util.JavaUtil.GetStringForBytes - (outStreamBytes, lOut, rOut - lOut), "\\r|\\n", " "); - errorMessage = String.Format("First bytes difference is encountered at index {0}. Expected: {1} ({2}). Found: {3} ({4}). Total number of different bytes: {5}" - , System.Convert.ToInt32(firstDifferenceOffset).ToString(), cmpByte, cmpByteNeighbours - , outByte, outBytesNeighbours, numberOfDifferentBytes); - } - else - { - // lengths are different - errorMessage = String.Format("Bytes of the shorter array are the same as the first {0} bytes of the longer one." - , minLength); - } - return errorMessage; - } - - /// - private bool CompareArraysExtended(PdfArray outArray, PdfArray cmpArray, CompareTool.ObjectPath - currentPath, CompareTool.CompareResult compareResult) - { - if (outArray == null) - { - if (compareResult != null && currentPath != null) - { - compareResult.AddError(currentPath, "Found null. Expected PdfArray."); - } - return false; - } - else - { - if (outArray.Size() != cmpArray.Size()) - { - if (compareResult != null && currentPath != null) - { - compareResult.AddError(currentPath, String.Format("PdfArrays. Lengths are different. Expected: {0}. Found: {1}." - , cmpArray.Size(), outArray.Size())); - } - return false; - } - } - bool arraysAreEqual = true; - for (int i = 0; i < cmpArray.Size(); i++) - { - if (currentPath != null) - { - currentPath.PushArrayItemToPath(i); - } - arraysAreEqual = CompareObjects(outArray.Get(i, false), cmpArray.Get(i, false), currentPath - , compareResult) && arraysAreEqual; - if (currentPath != null) - { - currentPath.Pop(); - } - if (!arraysAreEqual && (currentPath == null || compareResult == null || compareResult - .IsMessageLimitReached())) - { - return false; - } - } - return arraysAreEqual; - } - - private bool CompareNamesExtended(PdfName outName, PdfName cmpName, CompareTool.ObjectPath - currentPath, CompareTool.CompareResult compareResult) - { - if (cmpName.Equals(outName)) - { - return true; - } - else - { - if (compareResult != null && currentPath != null) - { - compareResult.AddError(currentPath, String.Format("PdfName. Expected: {0}. Found: {1}" - , cmpName.ToString(), outName.ToString())); - } - return false; - } - } - - private bool CompareNumbersExtended(PdfNumber outNumber, PdfNumber cmpNumber, CompareTool.ObjectPath - currentPath, CompareTool.CompareResult compareResult) - { - if (0 == cmpNumber.GetValue().CompareTo(outNumber.GetValue())) - { - return true; - } - else - { - if (compareResult != null && currentPath != null) - { - compareResult.AddError(currentPath, String.Format("PdfNumber. Expected: {0}. Found: {1}" - , cmpNumber, outNumber)); - } - return false; - } - } - - private bool CompareStringsExtended(PdfString outString, PdfString cmpString, CompareTool.ObjectPath - currentPath, CompareTool.CompareResult compareResult) - { - if (iText.IO.Util.JavaUtil.ArraysEquals(ConvertPdfStringToBytes(cmpString), - ConvertPdfStringToBytes(outString))) - { - return true; - } - else - { - String cmpStr = cmpString.ToUnicodeString(); - String outStr = outString.ToUnicodeString(); - if (cmpStr.Length != outStr.Length) - { - if (compareResult != null && currentPath != null) - { - compareResult.AddError(currentPath, String.Format("PdfString. Lengths are different. Expected: {0}. Found: {1}" - , cmpStr.Length, outStr.Length)); - } - } - else - { - for (int i = 0; i < cmpStr.Length; i++) - { - if (cmpStr[i] != outStr[i]) - { - int l = Math.Max(0, i - 10); - int r = Math.Min(cmpStr.Length, i + 10); - if (compareResult != null && currentPath != null) - { - currentPath.PushOffsetToPath(i); - compareResult.AddError(currentPath, String.Format("PdfString. Characters differ at position {0}. Expected: {1} ({2}). Found: {3} ({4})." - , i, char.ToString(cmpStr[i]), cmpStr.JSubstring(l, r).Replace("\n", "\\n"), char - .ToString(outStr[i]), outStr.JSubstring(l, r).Replace("\n", "\\n"))); - currentPath.Pop(); - } - break; - } - } - } - return false; - } - } - - private byte[] ConvertPdfStringToBytes(PdfString pdfString) - { - byte[] bytes; - String value = pdfString.GetValue(); - String encoding = pdfString.GetEncoding(); - if (encoding != null && encoding.Equals(PdfEncodings.UNICODE_BIG) && PdfEncodings - .IsPdfDocEncoding(value)) - { - bytes = PdfEncodings.ConvertToBytes(value, PdfEncodings.PDF_DOC_ENCODING); - } - else - { - bytes = PdfEncodings.ConvertToBytes(value, encoding); - } - return bytes; - } - - private bool CompareBooleansExtended(PdfBoolean outBoolean, PdfBoolean cmpBoolean - , CompareTool.ObjectPath currentPath, CompareTool.CompareResult compareResult) - { - if (cmpBoolean.GetValue() == outBoolean.GetValue()) - { - return true; - } - else - { - if (compareResult != null && currentPath != null) - { - compareResult.AddError(currentPath, String.Format("PdfBoolean. Expected: {0}. Found: {1}." - , cmpBoolean.GetValue(), outBoolean.GetValue())); - } - return false; - } - } - - /// - /// - /// - private bool CompareXmls(Stream xml1, Stream xml2) - { - XElement el1 = XElement.Load(xml1); - XElement el2 = XElement.Load(xml2); - - return XNode.DeepEquals(Normalize(el1), Normalize(el2)); - } - - private static XElement Normalize(XElement element) - { - if (element.HasElements) - { - return new XElement( - element.Name, - element.Attributes().Where(a => a.Name.Namespace == XNamespace.Xmlns) - .OrderBy(a => a.Name.ToString()), - element.Elements().OrderBy(a => a.Name.ToString()) - .Select(e => Normalize(e))); - } - - if (element.IsEmpty) - { - return new XElement(element.Name, element.Attributes() - .OrderBy(a => a.Name.ToString())); - } - - return new XElement(element.Name, element.Attributes() - .OrderBy(a => a.Name.ToString()), element.Value); - } - - private IList GetLinkAnnotations(int pageNum, PdfDocument document - ) - { - IList linkAnnotations = new List(); - IList annotations = document.GetPage(pageNum).GetAnnotations(); - foreach (PdfAnnotation annotation in annotations) - { - if (PdfName.Link.Equals(annotation.GetSubtype())) - { - linkAnnotations.Add((PdfLinkAnnotation)annotation); - } - } - return linkAnnotations; - } - - private bool CompareLinkAnnotations(PdfLinkAnnotation cmpLink, PdfLinkAnnotation - outLink, PdfDocument cmpDocument, PdfDocument outDocument) - { - // Compare link rectangles, page numbers the links refer to, and simple parameters (non-indirect, non-arrays, non-dictionaries) - PdfObject cmpDestObject = cmpLink.GetDestinationObject(); - PdfObject outDestObject = outLink.GetDestinationObject(); - if (cmpDestObject != null && outDestObject != null) - { - if (cmpDestObject.GetObjectType() != outDestObject.GetObjectType()) - { - return false; - } - else - { - PdfArray explicitCmpDest = null; - PdfArray explicitOutDest = null; - IDictionary cmpNamedDestinations = cmpDocument.GetCatalog().GetNameTree - (PdfName.Dests).GetNames(); - IDictionary outNamedDestinations = outDocument.GetCatalog().GetNameTree - (PdfName.Dests).GetNames(); - switch (cmpDestObject.GetObjectType()) - { - case PdfObject.ARRAY: - { - explicitCmpDest = (PdfArray)cmpDestObject; - explicitOutDest = (PdfArray)outDestObject; - break; - } - - case PdfObject.NAME: - { - explicitCmpDest = (PdfArray)cmpNamedDestinations[((PdfName)cmpDestObject).GetValue()]; - explicitOutDest = (PdfArray)outNamedDestinations[((PdfName)outDestObject).GetValue()]; - break; - } - - case PdfObject.STRING: - { - explicitCmpDest = (PdfArray)cmpNamedDestinations[((PdfString)cmpDestObject).ToUnicodeString - ()]; - explicitOutDest = (PdfArray)outNamedDestinations[((PdfString)outDestObject).ToUnicodeString - ()]; - break; - } - - default: - { - break; - } - } - if (GetExplicitDestinationPageNum(explicitCmpDest) != GetExplicitDestinationPageNum - (explicitOutDest)) - { - return false; - } - } - } - PdfDictionary cmpDict = cmpLink.GetPdfObject(); - PdfDictionary outDict = outLink.GetPdfObject(); - if (cmpDict.Size() != outDict.Size()) - { - return false; - } - Rectangle cmpRect = cmpDict.GetAsRectangle(PdfName.Rect); - Rectangle outRect = outDict.GetAsRectangle(PdfName.Rect); - if (cmpRect.GetHeight() != outRect.GetHeight() || cmpRect.GetWidth() != outRect.GetWidth - () || cmpRect.GetX() != outRect.GetX() || cmpRect.GetY() != outRect.GetY()) - { - return false; - } - foreach (KeyValuePair cmpEntry in cmpDict.EntrySet()) - { - PdfObject cmpObj = cmpEntry.Value; - if (!outDict.ContainsKey(cmpEntry.Key)) - { - return false; - } - PdfObject outObj = outDict.Get(cmpEntry.Key); - if (cmpObj.GetObjectType() != outObj.GetObjectType()) - { - return false; - } - switch (cmpObj.GetObjectType()) - { - case PdfObject.NULL: - case PdfObject.BOOLEAN: - case PdfObject.NUMBER: - case PdfObject.STRING: - case PdfObject.NAME: - { - if (!cmpObj.ToString().Equals(outObj.ToString())) - { - return false; - } - break; - } - } - } - return true; - } - - private int GetExplicitDestinationPageNum(PdfArray explicitDest) - { - PdfIndirectReference pageReference = (PdfIndirectReference)explicitDest.Get(0, false - ); - PdfDocument doc = pageReference.GetDocument(); - for (int i = 1; i <= doc.GetNumberOfPages(); ++i) - { - if (doc.GetPage(i).GetPdfObject().GetIndirectReference().Equals(pageReference)) - { - return i; - } - } - throw new ArgumentException("PdfLinkAnnotation comparison: Page not found."); - } - - private String[] ConvertInfo(PdfDocumentInfo info) - { - String[] convertedInfo = new String[] { "", "", "", "" }; - String infoValue = info.GetTitle(); - if (infoValue != null) - { - convertedInfo[0] = infoValue; - } - infoValue = info.GetAuthor(); - if (infoValue != null) - { - convertedInfo[1] = infoValue; - } - infoValue = info.GetSubject(); - if (infoValue != null) - { - convertedInfo[2] = infoValue; - } - infoValue = info.GetKeywords(); - if (infoValue != null) - { - convertedInfo[3] = infoValue; - } - return convertedInfo; - } - - private class PngFileFilter : FileUtil.FileFilter - { - public virtual bool Accept(String ap) { - bool b1 = ap.EndsWith(".png"); - bool b2 = ap.Contains("cmp_"); - return b1 && !b2 && ap.Contains(this._enclosing.outPdfName); - } - - internal PngFileFilter(CompareTool _enclosing) - { - this._enclosing = _enclosing; - } - - private readonly CompareTool _enclosing; - } - - private class CmpPngFileFilter : FileUtil.FileFilter - { - public virtual bool Accept(String ap) - { - bool b1 = ap.EndsWith(".png"); - bool b2 = ap.Contains("cmp_"); - return b1 && b2 && ap.Contains(this._enclosing.cmpPdfName); - } - - internal CmpPngFileFilter(CompareTool _enclosing) - { - this._enclosing = _enclosing; - } - - private readonly CompareTool _enclosing; - } - - private class DiffPngFileFilter : FileUtil.FileFilter - { - private String differenceImagePrefix; - - public DiffPngFileFilter(CompareTool _enclosing, String differenceImagePrefix) - { - this._enclosing = _enclosing; - this.differenceImagePrefix = differenceImagePrefix; - } - - public virtual bool Accept(String ap) - { - bool b1 = ap.EndsWith(".png"); - bool b2 = ap.StartsWith(this.differenceImagePrefix); - return b1 && b2; - } - - private readonly CompareTool _enclosing; - } - - private class ImageNameComparator : IComparer - { - public virtual int Compare(String f1, String f2) - { - String f1Name = Path.GetFileName(f1); - String f2Name = Path.GetFileName(f2); - return string.CompareOrdinal(f1Name, f2Name); - } - - internal ImageNameComparator(CompareTool _enclosing) - { - this._enclosing = _enclosing; - } - - private readonly CompareTool _enclosing; - } - - public class CompareResult - { - protected internal IDictionary differences = new - LinkedDictionary(); - - protected internal int messageLimit = 1; - - public CompareResult(CompareTool _enclosing, int messageLimit) - { - this._enclosing = _enclosing; - // LinkedHashMap to retain order. HashMap has different order in Java6/7 and Java8 - this.messageLimit = messageLimit; - } - - public virtual bool IsOk() - { - return this.differences.Count == 0; - } - - public virtual int GetErrorCount() - { - return this.differences.Count; - } - - public virtual String GetReport() - { - StringBuilder sb = new StringBuilder(); - bool firstEntry = true; - foreach (KeyValuePair entry in this.differences) - { - if (!firstEntry) - { - sb.Append("-----------------------------").Append("\n"); - } - CompareTool.ObjectPath diffPath = entry.Key; - sb.Append(entry.Value).Append("\n").Append(diffPath.ToString()).Append("\n"); - firstEntry = false; - } - return sb.ToString(); - } - - public virtual IDictionary GetDifferences() - { - return this.differences; - } - - /// - /// - public virtual void WriteReportToXml(Stream stream) - { - XmlDocument doc = new XmlDocument(); - - XmlElement root = doc.CreateElement("report"); - XmlElement errors = doc.CreateElement("errors"); - - errors.SetAttribute("count", this.differences.Count.ToString()); - root.AppendChild(errors); - foreach (KeyValuePair entry in this.differences) - { - XmlElement errorNode = doc.CreateElement("error"); - XmlElement message = doc.CreateElement("message"); - message.AppendChild(doc.CreateTextNode(entry.Value)); - XmlElement path = entry.Key.ToXmlNode(doc); - errorNode.AppendChild(message); - errorNode.AppendChild(path); - errors.AppendChild(errorNode); - } - doc.AppendChild(root); - XmlWriter writer = new XmlTextWriter(stream, Encoding.Default); - doc.WriteTo(writer); - writer.Flush(); - } - - protected internal virtual bool IsMessageLimitReached() - { - return this.differences.Count >= this.messageLimit; - } - - protected internal virtual void AddError(CompareTool.ObjectPath path, String message - ) - { - if (this.differences.Count < this.messageLimit) - { - this.differences[((CompareTool.ObjectPath)path.Clone())] = message; - } - } - - private readonly CompareTool _enclosing; - } - - public class ObjectPath - { - protected internal PdfIndirectReference baseCmpObject; - - protected internal PdfIndirectReference baseOutObject; - - protected internal Stack path = new Stack(); - - protected internal Stack indirects = new - Stack(); - - public ObjectPath() - { - } - - protected internal ObjectPath(PdfIndirectReference baseCmpObject - , PdfIndirectReference baseOutObject) - { - this.baseCmpObject = baseCmpObject; - this.baseOutObject = baseOutObject; - } - - private ObjectPath(PdfIndirectReference baseCmpObject, PdfIndirectReference - baseOutObject, Stack path, Stack indirects) - { - this.baseCmpObject = baseCmpObject; - this.baseOutObject = baseOutObject; - this.path = path; - this.indirects = indirects; - } - - public virtual CompareTool.ObjectPath ResetDirectPath(PdfIndirectReference baseCmpObject - , PdfIndirectReference baseOutObject) - { - CompareTool.ObjectPath newPath = new CompareTool.ObjectPath(baseCmpObject, - baseOutObject); - newPath.indirects.Clear(); - foreach (IndirectPathItem item in indirects) { - newPath.indirects.Push(item); - } - newPath.indirects.Push(new CompareTool.ObjectPath.IndirectPathItem(this, baseCmpObject - , baseOutObject)); - return newPath; - } - - public virtual bool IsComparing(PdfIndirectReference baseCmpObject, PdfIndirectReference - baseOutObject) - { - return this.indirects.Contains(new CompareTool.ObjectPath.IndirectPathItem(this, - baseCmpObject, baseOutObject)); - } - - public virtual void PushArrayItemToPath(int index) - { - this.path.Push(new CompareTool.ObjectPath.ArrayPathItem(index)); - } - - public virtual void PushDictItemToPath(PdfName key) - { - this.path.Push(new CompareTool.ObjectPath.DictPathItem(key)); - } - - public virtual void PushOffsetToPath(int offset) - { - this.path.Push(new CompareTool.ObjectPath.OffsetPathItem(offset)); - } - - public virtual void Pop() - { - this.path.Pop(); - } - - public virtual Stack GetLocalPath() - { - return this.path; - } - - public virtual Stack GetIndirectPath() - { - return this.indirects; - } - - public virtual PdfIndirectReference GetBaseCmpObject() - { - return this.baseCmpObject; - } - - public virtual PdfIndirectReference GetBaseOutObject() - { - return this.baseOutObject; - } - - public virtual XmlElement ToXmlNode(XmlDocument document) - { + } + } + if (equalPages.Count == cmpPages.Count && compareResult.IsOk()) { + System.Console.Out.WriteLine("OK"); + System.Console.Out.Flush(); + return null; + } + else { + System.Console.Out.WriteLine("Fail"); + System.Console.Out.Flush(); + String compareByContentReport = "Compare by content report:\n" + compareResult.GetReport(); + System.Console.Out.WriteLine(compareByContentReport); + System.Console.Out.Flush(); + String message = CompareVisually(outPath, differenceImagePrefix, ignoredAreas, equalPages); + if (message == null || message.Length == 0) { + return "Compare by content fails. No visual differences"; + } + return message; + } + } + + private void LoadPagesFromReader(PdfDocument doc, IList pages, IList + pagesRef) { + int numOfPages = doc.GetNumberOfPages(); + for (int i = 0; i < numOfPages; ++i) { + pages.Add(doc.GetPage(i + 1).GetPdfObject()); + pagesRef.Add(pages[i].GetIndirectReference()); + } + } + + /// + private void CompareDocumentsEncryption(PdfDocument outDocument, PdfDocument cmpDocument, CompareTool.CompareResult + compareResult) { + PdfDictionary outEncrypt = outDocument.GetTrailer().GetAsDictionary(PdfName.Encrypt); + PdfDictionary cmpEncrypt = cmpDocument.GetTrailer().GetAsDictionary(PdfName.Encrypt); + if (outEncrypt == null && cmpEncrypt == null) { + return; + } + CompareTool.TrailerPath trailerPath = new CompareTool.TrailerPath(cmpDocument, outDocument); + if (outEncrypt == null) { + compareResult.AddError(trailerPath, "Expected encrypted document."); + return; + } + if (cmpEncrypt == null) { + compareResult.AddError(trailerPath, "Expected not encrypted document."); + return; + } + ICollection ignoredEncryptEntries = new LinkedHashSet(iText.IO.Util.JavaUtil.ArraysAsList + (PdfName.O, PdfName.U, PdfName.OE, PdfName.UE, PdfName.Perms, PdfName.CF, PdfName.Recipients)); + CompareTool.ObjectPath objectPath = new CompareTool.ObjectPath(outEncrypt.GetIndirectReference(), cmpEncrypt + .GetIndirectReference()); + CompareDictionariesExtended(outEncrypt, cmpEncrypt, objectPath, compareResult, ignoredEncryptEntries); + PdfDictionary outCfDict = outEncrypt.GetAsDictionary(PdfName.CF); + PdfDictionary cmpCfDict = cmpEncrypt.GetAsDictionary(PdfName.CF); + if (cmpCfDict != null || outCfDict != null) { + if (cmpCfDict != null && outCfDict == null || cmpCfDict == null) { + compareResult.AddError(objectPath, "One of the dictionaries is null, the other is not."); + } + else { + ICollection mergedKeys = new SortedSet(outCfDict.KeySet()); + mergedKeys.AddAll(cmpCfDict.KeySet()); + foreach (PdfName key in mergedKeys) { + objectPath.PushDictItemToPath(key); + LinkedHashSet excludedKeys = new LinkedHashSet(iText.IO.Util.JavaUtil.ArraysAsList(PdfName + .Recipients)); + CompareDictionariesExtended(outCfDict.GetAsDictionary(key), cmpCfDict.GetAsDictionary(key), objectPath, compareResult + , excludedKeys); + objectPath.Pop(); + } + } + } + } + + /// + private bool CompareStreams(Stream is1, Stream is2) { + byte[] buffer1 = new byte[64 * 1024]; + byte[] buffer2 = new byte[64 * 1024]; + int len1; + int len2; + for (; ; ) { + len1 = is1.Read(buffer1); + len2 = is2.Read(buffer2); + if (len1 != len2) { + return false; + } + if (!iText.IO.Util.JavaUtil.ArraysEquals(buffer1, buffer2)) { + return false; + } + if (len1 == -1) { + break; + } + } + return true; + } + + /// + private bool CompareDictionariesExtended(PdfDictionary outDict, PdfDictionary cmpDict, CompareTool.ObjectPath + currentPath, CompareTool.CompareResult compareResult) { + return CompareDictionariesExtended(outDict, cmpDict, currentPath, compareResult, null); + } + + /// + private bool CompareDictionariesExtended(PdfDictionary outDict, PdfDictionary cmpDict, CompareTool.ObjectPath + currentPath, CompareTool.CompareResult compareResult, ICollection excludedKeys) { + if (cmpDict != null && outDict == null || outDict != null && cmpDict == null) { + compareResult.AddError(currentPath, "One of the dictionaries is null, the other is not."); + return false; + } + bool dictsAreSame = true; + // Iterate through the union of the keys of the cmp and out dictionaries + ICollection mergedKeys = new SortedSet(cmpDict.KeySet()); + mergedKeys.AddAll(outDict.KeySet()); + foreach (PdfName key in mergedKeys) { + if (excludedKeys != null && excludedKeys.Contains(key)) { + continue; + } + if (key.Equals(PdfName.Parent) || key.Equals(PdfName.P) || key.Equals(PdfName.ModDate)) { + continue; + } + if (outDict.IsStream() && cmpDict.IsStream() && (key.Equals(PdfName.Filter) || key.Equals(PdfName.Length)) + ) { + continue; + } + if (key.Equals(PdfName.BaseFont) || key.Equals(PdfName.FontName)) { + PdfObject cmpObj = cmpDict.Get(key); + if (cmpObj.IsName() && cmpObj.ToString().IndexOf('+') > 0) { + PdfObject outObj = outDict.Get(key); + if (!outObj.IsName() || outObj.ToString().IndexOf('+') == -1) { + if (compareResult != null && currentPath != null) { + compareResult.AddError(currentPath, String.Format("PdfDictionary {0} entry: Expected: {1}. Found: {2}", key + .ToString(), cmpObj.ToString(), outObj.ToString())); + } + dictsAreSame = false; + } + else { + String cmpName = cmpObj.ToString().Substring(cmpObj.ToString().IndexOf('+')); + String outName = outObj.ToString().Substring(outObj.ToString().IndexOf('+')); + if (!cmpName.Equals(outName)) { + if (compareResult != null && currentPath != null) { + compareResult.AddError(currentPath, String.Format("PdfDictionary {0} entry: Expected: {1}. Found: {2}", key + .ToString(), cmpObj.ToString(), outObj.ToString())); + } + dictsAreSame = false; + } + } + continue; + } + } + if (currentPath != null) { + currentPath.PushDictItemToPath(key); + } + dictsAreSame = CompareObjects(outDict.Get(key, false), cmpDict.Get(key, false), currentPath, compareResult + ) && dictsAreSame; + if (currentPath != null) { + currentPath.Pop(); + } + if (!dictsAreSame && (currentPath == null || compareResult == null || compareResult.IsMessageLimitReached( + ))) { + return false; + } + } + return dictsAreSame; + } + + /// + private bool CompareObjects(PdfObject outObj, PdfObject cmpObj, CompareTool.ObjectPath currentPath, CompareTool.CompareResult + compareResult) { + PdfObject outDirectObj = null; + PdfObject cmpDirectObj = null; + if (outObj != null) { + outDirectObj = outObj.IsIndirectReference() ? ((PdfIndirectReference)outObj).GetRefersTo(false) : outObj; + } + if (cmpObj != null) { + cmpDirectObj = cmpObj.IsIndirectReference() ? ((PdfIndirectReference)cmpObj).GetRefersTo(false) : cmpObj; + } + if (cmpDirectObj == null && outDirectObj == null) { + return true; + } + if (outDirectObj == null) { + compareResult.AddError(currentPath, "Expected object was not found."); + return false; + } + else { + if (cmpDirectObj == null) { + compareResult.AddError(currentPath, "Found object which was not expected to be found."); + return false; + } + else { + if (cmpDirectObj.GetObjectType() != outDirectObj.GetObjectType()) { + compareResult.AddError(currentPath, String.Format("Types do not match. Expected: {0}. Found: {1}.", cmpDirectObj + .GetType().Name, outDirectObj.GetType().Name)); + return false; + } + else { + if (cmpObj.IsIndirectReference() && !outObj.IsIndirectReference()) { + compareResult.AddError(currentPath, "Expected indirect object."); + return false; + } + else { + if (!cmpObj.IsIndirectReference() && outObj.IsIndirectReference()) { + compareResult.AddError(currentPath, "Expected direct object."); + return false; + } + } + } + } + } + if (currentPath != null && cmpObj.IsIndirectReference() && outObj.IsIndirectReference()) { + if (currentPath.IsComparing((PdfIndirectReference)cmpObj, (PdfIndirectReference)outObj)) { + return true; + } + currentPath = currentPath.ResetDirectPath((PdfIndirectReference)cmpObj, (PdfIndirectReference)outObj); + } + if (cmpDirectObj.IsDictionary() && PdfName.Page.Equals(((PdfDictionary)cmpDirectObj).GetAsName(PdfName.Type + )) && useCachedPagesForComparison) { + if (!outDirectObj.IsDictionary() || !PdfName.Page.Equals(((PdfDictionary)outDirectObj).GetAsName(PdfName.Type + ))) { + if (compareResult != null && currentPath != null) { + compareResult.AddError(currentPath, "Expected a page. Found not a page."); + } + return false; + } + PdfIndirectReference cmpRefKey = cmpObj.IsIndirectReference() ? (PdfIndirectReference)cmpObj : cmpObj.GetIndirectReference + (); + PdfIndirectReference outRefKey = outObj.IsIndirectReference() ? (PdfIndirectReference)outObj : outObj.GetIndirectReference + (); + // References to the same page + if (cmpPagesRef == null) { + cmpPagesRef = new List(); + for (int i = 1; i <= cmpObj.GetIndirectReference().GetDocument().GetNumberOfPages(); ++i) { + cmpPagesRef.Add(cmpObj.GetIndirectReference().GetDocument().GetPage(i).GetPdfObject().GetIndirectReference + ()); + } + } + if (outPagesRef == null) { + outPagesRef = new List(); + for (int i = 1; i <= outObj.GetIndirectReference().GetDocument().GetNumberOfPages(); ++i) { + outPagesRef.Add(outObj.GetIndirectReference().GetDocument().GetPage(i).GetPdfObject().GetIndirectReference + ()); + } + } + if (cmpPagesRef.Contains(cmpRefKey) && cmpPagesRef.IndexOf(cmpRefKey) == outPagesRef.IndexOf(outRefKey)) { + return true; + } + if (compareResult != null && currentPath != null) { + compareResult.AddError(currentPath, String.Format("The dictionaries refer to different pages. Expected page number: {0}. Found: {1}" + , cmpPagesRef.IndexOf(cmpRefKey), outPagesRef.IndexOf(outRefKey))); + } + return false; + } + if (cmpDirectObj.IsDictionary()) { + if (!CompareDictionariesExtended((PdfDictionary)outDirectObj, (PdfDictionary)cmpDirectObj, currentPath, compareResult + )) { + return false; + } + } + else { + if (cmpDirectObj.IsStream()) { + if (!CompareStreamsExtended((PdfStream)outDirectObj, (PdfStream)cmpDirectObj, currentPath, compareResult)) { + return false; + } + } + else { + if (cmpDirectObj.IsArray()) { + if (!CompareArraysExtended((PdfArray)outDirectObj, (PdfArray)cmpDirectObj, currentPath, compareResult)) { + return false; + } + } + else { + if (cmpDirectObj.IsName()) { + if (!CompareNamesExtended((PdfName)outDirectObj, (PdfName)cmpDirectObj, currentPath, compareResult)) { + return false; + } + } + else { + if (cmpDirectObj.IsNumber()) { + if (!CompareNumbersExtended((PdfNumber)outDirectObj, (PdfNumber)cmpDirectObj, currentPath, compareResult)) { + return false; + } + } + else { + if (cmpDirectObj.IsString()) { + if (!CompareStringsExtended((PdfString)outDirectObj, (PdfString)cmpDirectObj, currentPath, compareResult)) { + return false; + } + } + else { + if (cmpDirectObj.IsBoolean()) { + if (!CompareBooleansExtended((PdfBoolean)outDirectObj, (PdfBoolean)cmpDirectObj, currentPath, compareResult + )) { + return false; + } + } + else { + if (outDirectObj.IsNull() && cmpDirectObj.IsNull()) { + } + else { + throw new NotSupportedException(); + } + } + } + } + } + } + } + } + return true; + } + + /// + private bool CompareStreamsExtended(PdfStream outStream, PdfStream cmpStream, CompareTool.ObjectPath currentPath + , CompareTool.CompareResult compareResult) { + bool toDecode = PdfName.FlateDecode.Equals(outStream.Get(PdfName.Filter)); + byte[] outStreamBytes = outStream.GetBytes(toDecode); + byte[] cmpStreamBytes = cmpStream.GetBytes(toDecode); + if (iText.IO.Util.JavaUtil.ArraysEquals(outStreamBytes, cmpStreamBytes)) { + return CompareDictionariesExtended(outStream, cmpStream, currentPath, compareResult); + } + else { + String errorMessage = ""; + if (cmpStreamBytes.Length != outStreamBytes.Length) { + errorMessage += String.Format("PdfStream. Lengths are different. Expected: {0}. Found: {1}", cmpStreamBytes + .Length, outStreamBytes.Length) + "\n"; + } + else { + errorMessage += "PdfStream. Bytes are different.\n"; + } + String bytesDifference = FindBytesDifference(outStreamBytes, cmpStreamBytes); + if (bytesDifference != null) { + errorMessage += bytesDifference; + } + if (compareResult != null && currentPath != null) { + // currentPath.pushOffsetToPath(firstDifferenceOffset); + compareResult.AddError(currentPath, errorMessage); + } + // currentPath.pop(); + return false; + } + } + + private String FindBytesDifference(byte[] outStreamBytes, byte[] cmpStreamBytes) { + int numberOfDifferentBytes = 0; + int firstDifferenceOffset = 0; + int minLength = Math.Min(cmpStreamBytes.Length, outStreamBytes.Length); + for (int i = 0; i < minLength; i++) { + if (cmpStreamBytes[i] != outStreamBytes[i]) { + ++numberOfDifferentBytes; + if (numberOfDifferentBytes == 1) { + firstDifferenceOffset = i; + } + } + } + String errorMessage = null; + if (numberOfDifferentBytes > 0) { + int diffBytesAreaL = 10; + int diffBytesAreaR = 10; + int lCmp = Math.Max(0, firstDifferenceOffset - diffBytesAreaL); + int rCmp = Math.Min(cmpStreamBytes.Length, firstDifferenceOffset + diffBytesAreaR); + int lOut = Math.Max(0, firstDifferenceOffset - diffBytesAreaL); + int rOut = Math.Min(outStreamBytes.Length, firstDifferenceOffset + diffBytesAreaR); + String cmpByte = iText.IO.Util.JavaUtil.GetStringForBytes(new byte[] { cmpStreamBytes[firstDifferenceOffset + ] }); + String cmpByteNeighbours = iText.IO.Util.StringUtil.ReplaceAll(iText.IO.Util.JavaUtil.GetStringForBytes(cmpStreamBytes + , lCmp, rCmp - lCmp), "\\r|\\n", " "); + String outByte = iText.IO.Util.JavaUtil.GetStringForBytes(new byte[] { outStreamBytes[firstDifferenceOffset + ] }); + String outBytesNeighbours = iText.IO.Util.StringUtil.ReplaceAll(iText.IO.Util.JavaUtil.GetStringForBytes(outStreamBytes + , lOut, rOut - lOut), "\\r|\\n", " "); + errorMessage = String.Format("First bytes difference is encountered at index {0}. Expected: {1} ({2}). Found: {3} ({4}). Total number of different bytes: {5}" + , iText.IO.Util.JavaUtil.IntegerToString(System.Convert.ToInt32(firstDifferenceOffset)), cmpByte, cmpByteNeighbours + , outByte, outBytesNeighbours, numberOfDifferentBytes); + } + else { + // lengths are different + errorMessage = String.Format("Bytes of the shorter array are the same as the first {0} bytes of the longer one." + , minLength); + } + return errorMessage; + } + + /// + private bool CompareArraysExtended(PdfArray outArray, PdfArray cmpArray, CompareTool.ObjectPath currentPath + , CompareTool.CompareResult compareResult) { + if (outArray == null) { + if (compareResult != null && currentPath != null) { + compareResult.AddError(currentPath, "Found null. Expected PdfArray."); + } + return false; + } + else { + if (outArray.Size() != cmpArray.Size()) { + if (compareResult != null && currentPath != null) { + compareResult.AddError(currentPath, String.Format("PdfArrays. Lengths are different. Expected: {0}. Found: {1}." + , cmpArray.Size(), outArray.Size())); + } + return false; + } + } + bool arraysAreEqual = true; + for (int i = 0; i < cmpArray.Size(); i++) { + if (currentPath != null) { + currentPath.PushArrayItemToPath(i); + } + arraysAreEqual = CompareObjects(outArray.Get(i, false), cmpArray.Get(i, false), currentPath, compareResult + ) && arraysAreEqual; + if (currentPath != null) { + currentPath.Pop(); + } + if (!arraysAreEqual && (currentPath == null || compareResult == null || compareResult.IsMessageLimitReached + ())) { + return false; + } + } + return arraysAreEqual; + } + + private bool CompareNamesExtended(PdfName outName, PdfName cmpName, CompareTool.ObjectPath currentPath, CompareTool.CompareResult + compareResult) { + if (cmpName.Equals(outName)) { + return true; + } + else { + if (compareResult != null && currentPath != null) { + compareResult.AddError(currentPath, String.Format("PdfName. Expected: {0}. Found: {1}", cmpName.ToString() + , outName.ToString())); + } + return false; + } + } + + private bool CompareNumbersExtended(PdfNumber outNumber, PdfNumber cmpNumber, CompareTool.ObjectPath currentPath + , CompareTool.CompareResult compareResult) { + if (cmpNumber.GetValue() == outNumber.GetValue()) { + return true; + } + else { + if (compareResult != null && currentPath != null) { + compareResult.AddError(currentPath, String.Format("PdfNumber. Expected: {0}. Found: {1}", cmpNumber, outNumber + )); + } + return false; + } + } + + private bool CompareStringsExtended(PdfString outString, PdfString cmpString, CompareTool.ObjectPath currentPath + , CompareTool.CompareResult compareResult) { + if (iText.IO.Util.JavaUtil.ArraysEquals(ConvertPdfStringToBytes(cmpString), ConvertPdfStringToBytes(outString + ))) { + return true; + } + else { + String cmpStr = cmpString.ToUnicodeString(); + String outStr = outString.ToUnicodeString(); + if (cmpStr.Length != outStr.Length) { + if (compareResult != null && currentPath != null) { + compareResult.AddError(currentPath, String.Format("PdfString. Lengths are different. Expected: {0}. Found: {1}" + , cmpStr.Length, outStr.Length)); + } + } + else { + for (int i = 0; i < cmpStr.Length; i++) { + if (cmpStr[i] != outStr[i]) { + int l = Math.Max(0, i - 10); + int r = Math.Min(cmpStr.Length, i + 10); + if (compareResult != null && currentPath != null) { + currentPath.PushOffsetToPath(i); + compareResult.AddError(currentPath, String.Format("PdfString. Characters differ at position {0}. Expected: {1} ({2}). Found: {3} ({4})." + , i, char.ToString(cmpStr[i]), cmpStr.JSubstring(l, r).Replace("\n", "\\n"), char.ToString(outStr[i]), + outStr.JSubstring(l, r).Replace("\n", "\\n"))); + currentPath.Pop(); + } + break; + } + } + } + return false; + } + } + + private byte[] ConvertPdfStringToBytes(PdfString pdfString) { + byte[] bytes; + String value = pdfString.GetValue(); + String encoding = pdfString.GetEncoding(); + if (encoding != null && encoding.Equals(PdfEncodings.UNICODE_BIG) && PdfEncodings.IsPdfDocEncoding(value)) { + bytes = PdfEncodings.ConvertToBytes(value, PdfEncodings.PDF_DOC_ENCODING); + } + else { + bytes = PdfEncodings.ConvertToBytes(value, encoding); + } + return bytes; + } + + private bool CompareBooleansExtended(PdfBoolean outBoolean, PdfBoolean cmpBoolean, CompareTool.ObjectPath + currentPath, CompareTool.CompareResult compareResult) { + if (cmpBoolean.GetValue() == outBoolean.GetValue()) { + return true; + } + else { + if (compareResult != null && currentPath != null) { + compareResult.AddError(currentPath, String.Format("PdfBoolean. Expected: {0}. Found: {1}.", cmpBoolean.GetValue + (), outBoolean.GetValue())); + } + return false; + } + } + + private IList GetLinkAnnotations(int pageNum, PdfDocument document) { + IList linkAnnotations = new List(); + IList annotations = document.GetPage(pageNum).GetAnnotations(); + foreach (PdfAnnotation annotation in annotations) { + if (PdfName.Link.Equals(annotation.GetSubtype())) { + linkAnnotations.Add((PdfLinkAnnotation)annotation); + } + } + return linkAnnotations; + } + + private bool CompareLinkAnnotations(PdfLinkAnnotation cmpLink, PdfLinkAnnotation outLink, PdfDocument cmpDocument + , PdfDocument outDocument) { + // Compare link rectangles, page numbers the links refer to, and simple parameters (non-indirect, non-arrays, non-dictionaries) + PdfObject cmpDestObject = cmpLink.GetDestinationObject(); + PdfObject outDestObject = outLink.GetDestinationObject(); + if (cmpDestObject != null && outDestObject != null) { + if (cmpDestObject.GetObjectType() != outDestObject.GetObjectType()) { + return false; + } + else { + PdfArray explicitCmpDest = null; + PdfArray explicitOutDest = null; + IDictionary cmpNamedDestinations = cmpDocument.GetCatalog().GetNameTree(PdfName.Dests). + GetNames(); + IDictionary outNamedDestinations = outDocument.GetCatalog().GetNameTree(PdfName.Dests). + GetNames(); + switch (cmpDestObject.GetObjectType()) { + case PdfObject.ARRAY: { + explicitCmpDest = (PdfArray)cmpDestObject; + explicitOutDest = (PdfArray)outDestObject; + break; + } + + case PdfObject.NAME: { + explicitCmpDest = (PdfArray)cmpNamedDestinations.Get(((PdfName)cmpDestObject).GetValue()); + explicitOutDest = (PdfArray)outNamedDestinations.Get(((PdfName)outDestObject).GetValue()); + break; + } + + case PdfObject.STRING: { + explicitCmpDest = (PdfArray)cmpNamedDestinations.Get(((PdfString)cmpDestObject).ToUnicodeString()); + explicitOutDest = (PdfArray)outNamedDestinations.Get(((PdfString)outDestObject).ToUnicodeString()); + break; + } + + default: { + break; + } + } + if (GetExplicitDestinationPageNum(explicitCmpDest) != GetExplicitDestinationPageNum(explicitOutDest)) { + return false; + } + } + } + PdfDictionary cmpDict = cmpLink.GetPdfObject(); + PdfDictionary outDict = outLink.GetPdfObject(); + if (cmpDict.Size() != outDict.Size()) { + return false; + } + Rectangle cmpRect = cmpDict.GetAsRectangle(PdfName.Rect); + Rectangle outRect = outDict.GetAsRectangle(PdfName.Rect); + if (cmpRect.GetHeight() != outRect.GetHeight() || cmpRect.GetWidth() != outRect.GetWidth() || cmpRect.GetX + () != outRect.GetX() || cmpRect.GetY() != outRect.GetY()) { + return false; + } + foreach (KeyValuePair cmpEntry in cmpDict.EntrySet()) { + PdfObject cmpObj = cmpEntry.Value; + if (!outDict.ContainsKey(cmpEntry.Key)) { + return false; + } + PdfObject outObj = outDict.Get(cmpEntry.Key); + if (cmpObj.GetObjectType() != outObj.GetObjectType()) { + return false; + } + switch (cmpObj.GetObjectType()) { + case PdfObject.NULL: + case PdfObject.BOOLEAN: + case PdfObject.NUMBER: + case PdfObject.STRING: + case PdfObject.NAME: { + if (!cmpObj.ToString().Equals(outObj.ToString())) { + return false; + } + break; + } + } + } + return true; + } + + private int GetExplicitDestinationPageNum(PdfArray explicitDest) { + PdfIndirectReference pageReference = (PdfIndirectReference)explicitDest.Get(0, false); + PdfDocument doc = pageReference.GetDocument(); + for (int i = 1; i <= doc.GetNumberOfPages(); ++i) { + if (doc.GetPage(i).GetPdfObject().GetIndirectReference().Equals(pageReference)) { + return i; + } + } + throw new ArgumentException("PdfLinkAnnotation comparison: Page not found."); + } + + private String[] ConvertInfo(PdfDocumentInfo info) { + String[] convertedInfo = new String[] { "", "", "", "" }; + String infoValue = info.GetTitle(); + if (infoValue != null) { + convertedInfo[0] = infoValue; + } + infoValue = info.GetAuthor(); + if (infoValue != null) { + convertedInfo[1] = infoValue; + } + infoValue = info.GetSubject(); + if (infoValue != null) { + convertedInfo[2] = infoValue; + } + infoValue = info.GetKeywords(); + if (infoValue != null) { + convertedInfo[3] = infoValue; + } + return convertedInfo; + } + + private class PngFileFilter : iText.IO.Util.FileUtil.IFileFilter { + public virtual bool Accept(FileInfo pathname) { + String ap = pathname.Name; + bool b1 = ap.EndsWith(".png"); + bool b2 = ap.Contains("cmp_"); + return b1 && !b2 && ap.Contains(this._enclosing.outPdfName); + } + + internal PngFileFilter(CompareTool _enclosing) { + this._enclosing = _enclosing; + } + + private readonly CompareTool _enclosing; + } + + private class CmpPngFileFilter : iText.IO.Util.FileUtil.IFileFilter { + public virtual bool Accept(FileInfo pathname) { + String ap = pathname.Name; + bool b1 = ap.EndsWith(".png"); + bool b2 = ap.Contains("cmp_"); + return b1 && b2 && ap.Contains(this._enclosing.cmpPdfName); + } + + internal CmpPngFileFilter(CompareTool _enclosing) { + this._enclosing = _enclosing; + } + + private readonly CompareTool _enclosing; + } + + private class DiffPngFileFilter : iText.IO.Util.FileUtil.IFileFilter { + private String differenceImagePrefix; + + public DiffPngFileFilter(CompareTool _enclosing, String differenceImagePrefix) { + this._enclosing = _enclosing; + this.differenceImagePrefix = differenceImagePrefix; + } + + public virtual bool Accept(FileInfo pathname) { + String ap = pathname.Name; + bool b1 = ap.EndsWith(".png"); + bool b2 = ap.StartsWith(this.differenceImagePrefix); + return b1 && b2; + } + + private readonly CompareTool _enclosing; + } + + private class ImageNameComparator : IComparer { + public virtual int Compare(FileInfo f1, FileInfo f2) { + String f1Name = f1.Name; + String f2Name = f2.Name; + return string.CompareOrdinal(f1Name, f2Name); + } + + internal ImageNameComparator(CompareTool _enclosing) { + this._enclosing = _enclosing; + } + + private readonly CompareTool _enclosing; + } + + /// Class containing results of the comparison of two documents. + public class CompareResult { + protected internal IDictionary differences = new LinkedDictionary(); + + protected internal int messageLimit = 1; + + /// Creates new empty instance of CompareResult with given limit of difference messages. + /// maximum number of difference messages handled by this CompareResult. + public CompareResult(CompareTool _enclosing, int messageLimit) { + this._enclosing = _enclosing; + // LinkedHashMap to retain order. HashMap has different order in Java6/7 and Java8 + this.messageLimit = messageLimit; + } + + /// Is used to define if documents are considered equal after comparison. + /// true if documents are equal, false otherwise. + public virtual bool IsOk() { + return this.differences.Count == 0; + } + + /// Returns number of differences between two documents met during comparison. + /// number of differences. + public virtual int GetErrorCount() { + return this.differences.Count; + } + + /// Converts this CompareResult into text form. + /// text report of the differences between two documents. + public virtual String GetReport() { + StringBuilder sb = new StringBuilder(); + bool firstEntry = true; + foreach (KeyValuePair entry in this.differences) { + if (!firstEntry) { + sb.Append("-----------------------------").Append("\n"); + } + CompareTool.ObjectPath diffPath = entry.Key; + sb.Append(entry.Value).Append("\n").Append(diffPath.ToString()).Append("\n"); + firstEntry = false; + } + return sb.ToString(); + } + + /// + /// Returns map with + /// + /// as keys and difference descriptions as values. + /// + /// differences map which could be used to find in the document objects that are different. + public virtual IDictionary GetDifferences() { + return this.differences; + } + + /// Converts this CompareResult into xml form. + /// output stream to which xml report will be written. + /// + /// + public virtual void WriteReportToXml(Stream stream) { + XmlDocument xmlReport = XmlUtils.InitNewXmlDocument(); + XmlElement root = xmlReport.CreateElement("report"); + XmlElement errors = xmlReport.CreateElement("errors"); + errors.SetAttribute("count", this.differences.Count.ToString()); + root.AppendChild(errors); + foreach (KeyValuePair entry in this.differences) { + XmlElement errorNode = xmlReport.CreateElement("error"); + XmlElement message = xmlReport.CreateElement("message"); + message.AppendChild(xmlReport.CreateTextNode(entry.Value)); + XmlElement path = entry.Key.ToXmlNode(xmlReport); + errorNode.AppendChild(message); + errorNode.AppendChild(path); + errors.AppendChild(errorNode); + } + xmlReport.AppendChild(root); + XmlUtils.WriteXmlDocToStream(xmlReport, stream); + } + + protected internal virtual bool IsMessageLimitReached() { + return this.differences.Count >= this.messageLimit; + } + + protected internal virtual void AddError(CompareTool.ObjectPath path, String message) { + if (this.differences.Count < this.messageLimit) { + this.differences[((CompareTool.ObjectPath)path.Clone())] = message; + } + } + + private readonly CompareTool _enclosing; + } + + /// + /// Class that helps to find two corresponding objects in the comparing documents and also keeps track of the + /// already met in comparing process parent indirect objects. + /// + /// + /// Class that helps to find two corresponding objects in the comparing documents and also keeps track of the + /// already met in comparing process parent indirect objects. + ///

    + /// You could say that ObjectPath instance consists of two parts: direct path and indirect path. Direct path defines + /// path to the currently comparing objects in relation to base objects. It could be empty, which would mean that + /// currently comparing objects are base objects themselves. Base objects are the two indirect objects from the comparing + /// documents which are in the same position in the pdf trees. Another part, indirect path, defines which indirect + /// objects were met during comparison process to get to the current base objects. Indirect path is needed to avoid + /// infinite loops during comparison. + /// + public class ObjectPath { + protected internal PdfIndirectReference baseCmpObject; + + protected internal PdfIndirectReference baseOutObject; + + protected internal Stack path = new Stack(); + + protected internal Stack indirects = new Stack(); + + ///

    Creates empty ObjectPath. + public ObjectPath() { + } + + /// Creates ObjectPath with corresponding base objects in two documents. + /// base object in cmp document. + /// base object in out document. + protected internal ObjectPath(PdfIndirectReference baseCmpObject, PdfIndirectReference baseOutObject) { + this.baseCmpObject = baseCmpObject; + this.baseOutObject = baseOutObject; + } + + private ObjectPath(PdfIndirectReference baseCmpObject, PdfIndirectReference baseOutObject, Stack path, Stack indirects) { + this.baseCmpObject = baseCmpObject; + this.baseOutObject = baseOutObject; + this.path = path; + this.indirects = indirects; + } + + /// + /// Creates a new ObjectPath instance with two new given base objects, which are supposed to be nested in the base + /// objects of the current instance of the ObjectPath. + /// + /// + /// Creates a new ObjectPath instance with two new given base objects, which are supposed to be nested in the base + /// objects of the current instance of the ObjectPath. This method is used to avoid infinite loop in case of + /// circular references in pdf documents objects structure. + ///
    + /// Basically, this method creates copy of the current ObjectPath instance, but resets information of the direct + /// paths, and also adds current ObjectPath instance base objects to the indirect references chain that denotes + /// a path to the new base objects. + ///
    + /// new base object in cmp document. + /// new base object in out document. + /// + /// new ObjectPath instance, which stores chain of the indirect references which were already met to get + /// to the new base objects. + /// + public virtual CompareTool.ObjectPath ResetDirectPath(PdfIndirectReference baseCmpObject, PdfIndirectReference + baseOutObject) { + CompareTool.ObjectPath newPath = new CompareTool.ObjectPath(baseCmpObject, baseOutObject); + newPath.indirects = (Stack)indirects.Clone(); + newPath.indirects.Push(new CompareTool.ObjectPath.IndirectPathItem(this, baseCmpObject, baseOutObject)); + return newPath; + } + + /// This method is used to define if given objects were already met in the path to the current base objects. + /// + /// + /// This method is used to define if given objects were already met in the path to the current base objects. + /// If this method returns true it basically means that we found a loop in the objects structure and that we + /// already compared these objects. + /// + /// cmp object to check if it was already met in base objects path. + /// out object to check if it was already met in base objects path. + /// true if given objects are contained in the path and therefore were already compared. + public virtual bool IsComparing(PdfIndirectReference cmpObject, PdfIndirectReference outObject) { + return indirects.Contains(new CompareTool.ObjectPath.IndirectPathItem(this, cmpObject, outObject)); + } + + /// Adds array item to the direct path. + /// + /// Adds array item to the direct path. See + /// + /// . + /// + /// index in the array of the direct object to be compared. + public virtual void PushArrayItemToPath(int index) { + path.Push(new CompareTool.ObjectPath.ArrayPathItem(index)); + } + + /// Adds dictionary item to the direct path. + /// + /// Adds dictionary item to the direct path. See + /// + /// . + /// + /// key in the dictionary to which corresponds direct object to be compared. + public virtual void PushDictItemToPath(PdfName key) { + path.Push(new CompareTool.ObjectPath.DictPathItem(key)); + } + + /// Adds offset item to the direct path. + /// + /// Adds offset item to the direct path. See + /// + /// . + /// + /// offset to the specific byte in the stream that is compared. + public virtual void PushOffsetToPath(int offset) { + path.Push(new CompareTool.ObjectPath.OffsetPathItem(offset)); + } + + /// Removes the last path item from the direct path. + public virtual void Pop() { + path.Pop(); + } + + /// + /// Gets local (or direct) path that denotes sequence of the path items from base object to the comparing + /// direct object. + /// + /// direct path to the comparing object. + public virtual Stack GetLocalPath() { + return path; + } + + /// + /// Gets indirect path which denotes sequence of the indirect references that were passed in comparing process + /// to get to the current base objects. + /// + /// indirect path to the current base objects. + public virtual Stack GetIndirectPath() { + return indirects; + } + + /// current base object in the cmp document. + public virtual PdfIndirectReference GetBaseCmpObject() { + return baseCmpObject; + } + + /// current base object in the out document. + public virtual PdfIndirectReference GetBaseOutObject() { + return baseOutObject; + } + + /// Creates an xml node that describes a direct path stored in this ObjectPath instance. + /// xml document, to which this xml node will be added. + /// an xml node describing direct path. + public virtual XmlElement ToXmlNode(XmlDocument document) { XmlElement element = document.CreateElement("path"); XmlElement baseNode = document.CreateElement("base"); - baseNode.SetAttribute("cmp", String.Format("{0} {1} obj", this.baseCmpObject.GetObjNumber - (), this.baseCmpObject.GetGenNumber())); - baseNode.SetAttribute("out", String.Format("{0} {1} obj", this.baseOutObject.GetObjNumber - (), this.baseOutObject.GetGenNumber())); - element.AppendChild(baseNode); - foreach (CompareTool.ObjectPath.LocalPathItem pathItem in this.path) - { - element.AppendChild(pathItem.ToXmlNode(document)); - } - return element; - } - - public override String ToString() - { - StringBuilder sb = new StringBuilder(); - sb.Append(String.Format("Base cmp object: {0} obj. Base out object: {1} obj", this - .baseCmpObject, this.baseOutObject)); - foreach (CompareTool.ObjectPath.LocalPathItem pathItem in this.path) - { - sb.Append("\n"); - sb.Append(pathItem.ToString()); - } - return sb.ToString(); - } - - public override int GetHashCode() - { - int hashCode = (this.baseCmpObject != null ? this.baseCmpObject.GetHashCode() : 0 - ) * 31 + (this.baseOutObject != null ? this.baseOutObject.GetHashCode() : 0); - foreach (CompareTool.ObjectPath.LocalPathItem pathItem in this.path) - { - hashCode *= 31; - hashCode += pathItem.GetHashCode(); - } - return hashCode; - } - - public override bool Equals(Object obj) - { - return obj is CompareTool.ObjectPath && this.baseCmpObject.Equals(((CompareTool.ObjectPath - )obj).baseCmpObject) && this.baseOutObject.Equals(((CompareTool.ObjectPath)obj). - baseOutObject) && this.path.Equals(path); - } - - protected internal virtual Object Clone() - { - Stack clonedPath = new Stack(); - foreach (LocalPathItem item in path) { - clonedPath.Push(item); - } - Stack clonedIndirects = new Stack(); - foreach (IndirectPathItem item in indirects) - { - clonedIndirects.Push(item); - } - return new CompareTool.ObjectPath(this.baseCmpObject, this.baseOutObject, clonedPath, clonedIndirects); - } - - public class IndirectPathItem - { - private PdfIndirectReference cmpObject; - - private PdfIndirectReference outObject; - - public IndirectPathItem(ObjectPath _enclosing, PdfIndirectReference cmpObject, PdfIndirectReference - outObject) - { - this._enclosing = _enclosing; - this.cmpObject = cmpObject; - this.outObject = outObject; - } - - public virtual PdfIndirectReference GetCmpObject() - { - return this.cmpObject; - } - - public virtual PdfIndirectReference GetOutObject() - { - return this.outObject; - } - - public override int GetHashCode() - { - return this.cmpObject.GetHashCode() * 31 + this.outObject.GetHashCode(); - } - - public override bool Equals(Object obj) - { - return (obj is CompareTool.ObjectPath.IndirectPathItem && this.cmpObject.Equals(( - (CompareTool.ObjectPath.IndirectPathItem)obj).cmpObject) && this.outObject.Equals - (((CompareTool.ObjectPath.IndirectPathItem)obj).outObject)); - } - - private readonly ObjectPath _enclosing; - } - - public abstract class LocalPathItem - { - protected internal abstract XmlElement ToXmlNode(XmlDocument document); - } - - public class DictPathItem : CompareTool.ObjectPath.LocalPathItem - { - internal PdfName key; - - public DictPathItem(PdfName key) - { - this.key = key; - } - - public override String ToString() - { - return "Dict key: " + this.key; - } - - public override int GetHashCode() - { - return this.key.GetHashCode(); - } - - public override bool Equals(Object obj) - { - return obj is CompareTool.ObjectPath.DictPathItem && this.key.Equals(((CompareTool.ObjectPath.DictPathItem - )obj).key); - } - - protected internal override XmlElement ToXmlNode(XmlDocument document) - { + baseNode.SetAttribute("cmp", String.Format("{0} {1} obj", baseCmpObject.GetObjNumber(), baseCmpObject.GetGenNumber + ())); + baseNode.SetAttribute("out", String.Format("{0} {1} obj", baseOutObject.GetObjNumber(), baseOutObject.GetGenNumber + ())); + element.AppendChild(baseNode); + foreach (CompareTool.ObjectPath.LocalPathItem pathItem in path) { + element.AppendChild(pathItem.ToXmlNode(document)); + } + return element; + } + + /// string representation of the direct path stored in this ObjectPath instance. + public override String ToString() { + StringBuilder sb = new StringBuilder(); + sb.Append(String.Format("Base cmp object: {0} obj. Base out object: {1} obj", baseCmpObject, baseOutObject + )); + foreach (CompareTool.ObjectPath.LocalPathItem pathItem in path) { + sb.Append("\n"); + sb.Append(pathItem.ToString()); + } + return sb.ToString(); + } + + public override int GetHashCode() { + int hashCode = (baseCmpObject != null ? baseCmpObject.GetHashCode() : 0) * 31 + (baseOutObject != null ? baseOutObject + .GetHashCode() : 0); + foreach (CompareTool.ObjectPath.LocalPathItem pathItem in path) { + hashCode *= 31; + hashCode += pathItem.GetHashCode(); + } + return hashCode; + } + + public override bool Equals(Object obj) { + return obj is CompareTool.ObjectPath && baseCmpObject.Equals(((CompareTool.ObjectPath)obj).baseCmpObject) + && baseOutObject.Equals(((CompareTool.ObjectPath)obj).baseOutObject) && System.Linq.Enumerable.SequenceEqual + (path, ((CompareTool.ObjectPath)obj).path); + } + + protected internal virtual Object Clone() { + return new CompareTool.ObjectPath(baseCmpObject, baseOutObject, (Stack)path.Clone(), (Stack)indirects.Clone()); + } + + /// + /// An item in the indirect path (see + /// + /// . It encapsulates two corresponding objects from the two + /// comparing documents that were met to get to the path base objects during comparing process. + /// + public class IndirectPathItem { + private PdfIndirectReference cmpObject; + + private PdfIndirectReference outObject; + + /// Creates IndirectPathItem instance for two corresponding objects from two comparing documents. + /// an object from the cmp document. + /// an object from the out document. + public IndirectPathItem(ObjectPath _enclosing, PdfIndirectReference cmpObject, PdfIndirectReference outObject + ) { + this._enclosing = _enclosing; + this.cmpObject = cmpObject; + this.outObject = outObject; + } + + /// an object from the cmp object that was met to get to the path base objects during comparing process. + /// + public virtual PdfIndirectReference GetCmpObject() { + return this.cmpObject; + } + + /// an object from the out object that was met to get to the path base objects during comparing process. + /// + public virtual PdfIndirectReference GetOutObject() { + return this.outObject; + } + + public override int GetHashCode() { + return this.cmpObject.GetHashCode() * 31 + this.outObject.GetHashCode(); + } + + public override bool Equals(Object obj) { + return (obj is CompareTool.ObjectPath.IndirectPathItem && this.cmpObject.Equals(((CompareTool.ObjectPath.IndirectPathItem + )obj).cmpObject) && this.outObject.Equals(((CompareTool.ObjectPath.IndirectPathItem)obj).outObject)); + } + + private readonly ObjectPath _enclosing; + } + + /// + /// An abstract class for the items in the direct path (see + /// + /// . + /// + public abstract class LocalPathItem { + /// Creates an xml node that describes this direct path item. + /// xml document, to which this xml node will be added. + /// an xml node describing direct path item. + protected internal abstract XmlElement ToXmlNode(XmlDocument document); + } + + /// + /// Direct path item (see + /// + /// , which describes transition to the + /// + /// entry which value is now a currently comparing direct object. + /// + public class DictPathItem : CompareTool.ObjectPath.LocalPathItem { + internal PdfName key; + + /// + /// Creates an instance of the + /// + /// . + /// + /// + /// the key which defines to which entry of the + /// + /// the transition was performed. + /// + public DictPathItem(PdfName key) { + this.key = key; + } + + public override String ToString() { + return "Dict key: " + key; + } + + public override int GetHashCode() { + return key.GetHashCode(); + } + + public override bool Equals(Object obj) { + return obj is CompareTool.ObjectPath.DictPathItem && key.Equals(((CompareTool.ObjectPath.DictPathItem)obj) + .key); + } + + protected internal override XmlElement ToXmlNode(XmlDocument document) { XmlElement element = document.CreateElement("dictKey"); - element.AppendChild(document.CreateTextNode(this.key.ToString())); - return element; - } - - public virtual PdfName GetKey() - { - return this.key; - } - - private readonly ObjectPath _enclosing; - } - - public class ArrayPathItem : CompareTool.ObjectPath.LocalPathItem - { - internal int index; - - public ArrayPathItem(int index) - { - this.index = index; - } - - public override String ToString() - { - return "Array index: " + this.index.ToString(); - } - - public override int GetHashCode() - { - return this.index; - } - - public override bool Equals(Object obj) - { - return obj is CompareTool.ObjectPath.ArrayPathItem && this.index == ((CompareTool.ObjectPath.ArrayPathItem - )obj).index; - } - - protected internal override XmlElement ToXmlNode(XmlDocument document) - { + element.AppendChild(document.CreateTextNode(key.ToString())); + return element; + } + + /// + /// The key which defines to which entry of the + /// + /// the transition was performed. + /// See + /// + /// for more info. + /// + /// + /// a + /// + /// which is the key which defines to which entry of the dictionary + /// the transition was performed. + /// + public virtual PdfName GetKey() { + return key; + } + } + + /// + /// Direct path item (see + /// + /// , which describes transition to the + /// + /// element which is now a currently comparing direct object. + /// + public class ArrayPathItem : CompareTool.ObjectPath.LocalPathItem { + internal int index; + + /// + /// Creates an instance of the + /// + /// . + /// + /// + /// the index which defines element of the + /// + /// to which + /// the transition was performed. + /// + public ArrayPathItem(int index) { + this.index = index; + } + + public override String ToString() { + return "Array index: " + index.ToString(); + } + + public override int GetHashCode() { + return index; + } + + public override bool Equals(Object obj) { + return obj is CompareTool.ObjectPath.ArrayPathItem && index == ((CompareTool.ObjectPath.ArrayPathItem)obj) + .index; + } + + protected internal override XmlElement ToXmlNode(XmlDocument document) { XmlElement element = document.CreateElement("arrayIndex"); - element.AppendChild(document.CreateTextNode(this.index.ToString())); - return element; - } - - public virtual int GetIndex() - { - return this.index; - } - } - - public class OffsetPathItem : CompareTool.ObjectPath.LocalPathItem - { - internal int offset; - - public OffsetPathItem(int offset) - { - this.offset = offset; - } - - public virtual int GetOffset() - { - return this.offset; - } - - public override String ToString() - { - return "Offset: " + this.offset.ToString(); - } - - public override int GetHashCode() - { - return this.offset; - } - - public override bool Equals(Object obj) - { - return obj is CompareTool.ObjectPath.OffsetPathItem && this.offset == ((CompareTool.ObjectPath.OffsetPathItem - )obj).offset; - } - - protected internal override XmlElement ToXmlNode(XmlDocument document) - { + element.AppendChild(document.CreateTextNode(index.ToString())); + return element; + } + + /// + /// The index which defines element of the + /// + /// to which the transition was performed. + /// See + /// + /// for more info. + /// + /// the index which defines element of the array to which the transition was performed + public virtual int GetIndex() { + return index; + } + } + + /// + /// Direct path item (see + /// + /// , which describes transition to the + /// specific position in + /// + /// . + /// + public class OffsetPathItem : CompareTool.ObjectPath.LocalPathItem { + internal int offset; + + /// + /// Creates an instance of the + /// + /// . + /// + /// + /// bytes offset to the specific position in + /// + /// . + /// + public OffsetPathItem(int offset) { + this.offset = offset; + } + + /// + /// The bytes offset of the stream which defines specific position in the + /// + /// , to which transition + /// was performed. + /// + /// an integer defining bytes offset to the specific position in stream. + public virtual int GetOffset() { + return offset; + } + + public override String ToString() { + return "Offset: " + offset.ToString(); + } + + public override int GetHashCode() { + return offset; + } + + public override bool Equals(Object obj) { + return obj is CompareTool.ObjectPath.OffsetPathItem && offset == ((CompareTool.ObjectPath.OffsetPathItem)obj + ).offset; + } + + protected internal override XmlElement ToXmlNode(XmlDocument document) { XmlElement element = document.CreateElement("offset"); - element.AppendChild(document.CreateTextNode(this.offset.ToString())); - return element; - } - } - } - - private class TrailerPath : CompareTool.ObjectPath - { - private PdfDocument outDocument; - - private PdfDocument cmpDocument; - - public TrailerPath(PdfDocument cmpDoc, PdfDocument outDoc - ) - { - this.outDocument = outDoc; - this.cmpDocument = cmpDoc; - } - - public TrailerPath(PdfDocument cmpDoc, PdfDocument outDoc - , Stack path) - { - this.outDocument = outDoc; - this.cmpDocument = cmpDoc; - this.path = path; - } - - public override XmlElement ToXmlNode(XmlDocument document) - { + element.AppendChild(document.CreateTextNode(offset.ToString())); + return element; + } + } + } + + private class TrailerPath : CompareTool.ObjectPath { + private PdfDocument outDocument; + + private PdfDocument cmpDocument; + + public TrailerPath(PdfDocument cmpDoc, PdfDocument outDoc) { + outDocument = outDoc; + cmpDocument = cmpDoc; + } + + public TrailerPath(PdfDocument cmpDoc, PdfDocument outDoc, Stack path + ) { + this.outDocument = outDoc; + this.cmpDocument = cmpDoc; + this.path = path; + } + + public override XmlElement ToXmlNode(XmlDocument document) { XmlElement element = document.CreateElement("path"); XmlElement baseNode = document.CreateElement("base"); - baseNode.SetAttribute("cmp", "trailer"); - baseNode.SetAttribute("out", "trailer"); - element.AppendChild(baseNode); - foreach (CompareTool.ObjectPath.LocalPathItem pathItem in this.path) - { - element.AppendChild(pathItem.ToXmlNode(document)); - } - return element; - } - - public override String ToString() - { - StringBuilder sb = new StringBuilder(); - sb.Append("Base cmp object: trailer. Base out object: trailer"); - foreach (CompareTool.ObjectPath.LocalPathItem pathItem in this.path) - { - sb.Append("\n"); - sb.Append(pathItem.ToString()); - } - return sb.ToString(); - } - - public override int GetHashCode() - { - int hashCode = this.outDocument.GetHashCode() * 31 + this.cmpDocument.GetHashCode - (); - foreach (CompareTool.ObjectPath.LocalPathItem pathItem in this.path) - { - hashCode *= 31; - hashCode += pathItem.GetHashCode(); - } - return hashCode; - } - - public override bool Equals(Object obj) - { - return obj is CompareTool.TrailerPath && this.outDocument.Equals(((CompareTool.TrailerPath - )obj).outDocument) && this.cmpDocument.Equals(((CompareTool.TrailerPath)obj).cmpDocument - ) && this.path.Equals(((CompareTool.ObjectPath)obj).path); - } - - protected internal override Object Clone() - { - Stack clonedPath = new Stack(); - foreach (LocalPathItem item in path) { - clonedPath.Push(item); - } - return new CompareTool.TrailerPath(this.cmpDocument, this.outDocument, clonedPath); - } - } - } + baseNode.SetAttribute("cmp", "trailer"); + baseNode.SetAttribute("out", "trailer"); + element.AppendChild(baseNode); + foreach (CompareTool.ObjectPath.LocalPathItem pathItem in path) { + element.AppendChild(pathItem.ToXmlNode(document)); + } + return element; + } + + public override String ToString() { + StringBuilder sb = new StringBuilder(); + sb.Append("Base cmp object: trailer. Base out object: trailer"); + foreach (CompareTool.ObjectPath.LocalPathItem pathItem in path) { + sb.Append("\n"); + sb.Append(pathItem.ToString()); + } + return sb.ToString(); + } + + public override int GetHashCode() { + int hashCode = outDocument.GetHashCode() * 31 + cmpDocument.GetHashCode(); + foreach (CompareTool.ObjectPath.LocalPathItem pathItem in path) { + hashCode *= 31; + hashCode += pathItem.GetHashCode(); + } + return hashCode; + } + + public override bool Equals(Object obj) { + return obj is CompareTool.TrailerPath && outDocument.Equals(((CompareTool.TrailerPath)obj).outDocument) && + cmpDocument.Equals(((CompareTool.TrailerPath)obj).cmpDocument) && System.Linq.Enumerable.SequenceEqual + (path, ((CompareTool.ObjectPath)obj).path); + } + + protected internal override Object Clone() { + return new CompareTool.TrailerPath(cmpDocument, outDocument, (Stack) + path.Clone()); + } + } + } } diff --git a/itext/itext.kernel/itext/kernel/utils/PageRange.cs b/itext/itext.kernel/itext/kernel/utils/PageRange.cs index 949f7dea2b..0601472a31 100644 --- a/itext/itext.kernel/itext/kernel/utils/PageRange.cs +++ b/itext/itext.kernel/itext/kernel/utils/PageRange.cs @@ -46,16 +46,29 @@ source product. using System.Text.RegularExpressions; namespace iText.Kernel.Utils { + /// + /// Class representing a page range, for instance a page range can contain + /// pages 5, then pages 10 through 15, then page 18, then page 21 and so on. + /// public class PageRange { private IList sequenceStarts = new List(); private IList sequenceEnds = new List(); + /// + /// Constructs an empty + /// + /// instance. + /// public PageRange() { } - /// You can call specify the page range in a string form, for example: "1-12, 15, 45-66". - /// the page range. + /// + /// Constructs a + /// + /// instance from a range in a string form, for example: "1-12, 15, 45-66". + /// + /// the page range public PageRange(String pageRange) { pageRange = iText.IO.Util.StringUtil.ReplaceAll(pageRange, "\\s+", ""); Regex sequencePattern = iText.IO.Util.StringUtil.RegexCompile("(\\d+)-(\\d+)"); @@ -76,18 +89,27 @@ public PageRange(String pageRange) { } } + /// Adds a page sequence to the range. + /// the starting page number of the sequence + /// the finishing page number of the sequnce + /// this range, already modified public virtual iText.Kernel.Utils.PageRange AddPageSequence(int startPageNumber, int endPageNumber) { sequenceStarts.Add(startPageNumber); sequenceEnds.Add(endPageNumber); return this; } + /// Adds a single page to the range. + /// the page number to add + /// this range, already modified public virtual iText.Kernel.Utils.PageRange AddSinglePage(int pageNumber) { sequenceStarts.Add(pageNumber); sequenceEnds.Add(pageNumber); return this; } + /// Gets the list if pages that have been added to the range so far. + /// the list containing page numbers added to the range public virtual IList GetAllPages() { IList allPages = new List(); for (int ind = 0; ind < sequenceStarts.Count; ind++) { @@ -98,6 +120,9 @@ public virtual IList GetAllPages() { return allPages; } + /// Checks if a given page is present in the range built so far. + /// the page number to check + /// true if the page is present in this range, false otherwise public virtual bool IsPageInRange(int pageNumber) { for (int ind = 0; ind < sequenceStarts.Count; ind++) { if (sequenceStarts[ind] <= pageNumber && pageNumber <= sequenceEnds[ind]) { @@ -107,6 +132,7 @@ public virtual bool IsPageInRange(int pageNumber) { return false; } + /// public override bool Equals(Object obj) { if (!(obj is iText.Kernel.Utils.PageRange)) { return false; @@ -115,6 +141,7 @@ public override bool Equals(Object obj) { return sequenceStarts.Equals(other.sequenceStarts) && sequenceEnds.Equals(other.sequenceEnds); } + /// public override int GetHashCode() { return sequenceStarts.GetHashCode() * 31 + sequenceEnds.GetHashCode(); } diff --git a/itext/itext.kernel/itext/kernel/utils/PdfResourceCounter.cs b/itext/itext.kernel/itext/kernel/utils/PdfResourceCounter.cs index f7c7ef0fdc..8ec1e82c4f 100644 --- a/itext/itext.kernel/itext/kernel/utils/PdfResourceCounter.cs +++ b/itext/itext.kernel/itext/kernel/utils/PdfResourceCounter.cs @@ -131,7 +131,6 @@ public virtual IDictionary GetResources() { ///
    /// The resources that can be excluded when counting the bytes. /// The number of bytes needed for an object. - /// public virtual long GetLength(IDictionary res) { long length = 0; foreach (int @ref in resources.Keys) { @@ -140,7 +139,7 @@ public virtual long GetLength(IDictionary res) { } PdfOutputStream os = new PdfOutputStream(new IdelOutputStream()); os.Write(resources.Get(@ref).Clone()); - length += os.GetCurrentPos() - 1; + length += os.GetCurrentPos(); } return length; } diff --git a/itext/itext.kernel/itext/kernel/utils/PdfSplitter.cs b/itext/itext.kernel/itext/kernel/utils/PdfSplitter.cs index 7168b6f821..e7ac621b8d 100644 --- a/itext/itext.kernel/itext/kernel/utils/PdfSplitter.cs +++ b/itext/itext.kernel/itext/kernel/utils/PdfSplitter.cs @@ -116,7 +116,6 @@ public virtual IList SplitBySize(long size) { /// the event listener which is called when another document is ready. /// You can close this document in this listener, for instance. /// - /// public virtual void SplitByPageNumbers(IList pageNumbers, PdfSplitter.IDocumentReadyListener documentReady ) { int currentPageNumber = 1; @@ -139,15 +138,14 @@ public virtual void SplitByPageNumbers(IList pageNumbers, PdfSplitter.IDocu /// If the first element is not 1, then 1 is implied (i.e. the first split document will start from page 1 in any case). /// /// the list of resultant documents. By warned that they are not closed. - /// public virtual IList SplitByPageNumbers(IList pageNumbers) { IList splitDocuments = new List(); - SplitByPageNumbers(pageNumbers, new _IDocumentReadyListener_157(splitDocuments)); + SplitByPageNumbers(pageNumbers, new _IDocumentReadyListener_155(splitDocuments)); return splitDocuments; } - private sealed class _IDocumentReadyListener_157 : PdfSplitter.IDocumentReadyListener { - public _IDocumentReadyListener_157(IList splitDocuments) { + private sealed class _IDocumentReadyListener_155 : PdfSplitter.IDocumentReadyListener { + public _IDocumentReadyListener_155(IList splitDocuments) { this.splitDocuments = splitDocuments; } @@ -164,7 +162,6 @@ public void DocumentReady(PdfDocument pdfDocument, PageRange pageRange) { /// the event listener which is called when another document is ready. /// You can close this document in this listener, for instance. /// - /// public virtual void SplitByPageCount(int pageCount, PdfSplitter.IDocumentReadyListener documentReady) { for (int startPage = 1; startPage <= pdfDocument.GetNumberOfPages(); startPage += pageCount) { int endPage = Math.Min(startPage + pageCount - 1, pdfDocument.GetNumberOfPages()); @@ -178,15 +175,14 @@ public virtual void SplitByPageCount(int pageCount, PdfSplitter.IDocumentReadyLi /// Splits a document into smaller documents with no more than @pageCount pages each. /// the biggest possible number of pages in a split document. /// the list of resultant documents. By warned that they are not closed. - /// public virtual IList SplitByPageCount(int pageCount) { IList splitDocuments = new List(); - SplitByPageCount(pageCount, new _IDocumentReadyListener_196(splitDocuments)); + SplitByPageCount(pageCount, new _IDocumentReadyListener_192(splitDocuments)); return splitDocuments; } - private sealed class _IDocumentReadyListener_196 : PdfSplitter.IDocumentReadyListener { - public _IDocumentReadyListener_196(IList splitDocuments) { + private sealed class _IDocumentReadyListener_192 : PdfSplitter.IDocumentReadyListener { + public _IDocumentReadyListener_192(IList splitDocuments) { this.splitDocuments = splitDocuments; } @@ -203,7 +199,6 @@ public void DocumentReady(PdfDocument pdfDocument, PageRange pageRange) { /// the list of the resultant documents for each of the specified page range. /// Be warned that these documents are not closed. ///
    - /// public virtual IList ExtractPageRanges(IList pageRanges) { IList splitDocuments = new List(); foreach (PageRange currentPageRange in pageRanges) { @@ -220,7 +215,6 @@ public virtual IList ExtractPageRanges(IList pageRanges) /// the resultant document containing the pages specified by the provided page range. /// Be warned that this document is not closed. /// - /// public virtual PdfDocument ExtractPageRange(PageRange pageRange) { return ExtractPageRanges(JavaCollectionsUtil.SingletonList(pageRange))[0]; } @@ -263,7 +257,6 @@ public interface IDocumentReadyListener { /// and places the entire hierarchy in a separate document ( outlines and pages ) . /// /// list of outline titles . - /// public virtual IList SplitByOutlines(IList outlineTitles) { if (outlineTitles == null || outlineTitles.Count == 0) { return JavaCollectionsUtil.EmptyList(); @@ -331,7 +324,6 @@ private PdfPage GetPageByOutline(int fromPage, PdfOutline outline) { /// the next element in the entire hierarchy /// - /// private PdfOutline GetAbsoluteTreeNextOutline(PdfOutline outline) { PdfObject nextPdfObject = outline.GetContent().Get(PdfName.Next); PdfOutline nextPdfOutline = null; diff --git a/itext/itext.kernel/itext/kernel/utils/TaggedPdfReaderTool.cs b/itext/itext.kernel/itext/kernel/utils/TaggedPdfReaderTool.cs index d0bf0576c6..848e56be00 100644 --- a/itext/itext.kernel/itext/kernel/utils/TaggedPdfReaderTool.cs +++ b/itext/itext.kernel/itext/kernel/utils/TaggedPdfReaderTool.cs @@ -64,16 +64,37 @@ public class TaggedPdfReaderTool { protected internal IDictionary> parsedTags = new Dictionary>(); + /// + /// Constructs a + /// + /// via a given + /// + /// . + /// + /// the document to read tag structure from public TaggedPdfReaderTool(PdfDocument document) { - // key - page dictionary; value pairs of mcid and text in them + // key - page dictionary; value - a mapping of mcids to text in them this.document = document; } + /// Checks if a character value should be escaped/unescaped. + /// a character value + /// true if it's OK to escape or unescape this value + public static bool IsValidCharacterValue(int c) { + return (c == 0x9 || c == 0xA || c == 0xD || c >= 0x20 && c <= 0xD7FF || c >= 0xE000 && c <= 0xFFFD || c >= + 0x10000 && c <= 0x10FFFF); + } + + /// Converts the current tag structure into an XML file with default encoding (UTF-8). + /// the output stream to save XML file to /// public virtual void ConvertToXml(Stream os) { ConvertToXml(os, "UTF-8"); } + /// Converts the current tag structure into an XML file with provided encoding. + /// the output stream to save XML file to + /// the charset of the resultant XML file /// public virtual void ConvertToXml(Stream os, String charset) { @out = new StreamWriter(os, System.Text.Encoding.GetEncoding(charset)); @@ -94,12 +115,14 @@ public virtual void ConvertToXml(Stream os, String charset) { @out.Close(); } + /// Sets the name of the root tag of the resultant XML file + /// the name of the root tag + /// this object public virtual iText.Kernel.Utils.TaggedPdfReaderTool SetRootTag(String rootTagName) { this.rootTag = rootTagName; return this; } - /// protected internal virtual void InspectKids(IList kids) { if (kids == null) { return; @@ -109,39 +132,42 @@ protected internal virtual void InspectKids(IList kids) { } } - /// protected internal virtual void InspectKid(IPdfStructElem kid) { - if (kid is PdfStructElem) { - PdfStructElem structElemKid = (PdfStructElem)kid; - PdfName s = structElemKid.GetRole(); - String tagN = s.GetValue(); - String tag = FixTagName(tagN); - @out.Write("<"); - @out.Write(tag); - InspectAttributes(structElemKid); - @out.Write(">" + Environment.NewLine); - PdfString alt = (structElemKid).GetAlt(); - if (alt != null) { - @out.Write("" + Environment.NewLine); - } - InspectKids(structElemKid.GetKids()); - @out.Write("" + Environment.NewLine); - } - else { - if (kid is PdfMcr) { - ParseTag((PdfMcr)kid); + try { + if (kid is PdfStructElem) { + PdfStructElem structElemKid = (PdfStructElem)kid; + PdfName s = structElemKid.GetRole(); + String tagN = s.GetValue(); + String tag = FixTagName(tagN); + @out.Write("<"); + @out.Write(tag); + InspectAttributes(structElemKid); + @out.Write(">" + Environment.NewLine); + PdfString alt = (structElemKid).GetAlt(); + if (alt != null) { + @out.Write("" + Environment.NewLine); + } + InspectKids(structElemKid.GetKids()); + @out.Write("" + Environment.NewLine); } else { - @out.Write(" "); + if (kid is PdfMcr) { + ParseTag((PdfMcr)kid); + } + else { + @out.Write(" "); + } } } + catch (System.IO.IOException e) { + throw new iText.IO.IOException(iText.IO.IOException.UnknownIOException, e); + } } - /// protected internal virtual void InspectAttributes(PdfStructElem kid) { PdfObject attrObj = kid.GetAttributes(false); if (attrObj != null) { @@ -152,18 +178,22 @@ protected internal virtual void InspectAttributes(PdfStructElem kid) { else { attrDict = (PdfDictionary)attrObj; } - foreach (KeyValuePair entry in attrDict.EntrySet()) { - @out.Write(' '); - String attrName = entry.Key.GetValue(); - @out.Write(char.ToLower(attrName[0]) + attrName.Substring(1)); - @out.Write("=\""); - @out.Write(entry.Value.ToString()); - @out.Write("\""); + try { + foreach (PdfName key in attrDict.KeySet()) { + @out.Write(' '); + String attrName = key.GetValue(); + @out.Write(char.ToLower(attrName[0]) + attrName.Substring(1)); + @out.Write("=\""); + @out.Write(attrDict.Get(key, false).ToString()); + @out.Write("\""); + } + } + catch (System.IO.IOException e) { + throw new iText.IO.IOException(iText.IO.IOException.UnknownIOException, e); } } } - /// protected internal virtual void ParseTag(PdfMcr kid) { int mcid = kid.GetMcid(); PdfDictionary pageDic = kid.GetPageObject(); @@ -189,7 +219,12 @@ protected internal virtual void ParseTag(PdfMcr kid) { tagContent = subtype.ToString(); } } - @out.Write(EscapeXML(tagContent, true)); + try { + @out.Write(EscapeXML(tagContent, true)); + } + catch (System.IO.IOException e) { + throw new iText.IO.IOException(iText.IO.IOException.UnknownIOException, e); + } } protected internal static String FixTagName(String tag) { @@ -220,13 +255,11 @@ protected internal static String FixTagName(String tag) { /// /// NOTE: copied from itext5 XMLUtils class - ///

    /// Escapes a string with the appropriated XML codes. ///

    /// the string to be escaped /// codes above 127 will always be escaped with &#nn; if true /// the escaped string - /// 5.0.6 protected internal static String EscapeXML(String s, bool onlyASCII) { char[] cc = s.ToCharArray(); int len = cc.Length; @@ -275,14 +308,6 @@ protected internal static String EscapeXML(String s, bool onlyASCII) { return sb.ToString(); } - /// Checks if a character value should be escaped/unescaped. - /// a character value - /// true if it's OK to escape or unescape this value - public static bool IsValidCharacterValue(int c) { - return (c == 0x9 || c == 0xA || c == 0xD || c >= 0x20 && c <= 0xD7FF || c >= 0xE000 && c <= 0xFFFD || c >= - 0x10000 && c <= 0x10FFFF); - } - private class MarkedContentEventListener : IEventListener { private IDictionary contentByMcid = new Dictionary(); diff --git a/itext/itext.kernel/itext/kernel/utils/XmlUtils.cs b/itext/itext.kernel/itext/kernel/utils/XmlUtils.cs new file mode 100644 index 0000000000..8a86d2c477 --- /dev/null +++ b/itext/itext.kernel/itext/kernel/utils/XmlUtils.cs @@ -0,0 +1,90 @@ +/* + This file is part of the iText (R) project. + Copyright (c) 1998-2016 iText Group NV + Authors: Bruno Lowagie, Paulo Soares, et al. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License version 3 + as published by the Free Software Foundation with the addition of the + following permission added to Section 15 as permitted in Section 7(a): + FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY + ITEXT GROUP. ITEXT GROUP DISCLAIMS THE WARRANTY OF NON INFRINGEMENT + OF THIRD PARTY RIGHTS + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Affero General Public License for more details. + You should have received a copy of the GNU Affero General Public License + along with this program; if not, see http://www.gnu.org/licenses or write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA, 02110-1301 USA, or download the license from the following URL: + http://itextpdf.com/terms-of-use/ + + The interactive user interfaces in modified source and object code versions + of this program must display Appropriate Legal Notices, as required under + Section 5 of the GNU Affero General Public License. + + In accordance with Section 7(b) of the GNU Affero General Public License, + a covered work must retain the producer line in every PDF that is created + or manipulated using iText. + + You can be released from the requirements of the license by purchasing + a commercial license. Buying such a license is mandatory as soon as you + develop commercial activities involving the iText software without + disclosing the source code of your own applications. + These activities include: offering paid services to customers as an ASP, + serving PDFs on the fly in a web application, shipping iText with a closed + source product. + + For more information, please contact iText Software Corp. at this + address: sales@itextpdf.com + */ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Xml; +using System.Xml.Linq; + +namespace iText.Kernel.Utils { + class XmlUtils { + public static void WriteXmlDocToStream(XmlDocument xmlReport, Stream stream) { + XmlTextWriter writer = new XmlTextWriter(stream, Encoding.Default); + writer.Formatting = Formatting.Indented; + xmlReport.WriteTo(writer); + writer.Flush(); + } + + public static bool CompareXmls(Stream xml1, Stream xml2) { + XElement el1 = XElement.Load(xml1); + XElement el2 = XElement.Load(xml2); + + return XNode.DeepEquals(Normalize(el1), Normalize(el2)); + } + + public static XmlDocument InitNewXmlDocument() { + return new XmlDocument(); + } + + private static XElement Normalize(XElement element) { + if (element.HasElements) { + return new XElement( + element.Name, + element.Attributes().Where(a => a.Name.Namespace == XNamespace.Xmlns) + .OrderBy(a => a.Name.ToString()), + element.Elements().OrderBy(a => a.Name.ToString()) + .Select(e => Normalize(e))); + } + + if (element.IsEmpty) { + return new XElement(element.Name, element.Attributes() + .OrderBy(a => a.Name.ToString())); + } + + return new XElement(element.Name, element.Attributes() + .OrderBy(a => a.Name.ToString()), element.Value); + } + } +} diff --git a/itext/itext.kernel/itext/kernel/xmp/impl/xpath/XMPPath.cs b/itext/itext.kernel/itext/kernel/xmp/impl/xpath/XMPPath.cs index d83463fcce..f69c09c093 100644 --- a/itext/itext.kernel/itext/kernel/xmp/impl/xpath/XMPPath.cs +++ b/itext/itext.kernel/itext/kernel/xmp/impl/xpath/XMPPath.cs @@ -82,7 +82,7 @@ public virtual int Size() { return segments.Count; } - /// Serializes the normalized XMP-path. + /// Return a single String explaining which certificate was verified, how and why. /// public override String ToString() { StringBuilder result = new StringBuilder(); diff --git a/itext/itext.layout/Properties/AssemblyInfo.cs b/itext/itext.layout/Properties/AssemblyInfo.cs index d045ffc578..f52cef3cfb 100644 --- a/itext/itext.layout/Properties/AssemblyInfo.cs +++ b/itext/itext.layout/Properties/AssemblyInfo.cs @@ -21,5 +21,5 @@ [assembly: Guid("fd0a08a8-0f82-4d6f-a3db-7b8f3f9302b4")] -[assembly: AssemblyVersion("7.0.0.0")] -[assembly: AssemblyFileVersion("7.0.0.0")] +[assembly: AssemblyVersion("7.0.1.0")] +[assembly: AssemblyFileVersion("7.0.1.0")] diff --git a/itext/itext.layout/itext/layout/Canvas.cs b/itext/itext.layout/itext/layout/Canvas.cs index 83bd245d51..69be0cc9fb 100644 --- a/itext/itext.layout/itext/layout/Canvas.cs +++ b/itext/itext.layout/itext/layout/Canvas.cs @@ -159,6 +159,18 @@ public virtual bool IsAutoTaggingEnabled() { return page != null; } + /// + /// Performs an entire recalculation of the element flow on the canvas, + /// taking into account all its current child elements. + /// + /// + /// Performs an entire recalculation of the element flow on the canvas, + /// taking into account all its current child elements. May become very + /// resource-intensive for large documents. + /// Do not use when you have set + /// + /// to true. + /// public virtual void Relayout() { if (immediateFlush) { throw new InvalidOperationException("Operation not supported with immediate flush"); @@ -177,6 +189,23 @@ public virtual void Flush() { rootRenderer.Flush(); } + /// + /// Closes the + /// + /// . Although not completely necessary in all cases, it is still recommended to call this + /// method when you are done working with + /// + /// object, as due to some properties set there might be some + /// 'hanging' elements, which are waiting other elements to be added and processed. + /// + /// tells the + /// + /// that no more elements will be added and it is time to finish processing all the elements. + /// + public override void Close() { + rootRenderer.Close(); + } + protected internal override RootRenderer EnsureRootRendererNotNull() { if (rootRenderer == null) { rootRenderer = new CanvasRenderer(this, immediateFlush); diff --git a/itext/itext.layout/itext/layout/ColumnDocumentRenderer.cs b/itext/itext.layout/itext/layout/ColumnDocumentRenderer.cs index 4287f9bee4..9e9a94eada 100644 --- a/itext/itext.layout/itext/layout/ColumnDocumentRenderer.cs +++ b/itext/itext.layout/itext/layout/ColumnDocumentRenderer.cs @@ -53,11 +53,46 @@ public class ColumnDocumentRenderer : DocumentRenderer { protected internal int nextAreaNumber; + /// Creates a ColumnDocumentRenderer. + /// + /// Creates a ColumnDocumentRenderer. Sets + /// + /// to true. + /// + /// + /// the + /// + /// on which this Renderer will calculate + /// and execute element placements + /// + /// + /// an array of + /// + /// specifying the acceptable + /// positions for elements on a page + /// public ColumnDocumentRenderer(Document document, Rectangle[] columns) : base(document) { this.columns = columns; } + /// + /// Creates a ColumnDocumentRenderer whose elements need not be flushed + /// immediately. + /// + /// + /// the + /// + /// on which this Renderer will calculate + /// and execute element placements + /// + /// whether or not to flush contents as soon as possible + /// + /// an array of + /// + /// specifying the acceptable + /// positions for elements on a page + /// public ColumnDocumentRenderer(Document document, bool immediateFlush, Rectangle[] columns) : base(document, immediateFlush) { this.columns = columns; @@ -75,6 +110,11 @@ protected internal override LayoutArea UpdateCurrentArea(LayoutResult overflowRe )); } + /// + /// Gets the array index of the next area that will be written on after the + /// current one is full (overflowed). + /// + /// the array index of the next area that will be written on public virtual int GetNextAreaNumber() { return nextAreaNumber; } diff --git a/itext/itext.layout/itext/layout/Document.cs b/itext/itext.layout/itext/layout/Document.cs index 83ff062bdf..0887717a63 100644 --- a/itext/itext.layout/itext/layout/Document.cs +++ b/itext/itext.layout/itext/layout/Document.cs @@ -55,6 +55,7 @@ namespace iText.Layout { /// mainly operates high-level operations e.g. setting page size and rotation, /// adding elements, and writing text at specific coordinates. It has no /// knowledge of the actual PDF concepts and syntax. + ///

    /// A /// /// 's rendering behavior can be modified by extending @@ -123,9 +124,9 @@ public Document(PdfDocument pdfDoc, PageSize pageSize, bool immediateFlush) } ///

    Closes the document and associated PdfDocument. - public virtual void Close() { - if (rootRenderer != null && !immediateFlush) { - rootRenderer.Flush(); + public override void Close() { + if (rootRenderer != null) { + rootRenderer.Close(); } pdfDocument.Close(); } @@ -192,6 +193,7 @@ public virtual void Flush() { /// Performs an entire recalculation of the document flow, taking into /// account all its current child elements. May become very /// resource-intensive for large documents. + ///

    /// Do not use when you have set /// /// to true. @@ -216,34 +218,50 @@ protected internal override RootRenderer EnsureRootRendererNotNull() { return rootRenderer; } + ///

    Gets the left margin, measured in points + /// a float containing the left margin value public virtual float GetLeftMargin() { return leftMargin; } + /// Sets the left margin, measured in points + /// a float containing the new left margin value public virtual void SetLeftMargin(float leftMargin) { this.leftMargin = leftMargin; } + /// Gets the right margin, measured in points + /// a float containing the right margin value public virtual float GetRightMargin() { return rightMargin; } + /// Sets the right margin, measured in points + /// a float containing the new right margin value public virtual void SetRightMargin(float rightMargin) { this.rightMargin = rightMargin; } + /// Gets the top margin, measured in points + /// a float containing the top margin value public virtual float GetTopMargin() { return topMargin; } + /// Sets the top margin, measured in points + /// a float containing the new top margin value public virtual void SetTopMargin(float topMargin) { this.topMargin = topMargin; } + /// Gets the bottom margin, measured in points + /// a float containing the bottom margin value public virtual float GetBottomMargin() { return bottomMargin; } + /// Sets the bottom margin, measured in points + /// a float containing the new bottom margin value public virtual void SetBottomMargin(float bottomMargin) { this.bottomMargin = bottomMargin; } @@ -279,11 +297,10 @@ public virtual Rectangle GetPageEffectiveArea(PageSize pageSize) { () - leftMargin - rightMargin, pageSize.GetHeight() - bottomMargin - topMargin); } - /// checks whether a method is invoked at the closed document - /// + /// Checks whether a method is invoked at the closed document protected internal virtual void CheckClosingStatus() { if (GetPdfDocument().IsClosed()) { - throw new PdfException(PdfException.DocumentClosedImpossibleExecuteAction); + throw new PdfException(PdfException.DocumentClosedItIsImpossibleToExecuteAction); } } } diff --git a/itext/itext.layout/itext/layout/LayoutExtensions.cs b/itext/itext.layout/itext/layout/LayoutExtensions.cs index 8238e4b300..ed237bfaed 100644 --- a/itext/itext.layout/itext/layout/LayoutExtensions.cs +++ b/itext/itext.layout/itext/layout/LayoutExtensions.cs @@ -87,6 +87,34 @@ public static void AddAll(this IList list, int index, IList c) { } } + public static bool RemoveAll(this IList list, ICollection c) + { + bool modefied = false; + foreach (T item in c) + { + if (list.Remove(item)) modefied = true; + } + return modefied; + } + + // Removes from this list all of its elements that are not contained in the specified collection. + public static bool RetainAll(this IList list, ICollection c) { + bool modified = false; + int j = 0; + for (int i = 0; i < list.Count; ++i) { + if (c.Contains(list[i])) { + list[j++] = list[i]; + } + } + if (j != list.Count) { + modified = true; + for (int i = list.Count - 1; i >= j; --i) { + list.RemoveAt(i); + } + } + return modified; + } + public static void Add(this IList list, int index, T elem) { list.Insert(index, elem); } @@ -137,5 +165,13 @@ public static List SubList(this IList list, int fromIndex, int toIndex) public static String[] Split(this String str, String regex) { return str.Split(regex.ToCharArray()); } + + public static T JRemoveFirst(this LinkedList list) + { + T value = list.First.Value; + list.RemoveFirst(); + + return value; + } } } diff --git a/itext/itext.layout/itext/layout/RootElement.cs b/itext/itext.layout/itext/layout/RootElement.cs index 3c23a3f2ad..e9e885babf 100644 --- a/itext/itext.layout/itext/layout/RootElement.cs +++ b/itext/itext.layout/itext/layout/RootElement.cs @@ -54,7 +54,7 @@ source product. namespace iText.Layout { /// A generic abstract root element for a PDF layout object hierarchy. /// - public abstract class RootElement : ElementPropertyContainer + public abstract class RootElement : ElementPropertyContainer, IDisposable where T : IPropertyContainer { protected internal bool immediateFlush = true; @@ -277,32 +277,31 @@ public virtual T ShowTextAligned(Paragraph p, float x, float y, int pageNumber, } div.SetProperty(Property.ROTATION_POINT_X, x); div.SetProperty(Property.ROTATION_POINT_Y, y); - float divWidth = AbstractRenderer.INF; - float divHeight = AbstractRenderer.INF; + float divSize = 5e3f; float divX = x; float divY = y; if (textAlign == TextAlignment.CENTER) { - divX = x - divWidth / 2; + divX = x - divSize / 2; p.SetHorizontalAlignment(HorizontalAlignment.CENTER); } else { if (textAlign == TextAlignment.RIGHT) { - divX = x - divWidth; + divX = x - divSize; p.SetHorizontalAlignment(HorizontalAlignment.RIGHT); } } if (vertAlign == VerticalAlignment.MIDDLE) { - divY = y - divHeight / 2; + divY = y - divSize / 2; } else { if (vertAlign == VerticalAlignment.TOP) { - divY = y - divHeight; + divY = y - divSize; } } if (pageNumber == 0) { pageNumber = 1; } - div.SetFixedPosition(pageNumber, divX, divY, divWidth).SetHeight(divHeight); + div.SetFixedPosition(pageNumber, divX, divY, divSize).SetHeight(divSize); if (p.GetProperty(Property.LEADING) == null) { p.SetMultipliedLeading(1); } @@ -313,5 +312,11 @@ public virtual T ShowTextAligned(Paragraph p, float x, float y, int pageNumber, } protected internal abstract RootRenderer EnsureRootRendererNotNull(); + + public abstract void Close(); + + void System.IDisposable.Dispose() { + Close(); + } } } diff --git a/itext/itext.layout/itext/layout/borders/Border.cs b/itext/itext.layout/itext/layout/borders/Border.cs index e02af6726c..2866b69d94 100644 --- a/itext/itext.layout/itext/layout/borders/Border.cs +++ b/itext/itext.layout/itext/layout/borders/Border.cs @@ -46,39 +46,83 @@ source product. using iText.Kernel.Pdf.Canvas; namespace iText.Layout.Borders { + /// Represents a border. public abstract class Border { + /// The null Border, i.e. + /// The null Border, i.e. the presence of such border is equivalent to the absence of the border public static readonly iText.Layout.Borders.Border NO_BORDER = null; + /// The solid border. + /// public const int SOLID = 0; + /// The dashed border. + /// public const int DASHED = 1; + /// The dotted border. + /// public const int DOTTED = 2; + /// The double border. + /// public const int DOUBLE = 3; + /// The round-dots border. + /// public const int ROUND_DOTS = 4; + /// The 3D groove border. + /// public const int _3D_GROOVE = 5; + /// The 3D inset border. + /// public const int _3D_INSET = 6; + /// The 3D outset border. + /// public const int _3D_OUTSET = 7; + /// The 3D ridge border. + /// public const int _3D_RIDGE = 8; + /// The color of the border. + /// protected internal Color color; + /// The width of the border. protected internal float width; + /// The type of the border. protected internal int type; + /// The hash value for the border. private int hash; + /// + /// Creates a + /// border + /// with the given width. + /// The + /// color + /// to be set by default is black + /// + /// the width which the border should have protected internal Border(float width) : this(Color.BLACK, width) { } + /// + /// Creates a + /// border + /// with given width and + /// color + /// . + /// + /// the color which the border should have + /// the width which the border should have protected internal Border(Color color, float width) { this.color = color; this.width = width; @@ -116,18 +160,66 @@ protected internal Border(Color color, float width) { public abstract void Draw(PdfCanvas canvas, float x1, float y1, float x2, float y2, float borderWidthBefore , float borderWidthAfter); + /// Draws the border of a cell. + /// PdfCanvas to be written to + /// x coordinate of the beginning point of the element side, that should be bordered + /// y coordinate of the beginning point of the element side, that should be bordered + /// x coordinate of the ending point of the element side, that should be bordered + /// y coordinate of the ending point of the element side, that should be bordered public abstract void DrawCellBorder(PdfCanvas canvas, float x1, float y1, float x2, float y2); + /// + /// Returns the type of the + /// border + /// public abstract int GetBorderType(); + /// + /// Gets the + /// color + /// of the + /// border + /// + /// + /// the + /// color + /// public virtual Color GetColor() { return color; } + /// + /// Gets the width of the + /// border + /// + /// the width public virtual float GetWidth() { return width; } + /// + /// Sets the + /// color + /// of the + /// border + /// + public virtual void SetColor(Color color) { + this.color = color; + } + + /// + /// Sets the width of the + /// border + /// + public virtual void SetWidth(float width) { + this.width = width; + } + + /// Indicates whether the border is equal to the given border. + /// + /// Indicates whether the border is equal to the given border. + /// The border type, width and color are considered during the comparison. + /// public override bool Equals(Object anObject) { if (this == anObject) { return true; @@ -145,6 +237,7 @@ public override bool Equals(Object anObject) { return true; } + /// public override int GetHashCode() { int h = hash; if (h == 0) { @@ -154,6 +247,22 @@ public override int GetHashCode() { return h; } + /// + /// Returns the + /// side + /// corresponded to the line between two points. + /// Notice that we consider the rectangle traversal to be clockwise. + /// If the rectangle sides are not parallel to the corresponding page sides + /// the result is Side.NONE + /// + /// the abscissa of the left-bottom point + /// the ordinate of the left-bottom point + /// the abscissa of the right-top point + /// the ordinate of the right-top point + /// + /// the corresponded + /// side + /// protected internal virtual Border.Side GetBorderSide(float x1, float y1, float x2, float y2) { bool isLeft = false; bool isRight = false; @@ -188,6 +297,12 @@ protected internal virtual Border.Side GetBorderSide(float x1, float y1, float x return Border.Side.NONE; } + /// Enumerates the different sides of the rectangle. + /// + /// Enumerates the different sides of the rectangle. + /// The rectangle sides are expected to be parallel to corresponding page sides + /// Otherwise the result is Side.NONE + /// protected internal enum Side { NONE, TOP, diff --git a/itext/itext.layout/itext/layout/borders/Border3D.cs b/itext/itext.layout/itext/layout/borders/Border3D.cs index 313ed6dfce..debf40a042 100644 --- a/itext/itext.layout/itext/layout/borders/Border3D.cs +++ b/itext/itext.layout/itext/layout/borders/Border3D.cs @@ -47,6 +47,10 @@ source product. namespace iText.Layout.Borders { /// Represents a border that is displayed using a 3D effect. public abstract class Border3D : Border { + /// + /// Predefined gray + /// RGB-color + /// private static readonly DeviceRgb GRAY = new DeviceRgb(212, 208, 200); /// Creates a Border3D instance with the specified width. @@ -77,6 +81,7 @@ protected internal Border3D(DeviceGray color, float width) : base(color, width) { } + /// public override void Draw(PdfCanvas canvas, float x1, float y1, float x2, float y2, float borderWidthBefore , float borderWidthAfter) { float x3 = 0; @@ -159,11 +164,17 @@ public override void Draw(PdfCanvas canvas, float x1, float y1, float x2, float canvas.MoveTo(x1, y1).LineTo(x2, y2).LineTo(x3, y3).LineTo(x4, y4).LineTo(x1, y1).Fill(); } + /// public override void DrawCellBorder(PdfCanvas canvas, float x1, float y1, float x2, float y2) { canvas.SaveState().SetStrokeColor(color).SetLineWidth(width).MoveTo(x1, y1).LineTo(x2, y2).Stroke().RestoreState (); } + /// + /// Makes the + /// color of the border + /// darker and returns the result + /// protected internal virtual Color GetDarkerColor() { if (color is DeviceRgb) { return DeviceRgb.MakeDarker((DeviceRgb)color); @@ -181,8 +192,28 @@ protected internal virtual Color GetDarkerColor() { return color; } + /// + /// Sets the fill color for the inner half of + /// 3D Border + /// + /// PdfCanvas the color will be applied on + /// + /// the + /// side + /// the color will be applied on + /// protected internal abstract void SetInnerHalfColor(PdfCanvas canvas, Border.Side side); + /// + /// Sets the fill color for the outer half of + /// 3D Border + /// + /// PdfCanvas the color will be applied on + /// + /// the + /// side + /// the color will be applied on + /// protected internal abstract void SetOuterHalfColor(PdfCanvas canvas, Border.Side side); } } diff --git a/itext/itext.layout/itext/layout/borders/DashedBorder.cs b/itext/itext.layout/itext/layout/borders/DashedBorder.cs index df6bf77800..ba68fa660d 100644 --- a/itext/itext.layout/itext/layout/borders/DashedBorder.cs +++ b/itext/itext.layout/itext/layout/borders/DashedBorder.cs @@ -48,8 +48,10 @@ source product. namespace iText.Layout.Borders { /// Draws a border with dashes around the element it's been set to. public class DashedBorder : Border { + /// The modifier to be applied on the width to have the dash size private const float DASH_MODIFIER = 5f; + /// The modifier to be applied on the width to have the initial gap size private const float GAP_MODIFIER = 3.5f; /// Creates a DashedBorder with the specified width and sets the color to black. @@ -65,10 +67,12 @@ public DashedBorder(Color color, float width) : base(color, width) { } + /// public override int GetBorderType() { return Border.DASHED; } + /// public override void Draw(PdfCanvas canvas, float x1, float y1, float x2, float y2, float borderWidthBefore , float borderWidthAfter) { float initialGap = width * GAP_MODIFIER; @@ -112,6 +116,7 @@ public override void Draw(PdfCanvas canvas, float x1, float y1, float x2, float canvas.SetLineDash(dash, adjustedGap, dash + adjustedGap / 2).MoveTo(x1, y1).LineTo(x2, y2).Stroke(); } + /// public override void DrawCellBorder(PdfCanvas canvas, float x1, float y1, float x2, float y2) { float initialGap = width * GAP_MODIFIER; float dash = width * DASH_MODIFIER; @@ -126,6 +131,14 @@ public override void DrawCellBorder(PdfCanvas canvas, float x1, float y1, float (width).MoveTo(x1, y1).LineTo(x2, y2).Stroke().RestoreState(); } + /// Adjusts the size of the gap between dots + /// + /// the + /// border + /// length + /// + /// the initial size of the gap + /// the adjusted size of the gap protected internal virtual float GetDotsGap(double distance, float initialGap) { double gapsNum = System.Math.Ceiling(distance / initialGap); return (float)(distance / gapsNum); diff --git a/itext/itext.layout/itext/layout/borders/DottedBorder.cs b/itext/itext.layout/itext/layout/borders/DottedBorder.cs index 90e8657894..6a9d7fdcfb 100644 --- a/itext/itext.layout/itext/layout/borders/DottedBorder.cs +++ b/itext/itext.layout/itext/layout/borders/DottedBorder.cs @@ -54,6 +54,7 @@ namespace iText.Layout.Borders { /// . /// public class DottedBorder : Border { + /// The modifier to be applied on the width to have the initial gap size private const float GAP_MODIFIER = 1.5f; /// Creates a DottedBorder instance with the specified width. @@ -71,10 +72,12 @@ public DottedBorder(Color color, float width) : base(color, width) { } + /// public override int GetBorderType() { return Border.DOTTED; } + /// public override void Draw(PdfCanvas canvas, float x1, float y1, float x2, float y2, float borderWidthBefore , float borderWidthAfter) { float initialGap = width * GAP_MODIFIER; @@ -117,6 +120,7 @@ public override void Draw(PdfCanvas canvas, float x1, float y1, float x2, float canvas.SetLineDash(width, adjustedGap, width + adjustedGap / 2).MoveTo(x1, y1).LineTo(x2, y2).Stroke(); } + /// public override void DrawCellBorder(PdfCanvas canvas, float x1, float y1, float x2, float y2) { float initialGap = width * GAP_MODIFIER; float dx = x2 - x1; @@ -130,6 +134,14 @@ public override void DrawCellBorder(PdfCanvas canvas, float x1, float y1, float / 2).MoveTo(x1, y1).LineTo(x2, y2).Stroke().RestoreState(); } + /// Adjusts the size of the gap between dots + /// + /// the + /// border + /// length + /// + /// the initial size of the gap + /// the adjusted size of the gap protected internal virtual float GetDotsGap(double distance, float initialGap) { double gapsNum = System.Math.Ceiling(distance / initialGap); return (float)(distance / gapsNum); diff --git a/itext/itext.layout/itext/layout/borders/DoubleBorder.cs b/itext/itext.layout/itext/layout/borders/DoubleBorder.cs index 457f777078..22fe8cb5d3 100644 --- a/itext/itext.layout/itext/layout/borders/DoubleBorder.cs +++ b/itext/itext.layout/itext/layout/borders/DoubleBorder.cs @@ -77,10 +77,12 @@ public DoubleBorder(Color color, float width) : base(color, width) { } + /// public override int GetBorderType() { return Border.DOUBLE; } + /// public override void Draw(PdfCanvas canvas, float x1, float y1, float x2, float y2, float borderWidthBefore , float borderWidthAfter) { float x3 = 0; @@ -178,6 +180,7 @@ public override void Draw(PdfCanvas canvas, float x1, float y1, float x2, float canvas.MoveTo(x1, y1).LineTo(x2, y2).LineTo(x3, y3).LineTo(x4, y4).LineTo(x1, y1).Fill(); } + /// public override void DrawCellBorder(PdfCanvas canvas, float x1, float y1, float x2, float y2) { float thirdOfWidth = width / 3; Border.Side borderSide = GetBorderSide(x1, y1, x2, y2); diff --git a/itext/itext.layout/itext/layout/borders/GrooveBorder.cs b/itext/itext.layout/itext/layout/borders/GrooveBorder.cs index 49db04ef55..9b2eea44ce 100644 --- a/itext/itext.layout/itext/layout/borders/GrooveBorder.cs +++ b/itext/itext.layout/itext/layout/borders/GrooveBorder.cs @@ -46,26 +46,68 @@ source product. namespace iText.Layout.Borders { public class GrooveBorder : Border3D { + /// Creates a GrooveBorder instance with the specified width. + /// + /// Creates a GrooveBorder instance with the specified width. The color is set to the default: + /// gray + /// . + /// + /// width of the border public GrooveBorder(float width) : base(width) { } + /// + /// Creates a GrooveBorder instance with the specified width and the + /// rgb color + /// . + /// + /// width of the border + /// + /// the + /// rgb color + /// of the border + /// public GrooveBorder(DeviceRgb color, float width) : base(color, width) { } + /// + /// Creates a GrooveBorder instance with the specified width and the + /// cmyk color + /// . + /// + /// width of the border + /// + /// the + /// cmyk color + /// of the border + /// public GrooveBorder(DeviceCmyk color, float width) : base(color, width) { } + /// + /// Creates a GrooveBorder instance with the specified width and the + /// gray color + /// . + /// + /// width of the border + /// + /// the + /// gray color + /// of the border + /// public GrooveBorder(DeviceGray color, float width) : base(color, width) { } + /// public override int GetBorderType() { return Border._3D_GROOVE; } + /// protected internal override void SetInnerHalfColor(PdfCanvas canvas, Border.Side side) { switch (side) { case Border.Side.TOP: @@ -82,6 +124,7 @@ protected internal override void SetInnerHalfColor(PdfCanvas canvas, Border.Side } } + /// protected internal override void SetOuterHalfColor(PdfCanvas canvas, Border.Side side) { switch (side) { case Border.Side.TOP: diff --git a/itext/itext.layout/itext/layout/borders/InsetBorder.cs b/itext/itext.layout/itext/layout/borders/InsetBorder.cs index 25ed2e053e..046be6ba3d 100644 --- a/itext/itext.layout/itext/layout/borders/InsetBorder.cs +++ b/itext/itext.layout/itext/layout/borders/InsetBorder.cs @@ -46,26 +46,68 @@ source product. namespace iText.Layout.Borders { public class InsetBorder : Border3D { + /// Creates a InsetBorder instance with the specified width. + /// + /// Creates a InsetBorder instance with the specified width. The color is set to the default: + /// gray + /// . + /// + /// width of the border public InsetBorder(float width) : base(width) { } + /// + /// Creates a InsetBorder instance with the specified width and the + /// rgb color + /// . + /// + /// width of the border + /// + /// the + /// rgb color + /// of the border + /// public InsetBorder(DeviceRgb color, float width) : base(color, width) { } + /// + /// Creates a InsetBorder instance with the specified width and the + /// cmyk color + /// . + /// + /// width of the border + /// + /// the + /// cmyk color + /// of the border + /// public InsetBorder(DeviceCmyk color, float width) : base(color, width) { } + /// + /// Creates a InsetBorder instance with the specified width and the + /// gray color + /// . + /// + /// width of the border + /// + /// the + /// gray color + /// of the border + /// public InsetBorder(DeviceGray color, float width) : base(color, width) { } + /// public override int GetBorderType() { return Border._3D_INSET; } + /// protected internal override void SetInnerHalfColor(PdfCanvas canvas, Border.Side side) { switch (side) { case Border.Side.TOP: @@ -82,6 +124,7 @@ protected internal override void SetInnerHalfColor(PdfCanvas canvas, Border.Side } } + /// protected internal override void SetOuterHalfColor(PdfCanvas canvas, Border.Side side) { switch (side) { case Border.Side.TOP: diff --git a/itext/itext.layout/itext/layout/borders/OutsetBorder.cs b/itext/itext.layout/itext/layout/borders/OutsetBorder.cs index cbbcd18dce..0a778f665f 100644 --- a/itext/itext.layout/itext/layout/borders/OutsetBorder.cs +++ b/itext/itext.layout/itext/layout/borders/OutsetBorder.cs @@ -46,26 +46,68 @@ source product. namespace iText.Layout.Borders { public class OutsetBorder : Border3D { + /// Creates a OutsetBorder instance with the specified width. + /// + /// Creates a OutsetBorder instance with the specified width. The color is set to the default: + /// gray + /// . + /// + /// width of the border public OutsetBorder(float width) : base(width) { } + /// + /// Creates a OutsetBorder instance with the specified width and the + /// rgb color + /// . + /// + /// width of the border + /// + /// the + /// rgb color + /// of the border + /// public OutsetBorder(DeviceRgb color, float width) : base(color, width) { } + /// + /// Creates a OutsetBorder instance with the specified width and the + /// cmyk color + /// . + /// + /// width of the border + /// + /// the + /// cmyk color + /// of the border + /// public OutsetBorder(DeviceCmyk color, float width) : base(color, width) { } + /// + /// Creates a OutsetBorder instance with the specified width and the + /// gray color + /// . + /// + /// width of the border + /// + /// the + /// gray color + /// of the border + /// public OutsetBorder(DeviceGray color, float width) : base(color, width) { } + /// public override int GetBorderType() { return Border._3D_OUTSET; } + /// protected internal override void SetInnerHalfColor(PdfCanvas canvas, Border.Side side) { switch (side) { case Border.Side.TOP: @@ -82,6 +124,7 @@ protected internal override void SetInnerHalfColor(PdfCanvas canvas, Border.Side } } + /// protected internal override void SetOuterHalfColor(PdfCanvas canvas, Border.Side side) { switch (side) { case Border.Side.TOP: diff --git a/itext/itext.layout/itext/layout/borders/RidgeBorder.cs b/itext/itext.layout/itext/layout/borders/RidgeBorder.cs index 90da2818f4..9d2e096693 100644 --- a/itext/itext.layout/itext/layout/borders/RidgeBorder.cs +++ b/itext/itext.layout/itext/layout/borders/RidgeBorder.cs @@ -46,26 +46,68 @@ source product. namespace iText.Layout.Borders { public class RidgeBorder : Border3D { + /// Creates a RidgeBorder instance with the specified width. + /// + /// Creates a RidgeBorder instance with the specified width. The color is set to the default: + /// gray + /// . + /// + /// width of the border public RidgeBorder(float width) : base(width) { } + /// + /// Creates a RidgeBorder instance with the specified width and the + /// rgb color + /// . + /// + /// width of the border + /// + /// the + /// rgb color + /// of the border + /// public RidgeBorder(DeviceRgb color, float width) : base(color, width) { } + /// + /// Creates a RidgeBorder instance with the specified width and the + /// cmyk color + /// . + /// + /// width of the border + /// + /// the + /// cmyk color + /// of the border + /// public RidgeBorder(DeviceCmyk color, float width) : base(color, width) { } + /// + /// Creates a RidgeBorder instance with the specified width and the + /// gray color + /// . + /// + /// width of the border + /// + /// the + /// gray color + /// of the border + /// public RidgeBorder(DeviceGray color, float width) : base(color, width) { } + /// public override int GetBorderType() { return Border._3D_RIDGE; } + /// protected internal override void SetInnerHalfColor(PdfCanvas canvas, Border.Side side) { switch (side) { case Border.Side.TOP: @@ -82,6 +124,7 @@ protected internal override void SetInnerHalfColor(PdfCanvas canvas, Border.Side } } + /// protected internal override void SetOuterHalfColor(PdfCanvas canvas, Border.Side side) { switch (side) { case Border.Side.TOP: diff --git a/itext/itext.layout/itext/layout/borders/RoundDotsBorder.cs b/itext/itext.layout/itext/layout/borders/RoundDotsBorder.cs index ae88434a41..ef6e0f386f 100644 --- a/itext/itext.layout/itext/layout/borders/RoundDotsBorder.cs +++ b/itext/itext.layout/itext/layout/borders/RoundDotsBorder.cs @@ -53,6 +53,7 @@ namespace iText.Layout.Borders { /// . /// public class RoundDotsBorder : Border { + /// The modifier to be applied on the width to have the initial gap size private const float GAP_MODIFIER = 2.5f; /// Creates a RoundDotsBorder with the specified wit?dth and sets the color to black. @@ -68,10 +69,12 @@ public RoundDotsBorder(Color color, float width) : base(color, width) { } + /// public override int GetBorderType() { return Border.ROUND_DOTS; } + /// public override void Draw(PdfCanvas canvas, float x1, float y1, float x2, float y2, float borderWidthBefore , float borderWidthAfter) { float initialGap = width * GAP_MODIFIER; @@ -112,6 +115,7 @@ public override void Draw(PdfCanvas canvas, float x1, float y1, float x2, float canvas.SetLineDash(0, adjustedGap, adjustedGap / 2).MoveTo(x1, y1).LineTo(x2, y2).Stroke(); } + /// public override void DrawCellBorder(PdfCanvas canvas, float x1, float y1, float x2, float y2) { float initialGap = width * GAP_MODIFIER; float dx = x2 - x1; @@ -131,6 +135,14 @@ public override void DrawCellBorder(PdfCanvas canvas, float x1, float y1, float canvas.SetLineDash(0, adjustedGap, adjustedGap / 2).MoveTo(x1, y1).LineTo(x2, y2).Stroke(); } + /// Adjusts the size of the gap between dots + /// + /// the + /// border + /// length + /// + /// the initial size of the gap + /// the adjusted size of the gap protected internal virtual float GetDotsGap(double distance, float initialGap) { double gapsNum = System.Math.Ceiling(distance / initialGap); return (float)(distance / gapsNum); diff --git a/itext/itext.layout/itext/layout/borders/SolidBorder.cs b/itext/itext.layout/itext/layout/borders/SolidBorder.cs index 6ec6ff8551..4fd3811159 100644 --- a/itext/itext.layout/itext/layout/borders/SolidBorder.cs +++ b/itext/itext.layout/itext/layout/borders/SolidBorder.cs @@ -60,10 +60,12 @@ public SolidBorder(Color color, float width) : base(color, width) { } + /// public override int GetBorderType() { return Border.SOLID; } + /// public override void Draw(PdfCanvas canvas, float x1, float y1, float x2, float y2, float borderWidthBefore , float borderWidthAfter) { float x3 = 0; @@ -108,6 +110,7 @@ public override void Draw(PdfCanvas canvas, float x1, float y1, float x2, float canvas.MoveTo(x1, y1).LineTo(x2, y2).LineTo(x3, y3).LineTo(x4, y4).LineTo(x1, y1).Fill(); } + /// public override void DrawCellBorder(PdfCanvas canvas, float x1, float y1, float x2, float y2) { canvas.SaveState().SetStrokeColor(color).SetLineWidth(width).MoveTo(x1, y1).LineTo(x2, y2).Stroke().RestoreState (); diff --git a/itext/itext.layout/itext/layout/element/AbstractElement.cs b/itext/itext.layout/itext/layout/element/AbstractElement.cs index 06e1dc4655..efb0328d89 100644 --- a/itext/itext.layout/itext/layout/element/AbstractElement.cs +++ b/itext/itext.layout/itext/layout/element/AbstractElement.cs @@ -140,15 +140,38 @@ protected internal virtual void PropagateArtifactRoleToChildElements() { } } + /// Returns true if this list contains no elements. + /// true if this list contains no elements public virtual bool IsEmpty() { return 0 == childElements.Count; } + /// Sets an action on this Element. + /// + /// Sets an action on this Element. An action is a general PDF concept that + /// signifies anything that makes the document interactive, e.g. a hyperlink + /// or a button. + /// + /// + /// the + /// + /// that should be performed + /// + /// this Element public virtual T SetAction(PdfAction action) { SetProperty(Property.ACTION, action); return (T)(Object)this; } + /// Explicitly sets the page number this element should be put on. + /// + /// Explicitly sets the page number this element should be put on. The location + /// on the page will be the same as if it were added at the end of the document, + /// but it will be located on the specified page. + /// This method should be used very carefully in client code. + /// + /// the page number of the page this element should be placed on + /// this Element public virtual T SetPageNumber(int pageNumber) { SetProperty(Property.PAGE_NUMBER, pageNumber); return (T)(Object)this; diff --git a/itext/itext.layout/itext/layout/element/BlockElement.cs b/itext/itext.layout/itext/layout/element/BlockElement.cs index 0e65979c1e..6769663917 100644 --- a/itext/itext.layout/itext/layout/element/BlockElement.cs +++ b/itext/itext.layout/itext/layout/element/BlockElement.cs @@ -273,19 +273,54 @@ public virtual T SetKeepTogether(bool keepTogether) { return (T)(Object)this; } + /// + /// Returns whether the end of this + /// + /// and the start of the next sibling of this element + /// should be placed in the same area. + /// + /// + /// the current value of the + /// + /// property + /// + public virtual bool? IsKeepWithNext() { + return this.GetProperty(Property.KEEP_WITH_NEXT); + } + + /// + /// Sets whether the end of this + /// + /// and the start of the next sibling of this element + /// should be placed in the same area. + /// Note that this will only work for high-level elements, i.e. elements added to the + /// + /// . + /// + /// + /// the new value of the + /// + /// property + /// + /// this element + public virtual T SetKeepWithNext(bool keepWithNext) { + SetProperty(Property.KEEP_WITH_NEXT, keepWithNext); + return (T)(Object)this; + } + /// Sets the rotation radAngle. - /// the new rotation radAngle, as a float + /// the new rotation radAngle, as a float, in radians /// this element - public virtual T SetRotationAngle(float radAngle) { - SetProperty(Property.ROTATION_ANGLE, radAngle); + public virtual T SetRotationAngle(float angleInRadians) { + SetProperty(Property.ROTATION_ANGLE, angleInRadians); return (T)(Object)this; } /// Sets the rotation angle. - /// the new rotation angle, as a double + /// the new rotation angle, as a double, in radians /// this element - public virtual T SetRotationAngle(double angle) { - SetProperty(Property.ROTATION_ANGLE, (float)angle); + public virtual T SetRotationAngle(double angleInRadians) { + SetProperty(Property.ROTATION_ANGLE, (float)angleInRadians); return (T)(Object)this; } diff --git a/itext/itext.layout/itext/layout/element/Cell.cs b/itext/itext.layout/itext/layout/element/Cell.cs index 02245b6775..a9024e283e 100644 --- a/itext/itext.layout/itext/layout/element/Cell.cs +++ b/itext/itext.layout/itext/layout/element/Cell.cs @@ -124,18 +124,42 @@ public override IRenderer GetRenderer() { return cellRenderer == null ? MakeNewRenderer() : cellRenderer; } + /// + /// Gets + /// the number of the row + /// in which the cell is located. + /// + /// the row number public virtual int GetRow() { return row; } + /// + /// Gets + /// the number of the column + /// in which the cell is located. + /// + /// the column number public virtual int GetCol() { return col; } + /// + /// Gets the + /// rowspan + /// of the cell. + /// + /// the rowspan public virtual int GetRowspan() { return rowspan; } + /// + /// Gets the + /// colspan + /// of the cell. + /// + /// the colspan public virtual int GetColspan() { return colspan; } diff --git a/itext/itext.layout/itext/layout/element/Tab.cs b/itext/itext.layout/itext/layout/element/Tab.cs index 46320472b9..9a9c8b4df2 100644 --- a/itext/itext.layout/itext/layout/element/Tab.cs +++ b/itext/itext.layout/itext/layout/element/Tab.cs @@ -44,6 +44,16 @@ source product. using iText.Layout.Renderer; namespace iText.Layout.Element { + /// + /// This class represents the empty space from a + /// + /// to the following + /// + /// , if any. Using this class will not have any effect unless + /// there are + /// + /// objects defined for the enveloping element. + /// public class Tab : AbstractElement, ILeafElement { protected internal override IRenderer MakeNewRenderer() { return new TabRenderer(this); diff --git a/itext/itext.layout/itext/layout/element/TabStop.cs b/itext/itext.layout/itext/layout/element/TabStop.cs index 6a6bd1e635..f0b5d2ff1f 100644 --- a/itext/itext.layout/itext/layout/element/TabStop.cs +++ b/itext/itext.layout/itext/layout/element/TabStop.cs @@ -45,6 +45,20 @@ source product. using iText.Layout.Properties; namespace iText.Layout.Element { + /// + /// A TabStop is the closest location on a line of text that the text will jump + /// to if a + /// + /// is inserted. At least one TabStop must be defined on an + /// element if you want to use + /// Tabs + /// . + /// This object can be added to a + /// + /// with the method + /// + /// . + /// public class TabStop { private float tabPosition; @@ -54,14 +68,54 @@ public class TabStop { private ILineDrawer tabLeader; + /// Creates a TabStop at the appropriate position. + /// a float, measured in points public TabStop(float tabPosition) : this(tabPosition, TabAlignment.LEFT) { } + /// + /// Creates a TabStop at the appropriate position, with a specified tab + /// alignment. + /// + /// + /// Creates a TabStop at the appropriate position, with a specified tab + /// alignment. A tab alignment defines the way the textual content should be + /// positioned with regards to this tab stop. + /// + /// a float, measured in points + /// + /// a + /// + /// value + /// public TabStop(float tabPosition, TabAlignment tabAlignment) : this(tabPosition, tabAlignment, null) { } + /// + /// Creates a TabStop at the appropriate position, with a specified tab + /// alignment and an explicitly given line pattern. + /// + /// + /// Creates a TabStop at the appropriate position, with a specified tab + /// alignment and an explicitly given line pattern. A tab alignment defines + /// the way the textual content should be positioned with regards to this tab + /// stop. The line pattern defines a pattern that should be repeated until + /// the TabStop is reached. If null, the space leading up to the TabStop will + /// be empty. + /// + /// a float, measured in points + /// + /// a + /// + /// value + /// + /// + /// the + /// + /// value, a pattern drawing object + /// public TabStop(float tabPosition, TabAlignment tabAlignment, ILineDrawer tabLeader) { this.tabPosition = tabPosition; this.tabAlignment = tabAlignment; diff --git a/itext/itext.layout/itext/layout/element/Text.cs b/itext/itext.layout/itext/layout/element/Text.cs index 02735931a6..3fe343b26c 100644 --- a/itext/itext.layout/itext/layout/element/Text.cs +++ b/itext/itext.layout/itext/layout/element/Text.cs @@ -75,10 +75,14 @@ public Text(String text) { this.text = text; } + /// Gets the contents of the Text object that will be rendered. + /// the string with the contents public virtual String GetText() { return text; } + /// Sets the contents of the Text object. + /// the new contents public virtual void SetText(String text) { this.text = text; } diff --git a/itext/itext.layout/itext/layout/hyphenation/CharVector.cs b/itext/itext.layout/itext/layout/hyphenation/CharVector.cs index ae322cce22..87d44121e5 100644 --- a/itext/itext.layout/itext/layout/hyphenation/CharVector.cs +++ b/itext/itext.layout/itext/layout/hyphenation/CharVector.cs @@ -72,6 +72,8 @@ public CharVector(char[] a, int capacity) { n = a.Length; } + /// Copy constructor + /// the CharVector that should be cloned public CharVector(iText.Layout.Hyphenation.CharVector cv) { this.array = (char[])cv.array.Clone(); this.blockSize = cv.blockSize; diff --git a/itext/itext.layout/itext/layout/hyphenation/HyphenationException.cs b/itext/itext.layout/itext/layout/hyphenation/HyphenationException.cs index f3f1c5a22e..0be4b20032 100644 --- a/itext/itext.layout/itext/layout/hyphenation/HyphenationException.cs +++ b/itext/itext.layout/itext/layout/hyphenation/HyphenationException.cs @@ -17,14 +17,14 @@ using System; namespace iText.Layout.Hyphenation { - /// - ///

    An hyphenation exception.

    + /// A hyphenation exception. + /// + /// A hyphenation exception. ///

    This work was authored by Carlos Villegas (cav@uniscope.co.jp).

    - ///
    + /// public class HyphenationException : Exception { /// Construct a hyphenation exception. /// a message string - /// public HyphenationException(String msg) : base(msg) { } diff --git a/itext/itext.layout/itext/layout/hyphenation/TernaryTreeIterator.cs b/itext/itext.layout/itext/layout/hyphenation/TernaryTreeIterator.cs index 3593029874..302bd04dd3 100644 --- a/itext/itext.layout/itext/layout/hyphenation/TernaryTreeIterator.cs +++ b/itext/itext.layout/itext/layout/hyphenation/TernaryTreeIterator.cs @@ -46,6 +46,11 @@ source product. using System.Text; namespace iText.Layout.Hyphenation { + /// + /// An object that iterates over the + /// + /// . + /// internal class TernaryTreeIterator : IEnumerator { /// current node index internal int cur; @@ -108,6 +113,7 @@ public virtual void Rewind() { Reset(); } + /// Resets the Iterator to its initial state. public virtual void Reset() { ns.Clear(); ks.Length = 0; diff --git a/itext/itext.layout/itext/layout/layout/LayoutArea.cs b/itext/itext.layout/itext/layout/layout/LayoutArea.cs index d8173ac562..356ed82451 100644 --- a/itext/itext.layout/itext/layout/layout/LayoutArea.cs +++ b/itext/itext.layout/itext/layout/layout/LayoutArea.cs @@ -47,44 +47,77 @@ source product. using iText.Layout.Renderer; namespace iText.Layout.Layout { + /// + /// Represents the area for content + /// layouting + /// . + /// public class LayoutArea { + /// The number of page on which the area is located. protected internal int pageNumber; + /// The area's bounding box protected internal Rectangle bBox; + /// Indicates whether the area already has some placed content or not. protected internal bool emptyArea = true; + /// + /// Creates the area for content + /// layouting + /// . + /// + /// the number of page on which the area is located. + /// the area's bounding box public LayoutArea(int pageNumber, Rectangle bBox) { this.pageNumber = pageNumber; this.bBox = bBox; } + /// Gets the number of page on which the area is located. + /// page number public virtual int GetPageNumber() { return pageNumber; } + /// + /// Gets the + /// box + /// which bounds the area. + /// + /// the bounding box public virtual Rectangle GetBBox() { return bBox; } + /// + /// Sets the + /// box + /// which bounds the area. + /// public virtual void SetBBox(Rectangle bbox) { this.bBox = bbox; } + /// Indicates whether the area already has some placed content or not. + /// whether the area is empty or not public virtual bool IsEmptyArea() { return emptyArea; } + /// Defines whether the area already has some placed content or not. public virtual void SetEmptyArea(bool emptyArea) { this.emptyArea = emptyArea; } + /// public virtual iText.Layout.Layout.LayoutArea Clone() { iText.Layout.Layout.LayoutArea area = new iText.Layout.Layout.LayoutArea(pageNumber, bBox.Clone()); area.SetEmptyArea(emptyArea); return area; } + /// public override bool Equals(Object obj) { if (!(obj is iText.Layout.Layout.LayoutArea)) { return false; @@ -93,12 +126,14 @@ public override bool Equals(Object obj) { return pageNumber == that.pageNumber && bBox.EqualsWithEpsilon(that.bBox, AbstractRenderer.EPS); } + /// public override int GetHashCode() { HashCode hashCode = new HashCode(); hashCode.Append(pageNumber).Append(bBox.GetHashCode()).Append(emptyArea); return hashCode.GetHashCode(); } + /// public override String ToString() { return String.Format("{0}, page {1}", bBox.ToString(), pageNumber); } diff --git a/itext/itext.layout/itext/layout/layout/LayoutContext.cs b/itext/itext.layout/itext/layout/layout/LayoutContext.cs index 8d40d67c46..6e8de4116d 100644 --- a/itext/itext.layout/itext/layout/layout/LayoutContext.cs +++ b/itext/itext.layout/itext/layout/layout/LayoutContext.cs @@ -44,17 +44,34 @@ source product. using System; namespace iText.Layout.Layout { + /// + /// Represents the context for content + /// layouting + /// . + /// public class LayoutContext { + /// + /// The + /// area + /// the content to be placed on. + /// protected internal LayoutArea area; public LayoutContext(LayoutArea area) { this.area = area; } + /// + /// Gets the + /// area + /// the content to be placed on. + /// + /// the area for content layouting. public virtual LayoutArea GetArea() { return area; } + /// public override String ToString() { return area.ToString(); } diff --git a/itext/itext.layout/itext/layout/layout/LayoutResult.cs b/itext/itext.layout/itext/layout/layout/LayoutResult.cs index 206f9d2ffc..1092726296 100644 --- a/itext/itext.layout/itext/layout/layout/LayoutResult.cs +++ b/itext/itext.layout/itext/layout/layout/LayoutResult.cs @@ -46,51 +46,194 @@ source product. using iText.Layout.Renderer; namespace iText.Layout.Layout { + /// + /// Represents the result of content + /// layouting + /// . + /// public class LayoutResult { + /// + /// The status of + /// + /// which indicates that the content was fully placed. + /// public const int FULL = 1; + /// + /// The status of + /// + /// which indicates that the content was placed partially. + /// public const int PARTIAL = 2; + /// + /// The status of + /// + /// which indicates that the content was not placed. + /// public const int NOTHING = 3; + /// + /// The status of + /// + /// which indicates whether the content was added or not + /// and, if yes, was it added fully or partially. + /// protected internal int status; + /// + /// The area occupied by the content during its + /// layouting + /// . + /// which indicates whether the content was added or not and, if yes, was it added fully or partially. + /// protected internal LayoutArea occupiedArea; + /// + /// The split renderer created during + /// layouting + /// . + /// This renderer will be used to draw the splitted part of content. + /// protected internal IRenderer splitRenderer; + /// + /// The overflow renderer created during + /// layouting + /// . + /// This renderer will be used to draw the overflowed part of content. + /// protected internal IRenderer overflowRenderer; protected internal AreaBreak areaBreak; + /// + /// The first renderer to produce + /// + /// during + /// + /// . + /// + protected internal IRenderer causeOfNothing; + + /// + /// Creates the + /// + /// result of + /// layouting + /// }. + /// The + /// + /// will be set as null. + /// + /// + /// the status of + /// + /// + /// the area occupied by the content + /// the renderer to draw the splitted part of the content + /// the renderer to draw the overflowed part of the content public LayoutResult(int status, LayoutArea occupiedArea, IRenderer splitRenderer, IRenderer overflowRenderer ) { this.status = status; this.occupiedArea = occupiedArea; this.splitRenderer = splitRenderer; this.overflowRenderer = overflowRenderer; + causeOfNothing = null; + } + + /// + /// Creates the + /// + /// result of + /// layouting + /// }. + /// + /// + /// the status of + /// + /// + /// the area occupied by the content + /// the renderer to draw the splitted part of the content + /// the renderer to draw the overflowed part of the content + /// + /// the first renderer to produce + /// + /// + public LayoutResult(int status, LayoutArea occupiedArea, IRenderer splitRenderer, IRenderer overflowRenderer + , IRenderer cause) + : this(status, occupiedArea, splitRenderer, overflowRenderer) { + causeOfNothing = cause; } + /// + /// Gets the status of + /// + /// . + /// + /// the status public virtual int GetStatus() { return status; } + /// + /// Gets the + /// layout area + /// occupied by the content during + /// layouting + /// . + /// + /// + /// the + /// layout area + /// occupied by the content + /// public virtual LayoutArea GetOccupiedArea() { return occupiedArea; } + /// + /// Gets the split + /// renderer + /// created during + /// layouting + /// . + /// + /// + /// the + /// renderer + /// public virtual IRenderer GetSplitRenderer() { return splitRenderer; } + /// + /// Sets the split + /// renderer + /// . + /// public virtual void SetSplitRenderer(IRenderer splitRenderer) { this.splitRenderer = splitRenderer; } + /// + /// Gets the overflow renderer created during + /// layouting + /// . + /// + /// + /// the + /// renderer + /// public virtual IRenderer GetOverflowRenderer() { return overflowRenderer; } + /// + /// Sets the overflow + /// renderer + /// . + /// public virtual void SetOverflowRenderer(IRenderer overflowRenderer) { this.overflowRenderer = overflowRenderer; } @@ -104,6 +247,21 @@ public virtual iText.Layout.Layout.LayoutResult SetAreaBreak(AreaBreak areaBreak return this; } + /// + /// Gets the first renderer to produce + /// + /// during + /// + /// + /// + /// the + /// renderer + /// + public virtual IRenderer GetCauseOfNothing() { + return causeOfNothing; + } + + /// public override String ToString() { String status; switch (GetStatus()) { diff --git a/itext/itext.layout/itext/layout/layout/LineLayoutResult.cs b/itext/itext.layout/itext/layout/layout/LineLayoutResult.cs index bfb16387f2..e097cf1bd5 100644 --- a/itext/itext.layout/itext/layout/layout/LineLayoutResult.cs +++ b/itext/itext.layout/itext/layout/layout/LineLayoutResult.cs @@ -44,18 +44,82 @@ source product. using iText.Layout.Renderer; namespace iText.Layout.Layout { + /// + /// Represents the result of a line + /// layouting + /// . + /// public class LineLayoutResult : LayoutResult { + /// Indicates whether split was forced by new line symbol or not. protected internal bool splitForcedByNewline; + /// + /// Creates the + /// + /// result of + /// layouting + /// }. + /// The + /// + /// will be set as null. + /// + /// + /// the status of + /// + /// + /// the area occupied by the content + /// the renderer to draw the splitted part of the content + /// the renderer to draw the overflowed part of the content public LineLayoutResult(int status, LayoutArea occupiedArea, IRenderer splitRenderer, IRenderer overflowRenderer ) : base(status, occupiedArea, splitRenderer, overflowRenderer) { } + /// + /// Creates the + /// + /// result of + /// layouting + /// }. + /// + /// + /// the status of + /// + /// + /// the area occupied by the content + /// the renderer to draw the splitted part of the content + /// the renderer to draw the overflowed part of the content + /// + /// the first renderer to produce + /// + /// + public LineLayoutResult(int status, LayoutArea occupiedArea, IRenderer splitRenderer, IRenderer overflowRenderer + , IRenderer cause) + : base(status, occupiedArea, splitRenderer, overflowRenderer, cause) { + } + + /// Indicates whether split was forced by new line symbol in rendered text. + /// + /// Indicates whether split was forced by new line symbol in rendered text. + /// The value will be set as true if, for example, + /// the rendered text of one of the child renderers contains '\n' symbol. + /// + /// whether split was forced by new line or not public virtual bool IsSplitForcedByNewline() { return splitForcedByNewline; } + /// + /// Sets + /// + /// + /// indicates that split was forced by new line symbol in rendered text. + /// + /// + /// this layout result + /// the setting was applied on. + /// + /// public virtual iText.Layout.Layout.LineLayoutResult SetSplitForcedByNewline(bool isSplitForcedByNewline) { this.splitForcedByNewline = isSplitForcedByNewline; return this; diff --git a/itext/itext.layout/itext/layout/layout/TextLayoutResult.cs b/itext/itext.layout/itext/layout/layout/TextLayoutResult.cs index 261c6f3383..3bbfaae9e9 100644 --- a/itext/itext.layout/itext/layout/layout/TextLayoutResult.cs +++ b/itext/itext.layout/itext/layout/layout/TextLayoutResult.cs @@ -44,29 +44,119 @@ source product. using iText.Layout.Renderer; namespace iText.Layout.Layout { + /// + /// Represents the result of a text + /// layout + /// . + /// public class TextLayoutResult : LayoutResult { + /// + /// Indicates whether some word was splitted during + /// layout + /// . + /// protected internal bool wordHasBeenSplit; + /// Indicates whether split was forced by new line symbol in text or not. protected internal bool splitForcedByNewline; + /// + /// Creates the + /// + /// result of + /// layouting + /// }. + /// The + /// + /// will be set as null. + /// + /// + /// the status of + /// + /// + /// the area occupied by the content + /// the renderer to draw the splitted part of the content + /// the renderer to draw the overflowed part of the content public TextLayoutResult(int status, LayoutArea occupiedArea, IRenderer splitRenderer, IRenderer overflowRenderer ) : base(status, occupiedArea, splitRenderer, overflowRenderer) { } + /// + /// Creates the + /// + /// result of + /// layouting + /// }. + /// + /// + /// the status of + /// + /// + /// the area occupied by the content + /// the renderer to draw the splitted part of the content + /// the renderer to draw the overflowed part of the content + /// + /// the first renderer to produce + /// + /// + public TextLayoutResult(int status, LayoutArea occupiedArea, IRenderer splitRenderer, IRenderer overflowRenderer + , IRenderer cause) + : base(status, occupiedArea, splitRenderer, overflowRenderer, cause) { + } + + /// + /// Indicates whether some word in a rendered text was splitted during + /// layout + /// . + /// The value will be set as true if, for example, the rendered words width is bigger than the width of layout area. + /// + /// whether some word was splitted or not. public virtual bool IsWordHasBeenSplit() { return wordHasBeenSplit; } + /// + /// Sets + /// + /// + /// + /// indicates that some word was splitted during + /// layout + /// . + /// + /// + /// + /// this layout result + /// the setting was applied on + /// + /// public virtual iText.Layout.Layout.TextLayoutResult SetWordHasBeenSplit(bool wordHasBeenSplit) { this.wordHasBeenSplit = wordHasBeenSplit; return this; } + /// Indicates whether split was forced by new line symbol in rendered text. + /// + /// Indicates whether split was forced by new line symbol in rendered text. + /// The value will be set as true if, for example, the rendered text contains '\n' symbol. + /// + /// whether split was forced by new line or not. public virtual bool IsSplitForcedByNewline() { return splitForcedByNewline; } + /// + /// Sets + /// + /// + /// indicates that split was forced by new line symbol in rendered text. + /// + /// + /// this layout result + /// the setting was applied on. + /// + /// public virtual iText.Layout.Layout.TextLayoutResult SetSplitForcedByNewline(bool isSplitForcedByNewline) { this.splitForcedByNewline = isSplitForcedByNewline; return this; diff --git a/itext/itext.layout/itext/layout/properties/Leading.cs b/itext/itext.layout/itext/layout/properties/Leading.cs index 9ac0b7f731..f4c810182c 100644 --- a/itext/itext.layout/itext/layout/properties/Leading.cs +++ b/itext/itext.layout/itext/layout/properties/Leading.cs @@ -105,5 +105,9 @@ public override bool Equals(Object obj) { return obj is iText.Layout.Properties.Leading && type == ((iText.Layout.Properties.Leading)obj).type && value == ((iText.Layout.Properties.Leading)obj).value; } + + public override int GetHashCode() { + return iText.IO.Util.JavaUtil.ArraysHashCode(type, value); + } } } diff --git a/itext/itext.layout/itext/layout/properties/Property.cs b/itext/itext.layout/itext/layout/properties/Property.cs index dd3248a588..9de286c4b3 100644 --- a/itext/itext.layout/itext/layout/properties/Property.cs +++ b/itext/itext.layout/itext/layout/properties/Property.cs @@ -62,6 +62,8 @@ private Property() { public const int ACTION = 1; + public const int APPEARANCE_STREAM_LAYOUT = 82; + public const int AREA_BREAK_TYPE = 2; public const int AUTO_SCALE = 3; @@ -125,6 +127,8 @@ private Property() { public const int KEEP_TOGETHER = 32; + public const int KEEP_WITH_NEXT = 81; + public const int LEADING = 33; public const int LEFT = 34; @@ -201,7 +205,11 @@ private Property() { public const int TEXT_ALIGNMENT = 70; - /// Use values from . + /// + /// Use values from + /// + /// . + /// public const int TEXT_RENDERING_MODE = 71; public const int TEXT_RISE = 72; @@ -232,10 +240,11 @@ private Property() { /// private static readonly bool[] INHERITED_PROPERTIES; - private const int MAX_INHERITED_PROPERTY_ID = 80; + private const int MAX_INHERITED_PROPERTY_ID = 82; static Property() { INHERITED_PROPERTIES = new bool[MAX_INHERITED_PROPERTY_ID + 1]; + INHERITED_PROPERTIES[iText.Layout.Properties.Property.APPEARANCE_STREAM_LAYOUT] = true; INHERITED_PROPERTIES[iText.Layout.Properties.Property.BASE_DIRECTION] = true; INHERITED_PROPERTIES[iText.Layout.Properties.Property.BOLD_SIMULATION] = true; INHERITED_PROPERTIES[iText.Layout.Properties.Property.CHARACTER_SPACING] = true; @@ -263,8 +272,16 @@ static Property() { INHERITED_PROPERTIES[iText.Layout.Properties.Property.WORD_SPACING] = true; } + /// + /// This method checks whether a Property, in order to be picked up by the + /// rendering engine, must be defined on the current element or renderer + /// (return false), or may be defined in one of its parent + /// elements or renderers (return true). + /// + /// the ID, defined in this class, of the property to check + /// whether the property type is inheritable public static bool IsPropertyInherited(int property) { - return property >= 0 && property < MAX_INHERITED_PROPERTY_ID && INHERITED_PROPERTIES[property]; + return property >= 0 && property <= MAX_INHERITED_PROPERTY_ID && INHERITED_PROPERTIES[property]; } } } diff --git a/itext/itext.layout/itext/layout/properties/Underline.cs b/itext/itext.layout/itext/layout/properties/Underline.cs index 481aa67630..4f602e8cea 100644 --- a/itext/itext.layout/itext/layout/properties/Underline.cs +++ b/itext/itext.layout/itext/layout/properties/Underline.cs @@ -42,8 +42,16 @@ source product. address: sales@itextpdf.com */ using iText.Kernel.Colors; +using iText.Kernel.Pdf.Canvas; namespace iText.Layout.Properties { + /// A POJO that describes the underline of a layout element. + /// + /// A POJO that describes the underline of a layout element. + /// This class is to be used as a property for an element or renderer, + /// as the value for + /// + /// public class Underline { protected internal Color color; @@ -55,8 +63,34 @@ public class Underline { protected internal float yPositionMul; - protected internal int lineCapStyle; - + protected internal int lineCapStyle = PdfCanvasConstants.LineCapStyle.BUTT; + + /// Creates an Underline. + /// + /// Creates an Underline. Both the thickness and vertical positioning under + /// the text element's base line can be set to a fixed value, or a variable + /// one depending on the element's font size. + /// If you want a fixed-width thickness, set thicknessMul to 0; + /// if you want a thickness solely dependent on the font size, set + /// thickness to 0. + /// Mutatis mutandis for the y-position. + /// + /// + /// the + /// + /// of the underline + /// + /// a float defining the minimum thickness in points of the underline + /// a float defining the font size dependent component of the thickness of the underline + /// + /// a float defining the default absolute vertical distance in points from the text's base line + /// + /// a float defining the font size dependent component of the vertical positioning of the underline + /// + /// + /// the way the underline finishes at its edges. + /// + /// public Underline(Color color, float thickness, float thicknessMul, float yPosition, float yPositionMul, int lineCapStyle) { this.color = color; @@ -67,22 +101,45 @@ public Underline(Color color, float thickness, float thicknessMul, float yPositi this.lineCapStyle = lineCapStyle; } + /// Gets the color of the underline. + /// + /// a + /// + /// public virtual Color GetColor() { return color; } + /// Gets the total thickness of the underline (fixed + variable part). + /// the font size for which to calculate the variable thickness + /// the total thickness, as a float, in points public virtual float GetThickness(float fontSize) { return thickness + thicknessMul * fontSize; } + /// Gets the vertical position of the underline (fixed + variable part). + /// the font size for which to calculate the variable position + /// the y-position, as a float, in points public virtual float GetYPosition(float fontSize) { return yPosition + yPositionMul * fontSize; } + /// Gets the multiplier for the vertical positioning of the text underline. + /// the Y-position multiplier, as a float public virtual float GetYPositionMul() { return yPositionMul; } + /// + /// Gets the + /// + /// of the text underline. + /// + /// + /// the line cap style, as an int referring to + /// the values of + /// + /// public virtual int GetLineCapStyle() { return lineCapStyle; } diff --git a/itext/itext.layout/itext/layout/properties/UnitValue.cs b/itext/itext.layout/itext/layout/properties/UnitValue.cs index 298f0cf2b5..09e7f99f75 100644 --- a/itext/itext.layout/itext/layout/properties/UnitValue.cs +++ b/itext/itext.layout/itext/layout/properties/UnitValue.cs @@ -91,26 +91,48 @@ public static iText.Layout.Properties.UnitValue CreatePercentValue(float value) return new iText.Layout.Properties.UnitValue(PERCENT, value); } + /// Returns the unit this value is stored in, either points (pt) or percent(%) + /// + /// either 1 for + /// + /// or 2 for + /// + /// public virtual int GetUnitType() { return unitType; } + /// Sets the unit this value is stored in, either points (pt) or percent(%) + /// + /// either + /// + /// or + /// + /// public virtual void SetUnitType(int unitType) { this.unitType = unitType; } + /// Gets the measured value stored in this object + /// the value, as a float public virtual float GetValue() { return value; } + /// Sets the measured value stored in this object + /// a float public virtual void SetValue(float value) { this.value = value; } + /// Returns whether or not the value is stored in points (pt) + /// true if stored in points public virtual bool IsPointValue() { return unitType == POINT; } + /// Returns whether or not the value is stored in percent (%) + /// true if stored in percent public virtual bool IsPercentValue() { return unitType == PERCENT; } diff --git a/itext/itext.layout/itext/layout/renderer/AbstractRenderer.cs b/itext/itext.layout/itext/layout/renderer/AbstractRenderer.cs index 1d3331d0cf..41ff59975a 100644 --- a/itext/itext.layout/itext/layout/renderer/AbstractRenderer.cs +++ b/itext/itext.layout/itext/layout/renderer/AbstractRenderer.cs @@ -55,774 +55,883 @@ source product. using iText.Kernel.Pdf.Annot; using iText.Kernel.Pdf.Canvas; using iText.Kernel.Pdf.Tagutils; -using iText.Layout; using iText.Layout.Borders; using iText.Layout.Element; using iText.Layout.Layout; using iText.Layout.Properties; -namespace iText.Layout.Renderer -{ - /// - /// Defines the most common properties and behavior that are shared by most - /// - /// implementations. All default Renderers are subclasses of - /// this default implementation. - /// - public abstract class AbstractRenderer : IRenderer - { - public const float EPS = 1e-4f; - - public const float INF = 1e6f; - - protected internal IList childRenderers = new List(); - - protected internal IList positionedRenderers = new List(); - - protected internal IPropertyContainer modelElement; - - protected internal bool flushed = false; - - protected internal LayoutArea occupiedArea; - - protected internal IRenderer parent; - - protected internal IDictionary properties = new Dictionary(); - - protected internal bool isLastRendererForModelElement = true; - - /// Creates a renderer. - protected internal AbstractRenderer() - { - } - - /// Creates a renderer for the specified layout element. - /// the layout element that will be drawn by this renderer - /// - protected internal AbstractRenderer(IElement modelElement) - { - // TODO linkedList? - this.modelElement = modelElement; - } - - protected internal AbstractRenderer(iText.Layout.Renderer.AbstractRenderer other - ) - { - this.childRenderers = other.childRenderers; - this.positionedRenderers = other.positionedRenderers; - this.modelElement = other.modelElement; - this.flushed = other.flushed; - this.occupiedArea = other.occupiedArea.Clone(); - this.parent = other.parent; - this.properties.AddAll(other.properties); - this.isLastRendererForModelElement = other.isLastRendererForModelElement; - } - - public virtual void AddChild(IRenderer renderer) - { - // https://www.webkit.org/blog/116/webcore-rendering-iii-layout-basics - // "The rules can be summarized as follows:"... - int? positioning = renderer.GetProperty(Property.POSITION); - if (positioning == null || positioning == LayoutPosition.RELATIVE || positioning - == LayoutPosition.STATIC) - { - childRenderers.Add(renderer); - } - else - { - if (positioning == LayoutPosition.FIXED) - { - iText.Layout.Renderer.AbstractRenderer root = this; - while (root.parent is iText.Layout.Renderer.AbstractRenderer) - { - root = (iText.Layout.Renderer.AbstractRenderer)root.parent; - } - if (root == this) - { - positionedRenderers.Add(renderer); - } - else - { - root.AddChild(renderer); - } - } - } - } - - public virtual IPropertyContainer GetModelElement() - { - return modelElement; - } - - public virtual IList GetChildRenderers() - { - return childRenderers; - } - - public virtual bool HasProperty(int property) - { - return HasOwnProperty(property) || (modelElement != null && modelElement.HasProperty - (property)) || (parent != null && Property.IsPropertyInherited(property) && parent.HasProperty(property)); - } - - public virtual bool HasOwnProperty(int property) - { - return properties.ContainsKey(property); - } - - public virtual void DeleteOwnProperty(int property) - { - properties.JRemove(property); - } - - /// - /// Deletes property from this very renderer, or in case the property is specified on its model element, the - /// property of the model element is deleted - /// - /// the property key to be deleted - public virtual void DeleteProperty(int property) - { - if (properties.ContainsKey(property)) - { - properties.JRemove(property); - } - else - { - if (modelElement != null) - { - modelElement.DeleteOwnProperty(property); - } - } - } - - public virtual T1 GetProperty(int key) - { - Object property; - if ((property = properties.Get(key)) != null || properties.ContainsKey(key)) - { - return (T1)property; - } - if (modelElement != null && ((property = modelElement.GetProperty(key)) != null - || modelElement.HasProperty(key))) - { - return (T1)property; - } - // TODO in some situations we will want to check inheritance with additional info, such as parent and descendant. - if (parent != null && Property.IsPropertyInherited(key) && (property = parent.GetProperty(key)) != null) - { - return (T1)property; - } - property = this.GetDefaultProperty(key); - if (property != null) - { - return (T1)property; - } - return modelElement != null ? modelElement.GetDefaultProperty(key) : (T1)(Object - )null; - } - - public virtual T1 GetOwnProperty(int property) - { - return (T1)properties.Get(property); - } - - public virtual T1 GetProperty(int property, T1 defaultValue) - { - T1 result = this.GetProperty(property); - return result != null ? result : defaultValue; - } - - public virtual void SetProperty(int property, Object value) - { - properties[property] = value; - } - - public virtual T1 GetDefaultProperty(int property) - { - return (T1)(Object)null; - } - - /// Returns a property with a certain key, as a font object. - /// - /// an - /// enum value - /// - /// - /// a - /// - /// - public virtual PdfFont GetPropertyAsFont(int property) - { - return this.GetProperty(property); - } - - /// Returns a property with a certain key, as a color. - /// - /// an - /// enum value - /// - /// - /// a - //Color="Color.Color"/> - /// - public virtual Color GetPropertyAsColor(int property) - { - return this.GetProperty(property); - } - - /// Returns a property with a certain key, as a boolean value. - /// - /// an - /// enum value - /// - /// - /// a - /// - /// - public virtual bool? GetPropertyAsBoolean(int property) - { - return this.GetProperty(property); - } - - public override String ToString() - { - StringBuilder sb = new StringBuilder(); - foreach (IRenderer renderer in childRenderers) - { - sb.Append(renderer.ToString()); - } - return sb.ToString(); - } - - public virtual LayoutArea GetOccupiedArea() - { - return occupiedArea; - } - - public virtual void Draw(DrawContext drawContext) - { - ApplyDestination(drawContext.GetDocument()); - ApplyAction(drawContext.GetDocument()); - bool relativePosition = IsRelativePosition(); - if (relativePosition) - { - ApplyAbsolutePositioningTranslation(false); - } - DrawBackground(drawContext); - DrawBorder(drawContext); - DrawChildren(drawContext); - if (relativePosition) - { - ApplyAbsolutePositioningTranslation(true); - } - flushed = true; - } - - /// - /// Draws a background layer if it is defined by a key - /// - /// in either the layout element or this - /// - /// itself. - /// - /// the context (canvas, document, etc) of this drawing operation. - /// - public virtual void DrawBackground(DrawContext drawContext) - { - Background background = this.GetProperty(Property.BACKGROUND); - if (background != null) - { - Rectangle bBox = GetOccupiedAreaBBox(); - bool isTagged = drawContext.IsTaggingEnabled() && GetModelElement() is IAccessibleElement; - if (isTagged) - { - drawContext.GetCanvas().OpenTag(new CanvasArtifact()); - } - Rectangle backgroundArea = ApplyMargins(bBox, false); - if (backgroundArea.GetWidth() <= 0 || backgroundArea.GetHeight() <= 0) - { - ILogger logger = LoggerFactory.GetLogger(typeof(iText.Layout.Renderer.AbstractRenderer - )); - logger.Error(String.Format(LogMessageConstant.RECTANGLE_HAS_NEGATIVE_OR_ZERO_SIZES - , "background")); - return; - } - drawContext.GetCanvas().SaveState().SetFillColor(background.GetColor()).Rectangle - (backgroundArea.GetX() - background.GetExtraLeft(), backgroundArea.GetY() - background - .GetExtraBottom(), backgroundArea.GetWidth() + background.GetExtraLeft() + background - .GetExtraRight(), backgroundArea.GetHeight() + background.GetExtraTop() + background - .GetExtraBottom()).Fill().RestoreState(); - if (isTagged) - { - drawContext.GetCanvas().CloseTag(); - } - } - } - - /// - /// Performs the drawing operation for all - /// children - /// of this renderer. - /// - /// the context (canvas, document, etc) of this drawing operation. - /// - public virtual void DrawChildren(DrawContext drawContext) - { - foreach (IRenderer child in childRenderers) - { - child.Draw(drawContext); - } - } - - /// - /// Performs the drawing operation for the border of this renderer, if - /// defined by any of the - /// - /// values in either the layout - /// element or this - /// - /// itself. - /// - /// the context (canvas, document, etc) of this drawing operation. - /// - public virtual void DrawBorder(DrawContext drawContext) - { - Border[] borders = GetBorders(); - bool gotBorders = false; - foreach (Border border in borders) - { - gotBorders = gotBorders || border != null; - } - if (gotBorders) - { - float topWidth = borders[0] != null ? borders[0].GetWidth() : 0; - float rightWidth = borders[1] != null ? borders[1].GetWidth() : 0; - float bottomWidth = borders[2] != null ? borders[2].GetWidth() : 0; - float leftWidth = borders[3] != null ? borders[3].GetWidth() : 0; - Rectangle bBox = GetBorderAreaBBox(); - if (bBox.GetWidth() <= 0 || bBox.GetHeight() <= 0) - { - ILogger logger = LoggerFactory.GetLogger(typeof(iText.Layout.Renderer.AbstractRenderer - )); - logger.Error(String.Format(LogMessageConstant.RECTANGLE_HAS_NEGATIVE_OR_ZERO_SIZES - , "border")); - return; - } - float x1 = bBox.GetX(); - float y1 = bBox.GetY(); - float x2 = bBox.GetX() + bBox.GetWidth(); - float y2 = bBox.GetY() + bBox.GetHeight(); - bool isTagged = drawContext.IsTaggingEnabled() && GetModelElement() is IAccessibleElement; - PdfCanvas canvas = drawContext.GetCanvas(); - if (isTagged) - { - canvas.OpenTag(new CanvasArtifact()); - } - if (borders[0] != null) - { - canvas.SaveState(); - borders[0].Draw(canvas, x1, y2, x2, y2, leftWidth, rightWidth); - canvas.RestoreState(); - } - if (borders[1] != null) - { - canvas.SaveState(); - borders[1].Draw(canvas, x2, y2, x2, y1, topWidth, bottomWidth); - canvas.RestoreState(); - } - if (borders[2] != null) - { - canvas.SaveState(); - borders[2].Draw(canvas, x2, y1, x1, y1, rightWidth, leftWidth); - canvas.RestoreState(); - } - if (borders[3] != null) - { - canvas.SaveState(); - borders[3].Draw(canvas, x1, y1, x1, y2, bottomWidth, topWidth); - canvas.RestoreState(); - } - if (isTagged) - { - canvas.CloseTag(); - } - } - } - - public virtual bool IsFlushed() - { - return flushed; - } - - public virtual IRenderer SetParent(IRenderer parent) - { - this.parent = parent; - return this; - } - - public virtual void Move(float dxRight, float dyUp) - { - occupiedArea.GetBBox().MoveRight(dxRight); - occupiedArea.GetBBox().MoveUp(dyUp); - foreach (IRenderer childRenderer in childRenderers) - { - childRenderer.Move(dxRight, dyUp); - } - } - - /// - /// Gets all rectangles that this - /// - /// can draw upon in the given area. - /// - /// - /// a physical area on the - /// - /// - /// - /// a list of - /// rectangles - /// - public virtual IList InitElementAreas(LayoutArea area) - { - return JavaCollectionsUtil.SingletonList(area.GetBBox()); - } - - /// - /// Gets the bounding box that contains all content written to the - /// - /// by this - /// - /// . - /// - /// - /// the smallest - /// - /// that surrounds the content - /// - public virtual Rectangle GetOccupiedAreaBBox() - { - return occupiedArea.GetBBox().Clone(); - } - - /// Gets the border box of a renderer. - /// - /// Gets the border box of a renderer. - /// This is a box used to draw borders. - /// - /// border box of a renderer - public virtual Rectangle GetBorderAreaBBox() - { - Rectangle rect = GetOccupiedAreaBBox(); - ApplyMargins(rect, false); - ApplyBorderBox(rect, false); - return rect; - } - - public virtual Rectangle GetInnerAreaBBox() - { - Rectangle rect = GetOccupiedAreaBBox(); - ApplyMargins(rect, false); - ApplyBorderBox(rect, false); - ApplyPaddings(rect, false); - return rect; - } - - protected internal virtual float? RetrieveWidth(float parentBoxWidth) - { - return RetrieveUnitValue(parentBoxWidth, Property.WIDTH); - } - - protected internal virtual float? RetrieveHeight() - { - return this.GetProperty(Property.HEIGHT); - } - - protected internal virtual float? RetrieveUnitValue(float basePercentValue, int property - ) - { - UnitValue value = this.GetProperty(property); - if (value != null) - { - if (value.GetUnitType() == UnitValue.POINT) - { - return value.GetValue(); - } - else - { - if (value.GetUnitType() == UnitValue.PERCENT) - { - return value.GetValue() * basePercentValue / 100; - } - else - { - throw new InvalidOperationException("invalid unit type"); - } - } - } - else - { - return null; - } - } - - //TODO is behavior of copying all properties in split case common to all renderers? - protected internal virtual IDictionary GetOwnProperties() - { - return properties; - } - - protected internal virtual void AddAllProperties(IDictionary properties - ) - { - this.properties.AddAll(properties); - } - - /// Gets the first yLine of the nested children recursively. - /// - /// Gets the first yLine of the nested children recursively. E.g. for a list, this will be the yLine of the - /// first item (if the first item is indeed a paragraph). - /// NOTE: this method will no go further than the first child. - /// Returns null if there is no text found. - /// - protected internal virtual float? GetFirstYLineRecursively() - { - if (childRenderers.Count == 0) - { - return null; - } - return ((iText.Layout.Renderer.AbstractRenderer)childRenderers[0]).GetFirstYLineRecursively - (); - } - - protected internal virtual Rectangle ApplyMargins(Rectangle rect, bool reverse) - { - return this.ApplyMargins(rect, GetMargins(), reverse); - } - - protected internal virtual Rectangle ApplyMargins(Rectangle rect, float[] margins - , bool reverse) - { - if (IsPositioned()) - { - return rect; - } - return rect.ApplyMargins(margins[0], margins[1], margins[2], margins[3 - ], reverse); - } - - protected internal virtual float[] GetMargins() - { - return new float[] { (float)this.GetPropertyAsFloat(Property.MARGIN_TOP), - (float)this.GetPropertyAsFloat(Property.MARGIN_RIGHT), - (float)this.GetPropertyAsFloat(Property.MARGIN_BOTTOM), - (float)this.GetPropertyAsFloat(Property.MARGIN_LEFT) }; - } - - protected internal virtual float[] GetPaddings() - { - return new float[] { (float)this.GetPropertyAsFloat(Property.PADDING_TOP), - (float)this.GetPropertyAsFloat(Property.PADDING_RIGHT), - (float)this.GetPropertyAsFloat(Property.PADDING_BOTTOM), - (float)this.GetPropertyAsFloat(Property.PADDING_LEFT) }; - } - - protected internal virtual Rectangle ApplyPaddings(Rectangle rect, bool reverse) - { - return ApplyPaddings(rect, GetPaddings(), reverse); - } - - protected internal virtual Rectangle ApplyPaddings(Rectangle rect, float[] paddings - , bool reverse) - { - return rect.ApplyMargins(paddings[0], paddings[1], paddings[2], paddings - [3], reverse); - } - - protected internal virtual Rectangle ApplyBorderBox(Rectangle rect, bool reverse) - { - Border[] borders = GetBorders(); - return ApplyBorderBox(rect, borders, reverse); - } - - protected internal virtual Rectangle ApplyBorderBox(Rectangle rect, Border[] borders, bool reverse) - { - float topWidth = borders[0] != null ? borders[0].GetWidth() : 0; - float rightWidth = borders[1] != null ? borders[1].GetWidth() : 0; - float bottomWidth = borders[2] != null ? borders[2].GetWidth() : 0; - float leftWidth = borders[3] != null ? borders[3].GetWidth() : 0; - return rect.ApplyMargins(topWidth, rightWidth, bottomWidth, leftWidth, - reverse); - } - - protected internal virtual void ApplyAbsolutePositioningTranslation(bool reverse) - { - float top = (float)this.GetPropertyAsFloat(Property.TOP); - float bottom = (float)this.GetPropertyAsFloat(Property.BOTTOM); - float left = (float)this.GetPropertyAsFloat(Property.LEFT); - float right = (float)this.GetPropertyAsFloat(Property.RIGHT); - int reverseMultiplier = reverse ? -1 : 1; - float dxRight = left != 0 ? left * reverseMultiplier : -right * reverseMultiplier; - float dyUp = top != 0 ? -top * reverseMultiplier : bottom * reverseMultiplier; - if (dxRight != 0 || dyUp != 0) - { - Move(dxRight, dyUp); - } - } - - protected internal virtual void ApplyDestination(PdfDocument document) - { - String destination = this.GetProperty(Property.DESTINATION); - if (destination != null) - { - PdfArray array = new PdfArray(); - array.Add(document.GetPage(occupiedArea.GetPageNumber()).GetPdfObject()); - array.Add(PdfName.XYZ); - array.Add(new PdfNumber(occupiedArea.GetBBox().GetX())); - array.Add(new PdfNumber(occupiedArea.GetBBox().GetY() + occupiedArea.GetBBox().GetHeight - ())); - array.Add(new PdfNumber(1)); - document.AddNamedDestination(destination, ((PdfArray)array.MakeIndirect(document) - )); - DeleteProperty(Property.DESTINATION); - } - } - - protected internal virtual void ApplyAction(PdfDocument document) - { - PdfAction action = this.GetProperty(Property.ACTION); - if (action != null) - { - PdfLinkAnnotation link = new PdfLinkAnnotation(GetOccupiedArea().GetBBox()); - link.SetAction(action); - Border border = this.GetProperty(Property.BORDER); - if (border != null) - { - link.SetBorder(new PdfArray(new float[] { 0, 0, border.GetWidth() })); - } - else - { - link.SetBorder(new PdfArray(new float[] { 0, 0, 0 })); - } - document.GetPage(GetOccupiedArea().GetPageNumber()).AddAnnotation(link); - } - } - - protected internal virtual bool IsNotFittingHeight(LayoutArea layoutArea) - { - Rectangle area = ApplyMargins(layoutArea.GetBBox().Clone(), false); - area = ApplyPaddings(area, false); - return !IsPositioned() && occupiedArea.GetBBox().GetHeight() > area.GetHeight(); - } - - protected internal virtual bool IsPositioned() - { - Object positioning = this.GetProperty(Property.POSITION); - return System.Convert.ToInt32(LayoutPosition.FIXED).Equals(positioning); - } - - protected internal virtual bool IsFixedLayout() - { - Object positioning = this.GetProperty(Property.POSITION); - return System.Convert.ToInt32(LayoutPosition.FIXED).Equals(positioning); - } - - protected internal virtual bool IsRelativePosition() - { - int? positioning = this.GetPropertyAsInteger(Property.POSITION); - return System.Convert.ToInt32(LayoutPosition.RELATIVE).Equals(positioning); - } - - protected internal virtual bool IsKeepTogether() - { - return true.Equals(GetPropertyAsBoolean(Property.KEEP_TOGETHER)); - } - - protected internal virtual void AlignChildHorizontally(IRenderer childRenderer, float - availableWidth) - { - HorizontalAlignment? horizontalAlignment = childRenderer.GetProperty + /// Defines the most common properties and behavior that are shared by most + /// + /// implementations. All default Renderers are subclasses of + /// this default implementation. + /// + public abstract class AbstractRenderer : IRenderer { + /// + /// The maximum difference between + /// + /// coordinates to consider rectangles equal + /// + public const float EPS = 1e-4f; + + /// The infinity value which is used while layouting + public const float INF = 1e6f; + + protected internal IList childRenderers = new List(); + + protected internal IList positionedRenderers = new List(); + + protected internal IPropertyContainer modelElement; + + protected internal bool flushed = false; + + protected internal LayoutArea occupiedArea; + + protected internal IRenderer parent; + + protected internal IDictionary properties = new Dictionary(); + + protected internal bool isLastRendererForModelElement = true; + + /// Creates a renderer. + protected internal AbstractRenderer() { + } + + /// Creates a renderer for the specified layout element. + /// the layout element that will be drawn by this renderer + protected internal AbstractRenderer(IElement modelElement) { + // TODO linkedList? + this.modelElement = modelElement; + } + + protected internal AbstractRenderer(iText.Layout.Renderer.AbstractRenderer other + ) { + this.childRenderers = other.childRenderers; + this.positionedRenderers = other.positionedRenderers; + this.modelElement = other.modelElement; + this.flushed = other.flushed; + this.occupiedArea = other.occupiedArea.Clone(); + this.parent = other.parent; + this.properties.AddAll(other.properties); + this.isLastRendererForModelElement = other.isLastRendererForModelElement; + } + + /// + public virtual void AddChild(IRenderer renderer) { + // https://www.webkit.org/blog/116/webcore-rendering-iii-layout-basics + // "The rules can be summarized as follows:"... + int? positioning = renderer.GetProperty(Property.POSITION); + if (positioning == null || positioning == LayoutPosition.RELATIVE || positioning + == LayoutPosition.STATIC) { + childRenderers.Add(renderer); + } + else { + if (positioning == LayoutPosition.FIXED) { + iText.Layout.Renderer.AbstractRenderer root = this; + while (root.parent is iText.Layout.Renderer.AbstractRenderer) { + root = (iText.Layout.Renderer.AbstractRenderer) root.parent; + } + if (root == this) { + positionedRenderers.Add(renderer); + } + else { + root.AddChild(renderer); + } + } + } + } + + /// + public virtual IPropertyContainer GetModelElement() { + return modelElement; + } + + /// + public virtual IList GetChildRenderers() { + return childRenderers; + } + + /// + public virtual bool HasProperty(int property) { + return HasOwnProperty(property) || (modelElement != null && modelElement.HasProperty + (property)) || + (parent != null && Property.IsPropertyInherited(property) && parent.HasProperty(property)); + } + + /// + public virtual bool HasOwnProperty(int property) { + return properties.ContainsKey(property); + } + + /// + /// Checks if this renderer or its model element have the specified property, + /// i.e. if it was set to this very element or its very model element earlier. + /// + /// the property to be checked + /// + /// true if this instance or its model element have given own property, false otherwise + /// + public bool HasOwnOrModelProperty(int property) { + return properties.ContainsKey(property) || + (null != GetModelElement() && GetModelElement().HasProperty(property)); + } + + /// + public virtual void DeleteOwnProperty(int property) { + properties.JRemove(property); + } + + /// + /// Deletes property from this very renderer, or in case the property is specified on its model element, the + /// property of the model element is deleted + /// + /// the property key to be deleted + public virtual void DeleteProperty(int property) { + if (properties.ContainsKey(property)) { + properties.JRemove(property); + } + else { + if (modelElement != null) { + modelElement.DeleteOwnProperty(property); + } + } + } + + /// + public virtual T1 GetProperty(int key) { + Object property; + if ((property = properties.Get(key)) != null || properties.ContainsKey(key)) { + return (T1) property; + } + if (modelElement != null && ((property = modelElement.GetProperty(key)) != null + || modelElement.HasProperty(key))) { + return (T1) property; + } + // TODO in some situations we will want to check inheritance with additional info, such as parent and descendant. + if (parent != null && Property.IsPropertyInherited(key) && (property = parent.GetProperty(key)) != null) { + return (T1) property; + } + property = this.GetDefaultProperty(key); + if (property != null) { + return (T1) property; + } + return modelElement != null + ? modelElement.GetDefaultProperty(key) + : (T1) (Object + ) null; + } + + public virtual T1 GetOwnProperty(int property) { + return (T1) properties.Get(property); + } + + /// + public virtual T1 GetProperty(int property, T1 defaultValue) { + T1 result = this.GetProperty(property); + return result != null ? result : defaultValue; + } + + /// + public virtual void SetProperty(int property, Object value) { + properties[property] = value; + } + + /// + public virtual T1 GetDefaultProperty(int property) { + return (T1) (Object) null; + } + + /// Returns a property with a certain key, as a font object. + /// + /// an + /// enum value + /// + /// + /// a + /// + /// + public virtual PdfFont GetPropertyAsFont(int property) { + return this.GetProperty(property); + } + + /// Returns a property with a certain key, as a color. + /// + /// an + /// enum value + /// + /// + /// a + /// + /// + public virtual Color GetPropertyAsColor(int property) { + return this.GetProperty(property); + } + + /// Returns a property with a certain key, as a boolean value. + /// + /// an + /// enum value + /// + /// + /// a + /// + /// + public virtual bool? GetPropertyAsBoolean(int property) { + return this.GetProperty(property); + } + + public override String ToString() { + StringBuilder sb = new StringBuilder(); + foreach (IRenderer renderer in childRenderers) { + sb.Append(renderer.ToString()); + } + return sb.ToString(); + } + + /// + public virtual LayoutArea GetOccupiedArea() { + return occupiedArea; + } + + /// + public virtual void Draw(DrawContext drawContext) { + ApplyDestination(drawContext.GetDocument()); + ApplyAction(drawContext.GetDocument()); + bool relativePosition = IsRelativePosition(); + if (relativePosition) { + ApplyAbsolutePositioningTranslation(false); + } + DrawBackground(drawContext); + DrawBorder(drawContext); + DrawChildren(drawContext); + if (relativePosition) { + ApplyAbsolutePositioningTranslation(true); + } + flushed = true; + } + + /// + /// Draws a background layer if it is defined by a key + /// + /// in either the layout element or this + /// + /// itself. + /// + /// the context (canvas, document, etc) of this drawing operation. + public virtual void DrawBackground(DrawContext drawContext) { + Background background = this.GetProperty(Property.BACKGROUND); + if (background != null) { + Rectangle bBox = GetOccupiedAreaBBox(); + bool isTagged = drawContext.IsTaggingEnabled() && GetModelElement() is IAccessibleElement; + if (isTagged) { + drawContext.GetCanvas().OpenTag(new CanvasArtifact()); + } + Rectangle backgroundArea = ApplyMargins(bBox, false); + if (backgroundArea.GetWidth() <= 0 || backgroundArea.GetHeight() <= 0) { + ILogger logger = LoggerFactory.GetLogger(typeof (iText.Layout.Renderer.AbstractRenderer + )); + logger.Error(String.Format(LogMessageConstant.RECTANGLE_HAS_NEGATIVE_OR_ZERO_SIZES + , "background")); + return; + } + drawContext.GetCanvas().SaveState().SetFillColor(background.GetColor()).Rectangle + (backgroundArea.GetX() - background.GetExtraLeft(), backgroundArea.GetY() - background + .GetExtraBottom(), backgroundArea.GetWidth() + background.GetExtraLeft() + background + .GetExtraRight(), backgroundArea.GetHeight() + background.GetExtraTop() + background + .GetExtraBottom()).Fill().RestoreState(); + if (isTagged) { + drawContext.GetCanvas().CloseTag(); + } + } + } + + /// + /// Performs the drawing operation for all + /// children + /// of this renderer. + /// + /// the context (canvas, document, etc) of this drawing operation. + public virtual void DrawChildren(DrawContext drawContext) { + foreach (IRenderer child in childRenderers) { + child.Draw(drawContext); + } + } + + /// + /// Performs the drawing operation for the border of this renderer, if + /// defined by any of the + /// + /// values in either the layout + /// element or this + /// + /// itself. + /// + /// the context (canvas, document, etc) of this drawing operation. + public virtual void DrawBorder(DrawContext drawContext) { + Border[] borders = GetBorders(); + bool gotBorders = false; + foreach (Border border in borders) { + gotBorders = gotBorders || border != null; + } + if (gotBorders) { + float topWidth = borders[0] != null ? borders[0].GetWidth() : 0; + float rightWidth = borders[1] != null ? borders[1].GetWidth() : 0; + float bottomWidth = borders[2] != null ? borders[2].GetWidth() : 0; + float leftWidth = borders[3] != null ? borders[3].GetWidth() : 0; + Rectangle bBox = GetBorderAreaBBox(); + if (bBox.GetWidth() <= 0 || bBox.GetHeight() <= 0) { + ILogger logger = LoggerFactory.GetLogger(typeof (iText.Layout.Renderer.AbstractRenderer + )); + logger.Error(String.Format(LogMessageConstant.RECTANGLE_HAS_NEGATIVE_OR_ZERO_SIZES + , "border")); + return; + } + float x1 = bBox.GetX(); + float y1 = bBox.GetY(); + float x2 = bBox.GetX() + bBox.GetWidth(); + float y2 = bBox.GetY() + bBox.GetHeight(); + bool isTagged = drawContext.IsTaggingEnabled() && GetModelElement() is IAccessibleElement; + PdfCanvas canvas = drawContext.GetCanvas(); + if (isTagged) { + canvas.OpenTag(new CanvasArtifact()); + } + if (borders[0] != null) { + canvas.SaveState(); + borders[0].Draw(canvas, x1, y2, x2, y2, leftWidth, rightWidth); + canvas.RestoreState(); + } + if (borders[1] != null) { + canvas.SaveState(); + borders[1].Draw(canvas, x2, y2, x2, y1, topWidth, bottomWidth); + canvas.RestoreState(); + } + if (borders[2] != null) { + canvas.SaveState(); + borders[2].Draw(canvas, x2, y1, x1, y1, rightWidth, leftWidth); + canvas.RestoreState(); + } + if (borders[3] != null) { + canvas.SaveState(); + borders[3].Draw(canvas, x1, y1, x1, y2, bottomWidth, topWidth); + canvas.RestoreState(); + } + if (isTagged) { + canvas.CloseTag(); + } + } + } + + /// Indicates whether this renderer is flushed or not, i.e. + /// + /// Indicates whether this renderer is flushed or not, i.e. if + /// + /// has already + /// been called. + /// + /// whether the renderer has been flushed + /// + public virtual bool IsFlushed() { + return flushed; + } + + /// + public virtual IRenderer SetParent(IRenderer parent) { + this.parent = parent; + return this; + } + + public virtual void Move(float dxRight, float dyUp) { + occupiedArea.GetBBox().MoveRight(dxRight); + occupiedArea.GetBBox().MoveUp(dyUp); + foreach (IRenderer childRenderer in childRenderers) { + childRenderer.Move(dxRight, dyUp); + } + } + + /// + /// Gets all rectangles that this + /// + /// can draw upon in the given area. + /// + /// + /// a physical area on the + /// + /// + /// + /// a list of + /// rectangles + /// + public virtual IList InitElementAreas(LayoutArea area) { + return JavaCollectionsUtil.SingletonList(area.GetBBox()); + } + + /// + /// Gets the bounding box that contains all content written to the + /// + /// by this + /// + /// . + /// + /// + /// the smallest + /// + /// that surrounds the content + /// + public virtual Rectangle GetOccupiedAreaBBox() { + return occupiedArea.GetBBox().Clone(); + } + + /// Gets the border box of a renderer. + /// + /// Gets the border box of a renderer. + /// This is a box used to draw borders. + /// + /// border box of a renderer + public virtual Rectangle GetBorderAreaBBox() { + Rectangle rect = GetOccupiedAreaBBox(); + ApplyMargins(rect, false); + ApplyBorderBox(rect, false); + return rect; + } + + public virtual Rectangle GetInnerAreaBBox() { + Rectangle rect = GetOccupiedAreaBBox(); + ApplyMargins(rect, false); + ApplyBorderBox(rect, false); + ApplyPaddings(rect, false); + return rect; + } + + protected internal virtual float? RetrieveWidth(float parentBoxWidth) { + return RetrieveUnitValue(parentBoxWidth, Property.WIDTH); + } + + protected internal virtual float? RetrieveHeight() { + return this.GetProperty(Property.HEIGHT); + } + + protected internal virtual float? RetrieveUnitValue(float basePercentValue, int property + ) { + UnitValue value = this.GetProperty(property); + if (value != null) { + if (value.GetUnitType() == UnitValue.POINT) { + return value.GetValue(); + } + else { + if (value.GetUnitType() == UnitValue.PERCENT) { + return value.GetValue()*basePercentValue/100; + } + else { + throw new InvalidOperationException("invalid unit type"); + } + } + } + else { + return null; + } + } + + //TODO is behavior of copying all properties in split case common to all renderers? + protected internal virtual IDictionary GetOwnProperties() { + return properties; + } + + protected internal virtual void AddAllProperties(IDictionary properties + ) { + this.properties.AddAll(properties); + } + + /// Gets the first yLine of the nested children recursively. + /// + /// Gets the first yLine of the nested children recursively. E.g. for a list, this will be the yLine of the + /// first item (if the first item is indeed a paragraph). + /// NOTE: this method will no go further than the first child. + /// Returns null if there is no text found. + /// + protected internal virtual float? GetFirstYLineRecursively() { + if (childRenderers.Count == 0) { + return null; + } + return ((iText.Layout.Renderer.AbstractRenderer) childRenderers[0]).GetFirstYLineRecursively + (); + } + + /// Applies margins of the renderer on the given rectangle + /// a rectangle margins will be applied on. + /// + /// indicates whether margins will be applied + /// inside (in case of false) or outside (in case of false) the rectangle. + /// + /// + /// a + /// border box + /// of the renderer + /// + /// + protected internal virtual Rectangle ApplyMargins(Rectangle rect, bool reverse) { + return this.ApplyMargins(rect, GetMargins(), reverse); + } + + /// Applies given margins on the given rectangle + /// a rectangle margins will be applied on. + /// the margins to be applied on the given rectangle + /// + /// indicates whether margins will be applied + /// inside (in case of false) or outside (in case of false) the rectangle. + /// + /// + /// a + /// border box + /// of the renderer + /// + protected internal virtual Rectangle ApplyMargins(Rectangle rect, float[] margins + , bool reverse) { + if (IsPositioned()) { + return rect; + } + return rect.ApplyMargins(margins[0], margins[1], margins[2], margins[3 + ], reverse); + } + + /// Returns margins of the renderer + /// + /// a + /// float[] margins + /// of the renderer + /// + protected internal virtual float[] GetMargins() { + return new float[] { + (float) this.GetPropertyAsFloat(Property.MARGIN_TOP), + (float) this.GetPropertyAsFloat(Property.MARGIN_RIGHT), + (float) this.GetPropertyAsFloat(Property.MARGIN_BOTTOM), + (float) this.GetPropertyAsFloat(Property.MARGIN_LEFT) + }; + } + + /// Returns paddings of the renderer + /// + /// a + /// float[] paddings + /// of the renderer + /// + protected internal virtual float[] GetPaddings() { + return new float[] { + (float) this.GetPropertyAsFloat(Property.PADDING_TOP), + (float) this.GetPropertyAsFloat(Property.PADDING_RIGHT), + (float) this.GetPropertyAsFloat(Property.PADDING_BOTTOM), + (float) this.GetPropertyAsFloat(Property.PADDING_LEFT) + }; + } + + /// Applies paddings of the renderer on the given rectangle + /// a rectangle paddings will be applied on. + /// + /// indicates whether paddings will be applied + /// inside (in case of false) or outside (in case of false) the rectangle. + /// + /// + /// a + /// border box + /// of the renderer + /// + /// + protected internal virtual Rectangle ApplyPaddings(Rectangle rect, bool reverse) { + return ApplyPaddings(rect, GetPaddings(), reverse); + } + + /// Applies given paddings on the given rectangle + /// a rectangle paddings will be applied on. + /// the paddings to be applied on the given rectangle + /// + /// indicates whether paddings will be applied + /// inside (in case of false) or outside (in case of false) the rectangle. + /// + /// + /// a + /// border box + /// of the renderer + /// + protected internal virtual Rectangle ApplyPaddings(Rectangle rect, float[] paddings + , bool reverse) { + return rect.ApplyMargins(paddings[0], paddings[1], paddings[2], paddings + [3], reverse); + } + + /// + /// Applies the border box of the renderer on the given rectangle + /// If the border of a certain side is null, the side will remain as it was. + /// + /// a rectangle the border box will be applied on. + /// + /// indicates whether the border box will be applied + /// inside (in case of false) or outside (in case of false) the rectangle. + /// + /// + /// a + /// border box + /// of the renderer + /// + /// + protected internal virtual Rectangle ApplyBorderBox(Rectangle rect, bool reverse) { + Border[] borders = GetBorders(); + return ApplyBorderBox(rect, borders, reverse); + } + + /// Applies the given border box (borders) on the given rectangle + /// a rectangle paddings will be applied on. + /// + /// the + /// borders + /// to be applied on the given rectangle + /// + /// + /// indicates whether the border box will be applied + /// inside (in case of false) or outside (in case of false) the rectangle. + /// + /// + /// a + /// border box + /// of the renderer + /// + protected internal virtual Rectangle ApplyBorderBox(Rectangle rect, Border[] borders, bool reverse) { + float topWidth = borders[0] != null ? borders[0].GetWidth() : 0; + float rightWidth = borders[1] != null ? borders[1].GetWidth() : 0; + float bottomWidth = borders[2] != null ? borders[2].GetWidth() : 0; + float leftWidth = borders[3] != null ? borders[3].GetWidth() : 0; + return rect.ApplyMargins(topWidth, rightWidth, bottomWidth, leftWidth, + reverse); + } + + protected internal virtual void ApplyAbsolutePositioningTranslation(bool reverse) { + float top = (float) this.GetPropertyAsFloat(Property.TOP); + float bottom = (float) this.GetPropertyAsFloat(Property.BOTTOM); + float left = (float) this.GetPropertyAsFloat(Property.LEFT); + float right = (float) this.GetPropertyAsFloat(Property.RIGHT); + int reverseMultiplier = reverse ? -1 : 1; + float dxRight = left != 0 ? left*reverseMultiplier : -right*reverseMultiplier; + float dyUp = top != 0 ? -top*reverseMultiplier : bottom*reverseMultiplier; + if (dxRight != 0 || dyUp != 0) { + Move(dxRight, dyUp); + } + } + + protected internal virtual void ApplyDestination(PdfDocument document) { + String destination = this.GetProperty(Property.DESTINATION); + if (destination != null) { + PdfArray array = new PdfArray(); + array.Add(document.GetPage(occupiedArea.GetPageNumber()).GetPdfObject()); + array.Add(PdfName.XYZ); + array.Add(new PdfNumber(occupiedArea.GetBBox().GetX())); + array.Add(new PdfNumber(occupiedArea.GetBBox().GetY() + occupiedArea.GetBBox().GetHeight + ())); + array.Add(new PdfNumber(1)); + document.AddNamedDestination(destination, ((PdfArray) array.MakeIndirect(document) + )); + DeleteProperty(Property.DESTINATION); + } + } + + protected internal virtual void ApplyAction(PdfDocument document) { + PdfAction action = this.GetProperty(Property.ACTION); + if (action != null) { + PdfLinkAnnotation link = new PdfLinkAnnotation(GetOccupiedArea().GetBBox()); + link.SetAction(action); + Border border = this.GetProperty(Property.BORDER); + if (border != null) { + link.SetBorder(new PdfArray(new float[] {0, 0, border.GetWidth()})); + } + else { + link.SetBorder(new PdfArray(new float[] {0, 0, 0})); + } + document.GetPage(GetOccupiedArea().GetPageNumber()).AddAnnotation(link); + } + } + + [Obsolete("Use {@link #isNotFittingLayoutArea(LayoutArea)} instead.")] + protected internal virtual bool IsNotFittingHeight(LayoutArea layoutArea) { + return IsNotFittingLayoutArea(layoutArea); + } + + protected internal virtual bool IsNotFittingLayoutArea(LayoutArea layoutArea) { + Rectangle area = ApplyMargins(layoutArea.GetBBox().Clone(), false); + area = ApplyPaddings(area, false); + return !IsPositioned() && + (occupiedArea.GetBBox().GetHeight() > area.GetHeight() || + occupiedArea.GetBBox().GetWidth() > area.GetWidth()); + } + + /// Indicates whether the renderer's position is fixed or not. + /// + /// a + /// boolean + /// + protected internal virtual bool IsPositioned() { + return IsFixedLayout(); + } + + /// Indicates whether the renderer's position is fixed or not. + /// + /// a + /// boolean + /// + protected internal virtual bool IsFixedLayout() { + Object positioning = this.GetProperty(Property.POSITION); + return System.Convert.ToInt32(LayoutPosition.FIXED).Equals(positioning); + } + + protected internal virtual bool IsRelativePosition() { + int? positioning = this.GetPropertyAsInteger(Property.POSITION); + return System.Convert.ToInt32(LayoutPosition.RELATIVE).Equals(positioning); + } + + protected internal virtual bool IsKeepTogether() { + return true.Equals(GetPropertyAsBoolean(Property.KEEP_TOGETHER)); + } + + protected internal virtual void AlignChildHorizontally(IRenderer childRenderer, float + availableWidth) { + HorizontalAlignment? horizontalAlignment = childRenderer.GetProperty(Property.HORIZONTAL_ALIGNMENT); - if (horizontalAlignment != null && horizontalAlignment != HorizontalAlignment.LEFT) - { - float freeSpace = availableWidth - childRenderer.GetOccupiedArea().GetBBox().GetWidth - (); - switch (horizontalAlignment) - { - case HorizontalAlignment.RIGHT: - { - childRenderer.Move(freeSpace, 0); - break; - } - - case HorizontalAlignment.CENTER: - { - childRenderer.Move(freeSpace / 2, 0); - break; - } - } - } - } - - /// Gets borders of the element in the specified order: top, right, bottom, left. - /// - /// - /// an array of BorderDrawer objects. - /// In case when certain border isn't set Property.BORDER is used, - /// and if Property.BORDER is also not set then null is returned - /// on position of this border - /// - protected internal virtual Border[] GetBorders() - { - Border border = this.GetProperty(Property.BORDER); - Border topBorder = this.GetProperty(Property.BORDER_TOP); - Border rightBorder = this.GetProperty(Property.BORDER_RIGHT); - Border bottomBorder = this.GetProperty(Property.BORDER_BOTTOM); - Border leftBorder = this.GetProperty(Property.BORDER_LEFT); - Border[] borders = new Border[]{ topBorder, rightBorder, bottomBorder, leftBorder }; - for (int i = 0; i < borders.Length; ++i) - { - if (borders[i] == null) - { - borders[i] = border; - } - } - return borders; - } - - protected internal virtual iText.Layout.Renderer.AbstractRenderer SetBorders(Border border, int borderNumber) { - switch (borderNumber) - { - case 0: - { - SetProperty(Property.BORDER_TOP, border); - break; - } - - case 1: - { - SetProperty(Property.BORDER_RIGHT, border); - break; - } - - case 2: - { - SetProperty(Property.BORDER_BOTTOM, border); - break; - } - - case 3: - { - SetProperty(Property.BORDER_LEFT, border); - break; - } - } - return this; - } - - public abstract IRenderer GetNextRenderer(); - - public abstract LayoutResult Layout(LayoutContext arg1); - } + if (horizontalAlignment != null && horizontalAlignment != HorizontalAlignment.LEFT) { + float freeSpace = availableWidth - childRenderer.GetOccupiedArea().GetBBox().GetWidth + (); + switch (horizontalAlignment) { + case HorizontalAlignment.RIGHT: { + childRenderer.Move(freeSpace, 0); + break; + } + + case HorizontalAlignment.CENTER: { + childRenderer.Move(freeSpace/2, 0); + break; + } + } + } + } + + /// Gets borders of the element in the specified order: top, right, bottom, left. + /// + /// + /// an array of BorderDrawer objects. + /// In case when certain border isn't set Property.BORDER is used, + /// and if Property.BORDER is also not set then null is returned + /// on position of this border + /// + protected internal virtual Border[] GetBorders() { + Border border = this.GetProperty(Property.BORDER); + Border topBorder = this.GetProperty(Property.BORDER_TOP); + Border rightBorder = this.GetProperty(Property.BORDER_RIGHT); + Border bottomBorder = this.GetProperty(Property.BORDER_BOTTOM); + Border leftBorder = this.GetProperty(Property.BORDER_LEFT); + Border[] borders = new Border[] {topBorder, rightBorder, bottomBorder, leftBorder}; + if (!HasOwnOrModelProperty(Property.BORDER_TOP)) { + borders[0] = border; + } + if (!HasOwnOrModelProperty(Property.BORDER_RIGHT)) { + borders[1] = border; + } + if (!HasOwnOrModelProperty(Property.BORDER_BOTTOM)) { + borders[2] = border; + } + if (!HasOwnOrModelProperty(Property.BORDER_LEFT)) { + borders[3] = border; + } + return borders; + } + + protected internal virtual iText.Layout.Renderer.AbstractRenderer SetBorders(Border border, int borderNumber) { + switch (borderNumber) { + case 0: { + SetProperty(Property.BORDER_TOP, border); + break; + } + + case 1: { + SetProperty(Property.BORDER_RIGHT, border); + break; + } + + case 2: { + SetProperty(Property.BORDER_BOTTOM, border); + break; + } + + case 3: { + SetProperty(Property.BORDER_LEFT, border); + break; + } + } + return this; + } + + /** + * Calculates bounding box around points. + * @param points list of the points calculated bbox will enclose. + * @return array of float values which denote left, bottom, right, top lines of bbox in this specific order + */ + + protected Rectangle CalculateBBox(IList points) { + double minX = double.MaxValue; + double minY = double.MaxValue; + double maxX = -double.MaxValue; + double maxY = -double.MaxValue; + foreach (Point p in points) { + minX = Math.Min(p.GetX(), minX); + minY = Math.Min(p.GetY(), minY); + maxX = Math.Max(p.GetX(), maxX); + maxY = Math.Max(p.GetY(), maxY); + } + return new Rectangle((float) minX, (float) minY, (float) (maxX - minX), (float) (maxY - minY)); + } + + protected IList RectangleToPointsList(Rectangle rect) { + IList points = new List(); + points.AddAll(JavaUtil.ArraysAsList(new Point(rect.GetLeft(), rect.GetBottom()), + new Point(rect.GetRight(), rect.GetBottom()), + new Point(rect.GetRight(), rect.GetTop()), new Point(rect.GetLeft(), rect.GetTop()))); + return points; + } + + protected IList TransformPoints(IList points, AffineTransform transform) { + foreach (Point point in points) { + transform.Transform(point, point); + } + + return points; + } + + + /// + /// Calculates the bounding box of the content in the coordinate system of the pdf entity on which content is placed, + /// e.g. document page or form xObject. This is particularly useful for the cases when element is nested in the rotated + /// element. + /// + /// a which is a bbox of the content not relative to the parent's layout area but rather to + /// the some pdf entity coordinate system. + protected Rectangle CalculateAbsolutePdfBBox() { + Rectangle contentBox = GetOccupiedAreaBBox(); + IList contentBoxPoints = RectangleToPointsList(contentBox); + AbstractRenderer renderer = this; + while (renderer.parent != null) { + if (renderer is BlockRenderer) { + float? angle = renderer.GetProperty(Property.ROTATION_ANGLE); + if (angle != null) { + BlockRenderer blockRenderer = (BlockRenderer) renderer; + AffineTransform rotationTransform = blockRenderer.CreateRotationTransformInsideOccupiedArea(); + TransformPoints(contentBoxPoints, rotationTransform); + } + } + + renderer = (AbstractRenderer) renderer.parent; + } + + return CalculateBBox(contentBoxPoints); + } + + public abstract IRenderer GetNextRenderer(); + + public abstract LayoutResult Layout(LayoutContext layoutContext); + } } diff --git a/itext/itext.layout/itext/layout/renderer/AccessibleAttributesApplier.cs b/itext/itext.layout/itext/layout/renderer/AccessibleAttributesApplier.cs index f2cfb143d1..4d41c714f4 100644 --- a/itext/itext.layout/itext/layout/renderer/AccessibleAttributesApplier.cs +++ b/itext/itext.layout/itext/layout/renderer/AccessibleAttributesApplier.cs @@ -135,9 +135,9 @@ public static void ApplyTableAttributes(AbstractRenderer renderer) { } private static void ApplyCommonLayoutAttributes(AbstractRenderer renderer, PdfDictionary attributes) { - Color backgroundColor = renderer.GetPropertyAsColor(Property.BACKGROUND); - if (backgroundColor != null && backgroundColor is DeviceRgb) { - attributes.Put(PdfName.BackgroundColor, new PdfArray(backgroundColor.GetColorValue())); + Background background = renderer.GetProperty(Property.BACKGROUND); + if (background != null && background.GetColor() is DeviceRgb) { + attributes.Put(PdfName.BackgroundColor, new PdfArray(background.GetColor().GetColorValue())); } //TODO NOTE: applying border attributes for cells is temporarily turned off on purpose. Remove this 'if' in future. // The reason is that currently, we can't distinguish if all cells have same border style or not. diff --git a/itext/itext.layout/itext/layout/renderer/AreaBreakRenderer.cs b/itext/itext.layout/itext/layout/renderer/AreaBreakRenderer.cs index 31e91ddeb0..d273ef642a 100644 --- a/itext/itext.layout/itext/layout/renderer/AreaBreakRenderer.cs +++ b/itext/itext.layout/itext/layout/renderer/AreaBreakRenderer.cs @@ -75,7 +75,7 @@ public virtual LayoutResult Layout(LayoutContext layoutContext) { LayoutArea occupiedArea = layoutContext.GetArea().Clone(); occupiedArea.GetBBox().SetHeight(0); occupiedArea.GetBBox().SetWidth(0); - return new LayoutResult(LayoutResult.NOTHING, occupiedArea, null, null).SetAreaBreak(areaBreak); + return new LayoutResult(LayoutResult.NOTHING, occupiedArea, null, null, this).SetAreaBreak(areaBreak); } public virtual void Draw(DrawContext drawContext) { diff --git a/itext/itext.layout/itext/layout/renderer/BlockRenderer.cs b/itext/itext.layout/itext/layout/renderer/BlockRenderer.cs index 6d6626eb5d..601e396387 100644 --- a/itext/itext.layout/itext/layout/renderer/BlockRenderer.cs +++ b/itext/itext.layout/itext/layout/renderer/BlockRenderer.cs @@ -43,6 +43,8 @@ source product. */ using System; using System.Collections.Generic; +using iText.IO; +using iText.IO.Log; using iText.IO.Util; using iText.Kernel.Geom; using iText.Kernel.Pdf; @@ -61,19 +63,20 @@ protected internal BlockRenderer(IElement modelElement) public override LayoutResult Layout(LayoutContext layoutContext) { int pageNumber = layoutContext.GetArea().GetPageNumber(); + bool isPositioned = IsPositioned(); Rectangle parentBBox = layoutContext.GetArea().GetBBox().Clone(); - if (this.GetProperty(Property.ROTATION_ANGLE) != null) { + if (this.GetProperty(Property.ROTATION_ANGLE) != null || isPositioned) { parentBBox.MoveDown(AbstractRenderer.INF - parentBBox.GetHeight()).SetHeight(AbstractRenderer.INF); } float? blockHeight = RetrieveHeight(); - if (!IsFixedLayout() && blockHeight != null && blockHeight > parentBBox.GetHeight()) { - return new LayoutResult(LayoutResult.NOTHING, null, null, this); + if (!IsFixedLayout() && blockHeight != null && blockHeight > parentBBox.GetHeight() && !true.Equals(GetPropertyAsBoolean + (Property.FORCED_PLACEMENT))) { + return new LayoutResult(LayoutResult.NOTHING, null, null, this, this); } float[] margins = GetMargins(); ApplyMargins(parentBBox, margins, false); Border[] borders = GetBorders(); ApplyBorderBox(parentBBox, borders, false); - bool isPositioned = IsPositioned(); if (isPositioned) { float x = (float)this.GetPropertyAsFloat(Property.X); float relativeX = IsFixedLayout() ? 0 : parentBBox.GetX(); @@ -96,6 +99,8 @@ public override LayoutResult Layout(LayoutContext layoutContext) { GetHeight(), parentBBox.GetWidth(), 0)); int currentAreaPos = 0; Rectangle layoutBox = areas[0].Clone(); + // the first renderer (one of childRenderers or their children) to produce LayoutResult.NOTHING + IRenderer causeOfNothing = null; bool anythingPlaced = false; for (int childPos = 0; childPos < childRenderers.Count; childPos++) { IRenderer childRenderer = childRenderers[childPos]; @@ -108,9 +113,13 @@ public override LayoutResult Layout(LayoutContext layoutContext) { ())); layoutBox.SetHeight(layoutBox.GetHeight() - result.GetOccupiedArea().GetBBox().GetHeight()); } - if (childRenderer.GetProperty(Property.WIDTH) != null) { + if (childRenderer.GetOccupiedArea() != null) { AlignChildHorizontally(childRenderer, layoutBox.GetWidth()); } + // Save the first renderer to produce LayoutResult.NOTHING + if (null == causeOfNothing && null != result.GetCauseOfNothing()) { + causeOfNothing = result.GetCauseOfNothing(); + } // have more areas if (currentAreaPos + 1 < areas.Count) { if (result.GetStatus() == LayoutResult.PARTIAL) { @@ -134,6 +143,8 @@ public override LayoutResult Layout(LayoutContext layoutContext) { splitRenderer.childRenderers.Add(result.GetSplitRenderer()); splitRenderer.occupiedArea = occupiedArea; AbstractRenderer overflowRenderer = CreateOverflowRenderer(LayoutResult.PARTIAL); + // Apply forced placement only on split renderer + overflowRenderer.DeleteOwnProperty(Property.FORCED_PLACEMENT); IList overflowRendererChildren = new List(); overflowRendererChildren.Add(result.GetOverflowRenderer()); overflowRendererChildren.AddAll(childRenderers.SubList(childPos + 1, childRenderers.Count)); @@ -141,7 +152,8 @@ public override LayoutResult Layout(LayoutContext layoutContext) { ApplyPaddings(occupiedArea.GetBBox(), paddings, true); ApplyBorderBox(occupiedArea.GetBBox(), borders, true); ApplyMargins(occupiedArea.GetBBox(), margins, true); - return new LayoutResult(LayoutResult.PARTIAL, occupiedArea, splitRenderer, overflowRenderer); + return new LayoutResult(LayoutResult.PARTIAL, occupiedArea, splitRenderer, overflowRenderer, causeOfNothing + ); } else { childRenderers[childPos] = result.GetSplitRenderer(); @@ -176,7 +188,8 @@ public override LayoutResult Layout(LayoutContext layoutContext) { return new LayoutResult(LayoutResult.FULL, occupiedArea, null, null); } else { - return new LayoutResult(layoutResult, occupiedArea, splitRenderer, overflowRenderer); + return new LayoutResult(layoutResult, occupiedArea, splitRenderer, overflowRenderer, LayoutResult.NOTHING + == layoutResult ? result.GetCauseOfNothing() : null); } } } @@ -187,10 +200,14 @@ public override LayoutResult Layout(LayoutContext layoutContext) { ())); if (result.GetStatus() == LayoutResult.FULL) { layoutBox.SetHeight(layoutBox.GetHeight() - result.GetOccupiedArea().GetBBox().GetHeight()); - if (childRenderer.GetProperty(Property.WIDTH) != null) { + if (childRenderer.GetOccupiedArea() != null) { AlignChildHorizontally(childRenderer, layoutBox.GetWidth()); } } + // Save the first renderer to produce LayoutResult.NOTHING + if (null == causeOfNothing && null != result.GetCauseOfNothing()) { + causeOfNothing = result.GetCauseOfNothing(); + } } ApplyPaddings(occupiedArea.GetBBox(), paddings, true); if (blockHeight != null && blockHeight > occupiedArea.GetBBox().GetHeight()) { @@ -206,14 +223,14 @@ public override LayoutResult Layout(LayoutContext layoutContext) { ApplyMargins(occupiedArea.GetBBox(), margins, true); if (this.GetProperty(Property.ROTATION_ANGLE) != null) { ApplyRotationLayout(layoutContext.GetArea().GetBBox().Clone()); - if (IsNotFittingHeight(layoutContext.GetArea())) { + if (IsNotFittingLayoutArea(layoutContext.GetArea())) { if (!true.Equals(GetPropertyAsBoolean(Property.FORCED_PLACEMENT))) { - return new LayoutResult(LayoutResult.NOTHING, occupiedArea, null, this); + return new LayoutResult(LayoutResult.NOTHING, occupiedArea, null, this, this); } } } ApplyVerticalAlignment(); - return new LayoutResult(LayoutResult.FULL, occupiedArea, null, null); + return new LayoutResult(LayoutResult.FULL, occupiedArea, null, null, causeOfNothing); } protected internal virtual AbstractRenderer CreateSplitRenderer(int layoutResult) { @@ -229,7 +246,7 @@ protected internal virtual AbstractRenderer CreateOverflowRenderer(int layoutRes AbstractRenderer overflowRenderer = (AbstractRenderer)GetNextRenderer(); overflowRenderer.parent = parent; overflowRenderer.modelElement = modelElement; - overflowRenderer.properties = properties; + overflowRenderer.properties = new Dictionary(properties); return overflowRenderer; } @@ -285,8 +302,16 @@ public override Rectangle GetOccupiedAreaBBox() { Rectangle bBox = occupiedArea.GetBBox().Clone(); float? rotationAngle = this.GetProperty(Property.ROTATION_ANGLE); if (rotationAngle != null) { - bBox.SetWidth((float)this.GetPropertyAsFloat(Property.ROTATION_INITIAL_WIDTH)); - bBox.SetHeight((float)this.GetPropertyAsFloat(Property.ROTATION_INITIAL_HEIGHT)); + if (!HasOwnProperty(Property.ROTATION_INITIAL_HEIGHT) || !HasOwnProperty(Property.ROTATION_INITIAL_HEIGHT) + ) { + ILogger logger = LoggerFactory.GetLogger(typeof(iText.Layout.Renderer.BlockRenderer)); + logger.Error(String.Format(LogMessageConstant.ROTATION_WAS_NOT_CORRECTLY_PROCESSED_FOR_RENDERER, GetType() + .Name)); + } + else { + bBox.SetWidth((float)this.GetPropertyAsFloat(Property.ROTATION_INITIAL_WIDTH)); + bBox.SetHeight((float)this.GetPropertyAsFloat(Property.ROTATION_INITIAL_HEIGHT)); + } } return bBox; } @@ -315,126 +340,135 @@ protected internal virtual void ApplyVerticalAlignment() { } protected internal virtual void ApplyRotationLayout(Rectangle layoutBox) { - float? rotationPointX = this.GetPropertyAsFloat(Property.ROTATION_POINT_X); - float? rotationPointY = this.GetPropertyAsFloat(Property.ROTATION_POINT_Y); - if (rotationPointX == null || rotationPointY == null) { - // if rotation point was not specified, the most bottom-left point is used - rotationPointX = occupiedArea.GetBBox().GetX(); - rotationPointY = occupiedArea.GetBBox().GetY(); - SetProperty(Property.ROTATION_POINT_X, rotationPointX); - SetProperty(Property.ROTATION_POINT_Y, rotationPointY); - } + float angle = (float)this.GetPropertyAsFloat(Property.ROTATION_ANGLE); + float x = occupiedArea.GetBBox().GetX(); + float y = occupiedArea.GetBBox().GetY(); float height = occupiedArea.GetBBox().GetHeight(); float width = occupiedArea.GetBBox().GetWidth(); SetProperty(Property.ROTATION_INITIAL_WIDTH, width); SetProperty(Property.ROTATION_INITIAL_HEIGHT, height); - if (!IsPositioned()) { - IList rotatedPoints = new List(); - GetLayoutShiftAndRotatedPoints(rotatedPoints, (float)rotationPointX, (float)rotationPointY); - Point clipLineBeg = new Point(layoutBox.GetRight(), layoutBox.GetTop()); - Point clipLineEnd = new Point(layoutBox.GetRight(), layoutBox.GetBottom()); - IList newOccupiedBox = ClipBBox(rotatedPoints, clipLineBeg, clipLineEnd); - double maxX = -double.MaxValue; - double minY = double.MaxValue; - foreach (Point point in newOccupiedBox) { - if (point.GetX() > maxX) { - maxX = point.GetX(); - } - if (point.GetY() < minY) { - minY = point.GetY(); - } + AffineTransform rotationTransform = new AffineTransform(); + // here we calculate and set the actual occupied area of the rotated content + if (IsPositioned()) { + float? rotationPointX = this.GetPropertyAsFloat(Property.ROTATION_POINT_X); + float? rotationPointY = this.GetPropertyAsFloat(Property.ROTATION_POINT_Y); + if (rotationPointX == null || rotationPointY == null) { + // if rotation point was not specified, the most bottom-left point is used + rotationPointX = x; + rotationPointY = y; + } + // transforms apply from bottom to top + rotationTransform.Translate((float)rotationPointX, (float)rotationPointY); + // move point back at place + rotationTransform.Rotate(angle); + // rotate + rotationTransform.Translate((float)-rotationPointX, (float)-rotationPointY); + // move rotation point to origin + IList rotatedPoints = TransformPoints(RectangleToPointsList(occupiedArea.GetBBox()), rotationTransform + ); + Rectangle newBBox = CalculateBBox(rotatedPoints); + // make occupied area be of size and position of actual content + occupiedArea.GetBBox().SetWidth(newBBox.GetWidth()); + occupiedArea.GetBBox().SetHeight(newBBox.GetHeight()); + float occupiedAreaShiftX = newBBox.GetX() - x; + float occupiedAreaShiftY = newBBox.GetY() - y; + Move(occupiedAreaShiftX, occupiedAreaShiftY); + } + else { + rotationTransform = AffineTransform.GetRotateInstance(angle); + IList rotatedPoints = TransformPoints(RectangleToPointsList(occupiedArea.GetBBox()), rotationTransform + ); + float[] shift = CalculateShiftToPositionBBoxOfPointsAt(x, y + height, rotatedPoints); + foreach (Point point in rotatedPoints) { + point.SetLocation(point.GetX() + shift[0], point.GetY() + shift[1]); } - float newHeight = (float)(occupiedArea.GetBBox().GetTop() - minY); - float newWidth = (float)(maxX - occupiedArea.GetBBox().GetLeft()); - occupiedArea.GetBBox().SetWidth(newWidth); - occupiedArea.GetBBox().SetHeight(newHeight); - Move(0, height - newHeight); + Rectangle newBBox = CalculateBBox(rotatedPoints); + occupiedArea.GetBBox().SetWidth(newBBox.GetWidth()); + occupiedArea.GetBBox().SetHeight(newBBox.GetHeight()); + float heightDiff = height - newBBox.GetHeight(); + Move(0, heightDiff); } } + [System.ObsoleteAttribute(@"Will be removed in iText 7.1")] protected internal virtual float[] ApplyRotation() { - float dx = 0; - float dy = 0; - if (!IsPositioned()) { - Point shift = GetLayoutShiftAndRotatedPoints(new List(), 0, 0); - dy = (float)shift.GetY(); - dx = (float)shift.GetX(); - } - float? angle = this.GetPropertyAsFloat(Property.ROTATION_ANGLE); - AffineTransform transform = new AffineTransform(); - transform.Rotate((float)angle); float[] ctm = new float[6]; - transform.GetMatrix(ctm); - ctm[4] = (float)this.GetPropertyAsFloat(Property.ROTATION_POINT_X) + dx; - ctm[5] = (float)this.GetPropertyAsFloat(Property.ROTATION_POINT_Y) + dy; + CreateRotationTransformInsideOccupiedArea().GetMatrix(ctm); return ctm; } - private Point GetLayoutShiftAndRotatedPoints(IList rotatedPoints, float shiftX, float shiftY) { - float angle = (float)this.GetPropertyAsFloat(Property.ROTATION_ANGLE); - float width = (float)this.GetPropertyAsFloat(Property.ROTATION_INITIAL_WIDTH); - float height = (float)this.GetPropertyAsFloat(Property.ROTATION_INITIAL_HEIGHT); - float left = occupiedArea.GetBBox().GetX() - shiftX; - float bottom = occupiedArea.GetBBox().GetY() - shiftY; - float right = left + width; - float top = bottom + height; - AffineTransform rotateTransform = new AffineTransform(); - rotateTransform.Rotate(angle); - TransformBBox(left, bottom, right, top, rotateTransform, rotatedPoints); - double minX = double.MaxValue; - double maxY = -double.MaxValue; - foreach (Point point in rotatedPoints) { - if (point.GetX() < minX) { - minX = point.GetX(); - } - if (point.GetY() > maxY) { - maxY = point.GetY(); - } - } - float dx = (float)(left - minX); - float dy = (float)(top - maxY); - foreach (Point point_1 in rotatedPoints) { - point_1.SetLocation(point_1.GetX() + dx + shiftX, point_1.GetY() + dy + shiftY); - } - return new Point(dx, dy); + /// + /// This method creates + /// + /// instance that could be used + /// to rotate content inside the occupied area. Be aware that it should be used only after + /// layout rendering is finished and correct occupied area for the rotated element is calculated. + /// + /// + /// + /// + /// that rotates the content and places it inside occupied area. + /// + protected internal virtual AffineTransform CreateRotationTransformInsideOccupiedArea() { + float? angle = this.GetProperty(Property.ROTATION_ANGLE); + AffineTransform rotationTransform = AffineTransform.GetRotateInstance((float)angle); + Rectangle contentBox = this.GetOccupiedAreaBBox(); + IList rotatedContentBoxPoints = TransformPoints(RectangleToPointsList(contentBox), rotationTransform + ); + // Occupied area for rotated elements is already calculated on layout in such way to enclose rotated content; + // therefore we can simply rotate content as is and then shift it to the occupied area. + float[] shift = CalculateShiftToPositionBBoxOfPointsAt(occupiedArea.GetBBox().GetLeft(), occupiedArea.GetBBox + ().GetTop(), rotatedContentBoxPoints); + rotationTransform.PreConcatenate(AffineTransform.GetTranslateInstance(shift[0], shift[1])); + return rotationTransform; } protected internal virtual void BeginRotationIfApplied(PdfCanvas canvas) { float? angle = this.GetPropertyAsFloat(Property.ROTATION_ANGLE); if (angle != null) { - float heightDiff = (float)this.GetPropertyAsFloat(Property.ROTATION_INITIAL_HEIGHT) - occupiedArea.GetBBox - ().GetHeight(); - float shiftX = (float)this.GetPropertyAsFloat(Property.ROTATION_POINT_X); - float shiftY = (float)this.GetPropertyAsFloat(Property.ROTATION_POINT_Y) + heightDiff; - Move(-shiftX, -shiftY); - float[] ctm = ApplyRotation(); - canvas.SaveState().ConcatMatrix(ctm[0], ctm[1], ctm[2], ctm[3], ctm[4], ctm[5]); + if (!HasOwnProperty(Property.ROTATION_INITIAL_HEIGHT)) { + ILogger logger = LoggerFactory.GetLogger(typeof(iText.Layout.Renderer.BlockRenderer)); + logger.Error(String.Format(LogMessageConstant.ROTATION_WAS_NOT_CORRECTLY_PROCESSED_FOR_RENDERER, GetType() + .Name)); + } + else { + AffineTransform transform = CreateRotationTransformInsideOccupiedArea(); + canvas.SaveState().ConcatMatrix(transform); + } } } protected internal virtual void EndRotationIfApplied(PdfCanvas canvas) { float? angle = this.GetPropertyAsFloat(Property.ROTATION_ANGLE); if (angle != null) { - float heightDiff = (float)this.GetPropertyAsFloat(Property.ROTATION_INITIAL_HEIGHT) - occupiedArea.GetBBox - ().GetHeight(); - float shiftX = (float)this.GetPropertyAsFloat(Property.ROTATION_POINT_X); - float shiftY = (float)this.GetPropertyAsFloat(Property.ROTATION_POINT_Y) + heightDiff; canvas.RestoreState(); - Move(shiftX, shiftY); } } - private IList TransformBBox(float left, float bottom, float right, float top, AffineTransform transform - , IList bBoxPoints) { - bBoxPoints.AddAll(iText.IO.Util.JavaUtil.ArraysAsList(new Point(left, bottom), new Point(right, bottom), new - Point(right, top), new Point(left, top))); - foreach (Point point in bBoxPoints) { - transform.Transform(point, point); + /// + /// This method calculates the shift needed to be applied to the points in order to position + /// upper and left borders of their bounding box at the given lines. + /// + /// x coordinate at which points bbox left border is to be aligned + /// y coordinate at which points bbox upper border is to be aligned + /// the points, which bbox will be aligned at the given position + /// + /// array of two floats, where first element denotes x-coordinate shift and the second + /// element denotes y-coordinate shift which are needed to align points bbox at the given lines. + /// + private float[] CalculateShiftToPositionBBoxOfPointsAt(float left, float top, IList points) { + double minX = double.MaxValue; + double maxY = -double.MaxValue; + foreach (Point point in points) { + minX = Math.Min(point.GetX(), minX); + maxY = Math.Max(point.GetY(), maxY); } - return bBoxPoints; + float dx = (float)(left - minX); + float dy = (float)(top - maxY); + return new float[] { dx, dy }; } - private IList ClipBBox(IList points, Point clipLineBeg, Point clipLineEnd) { + private IList ClipPolygon(IList points, Point clipLineBeg, Point clipLineEnd) { IList filteredPoints = new List(); bool prevOnRightSide = false; Point filteringPoint = points[0]; diff --git a/itext/itext.layout/itext/layout/renderer/CanvasRenderer.cs b/itext/itext.layout/itext/layout/renderer/CanvasRenderer.cs index 776559b6af..13566a6f5d 100644 --- a/itext/itext.layout/itext/layout/renderer/CanvasRenderer.cs +++ b/itext/itext.layout/itext/layout/renderer/CanvasRenderer.cs @@ -51,10 +51,35 @@ namespace iText.Layout.Renderer { public class CanvasRenderer : RootRenderer { protected internal Canvas canvas; + /// Creates a CanvasRenderer from its corresponding layout object. + /// + /// Creates a CanvasRenderer from its corresponding layout object. + /// Sets + /// + /// to true. + /// + /// + /// the + /// + /// which this object should manage + /// public CanvasRenderer(Canvas canvas) : this(canvas, true) { } + /// Creates a CanvasRenderer from its corresponding layout object. + /// + /// Creates a CanvasRenderer from its corresponding layout object. + /// Defines whether the content should be flushed immediately after addition + /// + /// or not + /// + /// + /// the + /// + /// which this object should manage + /// + /// the value which stands for immediate flushing public CanvasRenderer(Canvas canvas, bool immediateFlush) { this.canvas = canvas; this.modelElement = canvas; @@ -71,6 +96,7 @@ public override void AddChild(IRenderer renderer) { } } + /// protected internal override void FlushSingleRenderer(IRenderer resultRenderer) { if (!resultRenderer.IsFlushed()) { bool toTag = canvas.GetPdfDocument().IsTagged() && canvas.IsAutoTaggingEnabled(); @@ -87,6 +113,7 @@ protected internal override void FlushSingleRenderer(IRenderer resultRenderer) { } } + /// protected internal override LayoutArea UpdateCurrentArea(LayoutResult overflowResult) { if (currentArea == null) { currentArea = new LayoutArea(0, canvas.GetRootArea().Clone()); @@ -98,6 +125,7 @@ protected internal override LayoutArea UpdateCurrentArea(LayoutResult overflowRe return currentArea; } + /// public override IRenderer GetNextRenderer() { return null; } diff --git a/itext/itext.layout/itext/layout/renderer/CellRenderer.cs b/itext/itext.layout/itext/layout/renderer/CellRenderer.cs index 432cd43922..369491d60a 100644 --- a/itext/itext.layout/itext/layout/renderer/CellRenderer.cs +++ b/itext/itext.layout/itext/layout/renderer/CellRenderer.cs @@ -41,22 +41,34 @@ source product. For more information, please contact iText Software Corp. at this address: sales@itextpdf.com */ +using System; +using iText.Kernel.Geom; +using iText.Kernel.Pdf.Canvas; using iText.Layout; +using iText.Layout.Borders; using iText.Layout.Element; using iText.Layout.Properties; namespace iText.Layout.Renderer { public class CellRenderer : BlockRenderer { + /// Creates a CellRenderer from its corresponding layout object. + /// + /// the + /// + /// which this object should manage + /// public CellRenderer(Cell modelElement) : base(modelElement) { SetProperty(Property.ROWSPAN, modelElement.GetRowspan()); SetProperty(Property.COLSPAN, modelElement.GetColspan()); } + /// public override IPropertyContainer GetModelElement() { return (Cell)base.GetModelElement(); } + /// protected internal override AbstractRenderer CreateSplitRenderer(int layoutResult) { iText.Layout.Renderer.CellRenderer splitRenderer = (iText.Layout.Renderer.CellRenderer)GetNextRenderer(); splitRenderer.parent = parent; @@ -67,6 +79,7 @@ protected internal override AbstractRenderer CreateSplitRenderer(int layoutResul return splitRenderer; } + /// protected internal override AbstractRenderer CreateOverflowRenderer(int layoutResult) { iText.Layout.Renderer.CellRenderer overflowRenderer = (iText.Layout.Renderer.CellRenderer)GetNextRenderer( ); @@ -76,10 +89,48 @@ protected internal override AbstractRenderer CreateOverflowRenderer(int layoutRe return overflowRenderer; } + public override void DrawBackground(DrawContext drawContext) { + PdfCanvas canvas = drawContext.GetCanvas(); + Matrix ctm = canvas.GetGraphicsState().GetCtm(); + // Avoid rotation + float? angle = this.GetPropertyAsFloat(Property.ROTATION_ANGLE); + bool avoidRotation = null != angle && null != this.GetProperty(Property.BACKGROUND); + if (avoidRotation) { + AffineTransform transform = new AffineTransform(ctm.Get(0), ctm.Get(1), ctm.Get(3), ctm.Get(4), ctm.Get(6) + , ctm.Get(7)); + try { + transform = transform.CreateInverse(); + } + catch (NoninvertibleTransformException e) { + throw new Exception(e.Message, e); + } + transform.Concatenate(new AffineTransform()); + canvas.ConcatMatrix(transform); + DeleteProperty(Property.ROTATION_ANGLE); + } + base.DrawBackground(drawContext); + // restore concat matrix and rotation angle + if (avoidRotation) { + SetProperty(Property.ROTATION_ANGLE, angle); + canvas.ConcatMatrix(new AffineTransform(ctm.Get(0), ctm.Get(1), ctm.Get(3), ctm.Get(4), ctm.Get(6), ctm.Get + (7))); + } + } + + /// public override void DrawBorder(DrawContext drawContext) { } - // Do nothing here. Border drawing for tables is done on TableRenderer. + // Do nothing here. Border drawing for cells is done on TableRenderer. + protected internal override Rectangle ApplyBorderBox(Rectangle rect, Border[] borders, bool reverse) { + float topWidth = borders[0] != null ? borders[0].GetWidth() : 0; + float rightWidth = borders[1] != null ? borders[1].GetWidth() : 0; + float bottomWidth = borders[2] != null ? borders[2].GetWidth() : 0; + float leftWidth = borders[3] != null ? borders[3].GetWidth() : 0; + return rect.ApplyMargins(topWidth / 2, rightWidth / 2, bottomWidth / 2, leftWidth / 2, reverse); + } + + /// public override IRenderer GetNextRenderer() { return new iText.Layout.Renderer.CellRenderer(((Cell)GetModelElement())); } diff --git a/itext/itext.layout/itext/layout/renderer/DivRenderer.cs b/itext/itext.layout/itext/layout/renderer/DivRenderer.cs index 14299977d6..d54b7ad239 100644 --- a/itext/itext.layout/itext/layout/renderer/DivRenderer.cs +++ b/itext/itext.layout/itext/layout/renderer/DivRenderer.cs @@ -45,10 +45,17 @@ source product. namespace iText.Layout.Renderer { public class DivRenderer : BlockRenderer { + /// Creates a DivRenderer from its corresponding layout object. + /// + /// the + /// + /// which this object should manage + /// public DivRenderer(Div modelElement) : base(modelElement) { } + /// public override IRenderer GetNextRenderer() { return new iText.Layout.Renderer.DivRenderer((Div)modelElement); } diff --git a/itext/itext.layout/itext/layout/renderer/ImageRenderer.cs b/itext/itext.layout/itext/layout/renderer/ImageRenderer.cs index 67bc465027..75bf8878b1 100644 --- a/itext/itext.layout/itext/layout/renderer/ImageRenderer.cs +++ b/itext/itext.layout/itext/layout/renderer/ImageRenderer.cs @@ -71,6 +71,12 @@ public class ImageRenderer : AbstractRenderer { internal float[] matrix = new float[6]; + /// Creates an ImageRenderer from its corresponding layout object. + /// + /// the + /// + /// which this object should manage + /// public ImageRenderer(Image image) : base(image) { } @@ -123,9 +129,15 @@ public override LayoutResult Layout(LayoutContext layoutContext) { t.Scale(scaleCoef, scaleCoef); } GetMatrix(t, imageItselfScaledWidth, imageItselfScaledHeight); - if (!true.Equals(GetPropertyAsBoolean(Property.FORCED_PLACEMENT)) && (width > layoutBox.GetWidth() || height - > layoutBox.GetHeight())) { - return new LayoutResult(LayoutResult.NOTHING, occupiedArea, null, this); + // indicates whether the placement is forced + bool isPlacingForced = false; + if (width > layoutBox.GetWidth() || height > layoutBox.GetHeight()) { + if (true.Equals(GetPropertyAsBoolean(Property.FORCED_PLACEMENT))) { + isPlacingForced = true; + } + else { + return new LayoutResult(LayoutResult.NOTHING, occupiedArea, null, this, this); + } } occupiedArea.GetBBox().MoveDown(height); occupiedArea.GetBBox().SetHeight(height); @@ -137,7 +149,7 @@ public override LayoutResult Layout(LayoutContext layoutContext) { GetMatrix(t, imageItselfScaledWidth, imageItselfScaledHeight); } ApplyMargins(occupiedArea.GetBBox(), true); - return new LayoutResult(LayoutResult.FULL, occupiedArea, null, null); + return new LayoutResult(LayoutResult.FULL, occupiedArea, null, null, isPlacingForced ? this : null); } public override void Draw(DrawContext drawContext) { diff --git a/itext/itext.layout/itext/layout/renderer/LineRenderer.cs b/itext/itext.layout/itext/layout/renderer/LineRenderer.cs index 99f3e1a627..b820bfefa4 100644 --- a/itext/itext.layout/itext/layout/renderer/LineRenderer.cs +++ b/itext/itext.layout/itext/layout/renderer/LineRenderer.cs @@ -84,26 +84,35 @@ public override LayoutResult Layout(LayoutContext layoutContext) } } } + IList unicodeIdsReorderingList = null; if (levels == null && baseDirection != null && baseDirection != BaseDirection.NO_BIDI) { - IList unicodeIdsLst = new List(); + unicodeIdsReorderingList = new List(); + bool newLineFound = false; + foreach (IRenderer child in childRenderers) { + if (newLineFound) + { + break; + } if (child is TextRenderer) { GlyphLine text = ((TextRenderer)child).GetText(); for (int i = text.start; i < text.end; i++) { - System.Diagnostics.Debug.Assert(text.Get(i).GetChars().Length > 0); + if (TextRenderer.IsNewLine(text, i)) + { + newLineFound = true; + break; + } // we assume all the chars will have the same bidi group // we also assume pairing symbols won't get merged with other ones - int unicode = text.Get(i).GetChars()[0]; - unicodeIdsLst.Add(unicode); - } + unicodeIdsReorderingList.Add(text.Get(i).GetUnicode()); + } } } - levels = TypographyUtils.GetBidiLevels((BaseDirection)baseDirection, ArrayUtil.ToArray(unicodeIdsLst - )); + levels = unicodeIdsReorderingList.Count > 0 ? TypographyUtils.GetBidiLevels((BaseDirection) baseDirection, ArrayUtil.ToArray(unicodeIdsReorderingList)) : null; } bool anythingPlaced = false; TabStop nextTabStop = null; @@ -184,10 +193,21 @@ public override LayoutResult Layout(LayoutContext layoutContext) { childResult.GetSplitRenderer().GetOccupiedArea().GetBBox().MoveRight(tabWidth); } - nextTabStop = null; - curWidth += tabWidth; - } - curWidth += childResult.GetOccupiedArea().GetBBox().GetWidth(); + float tabAndNextElemWidth = tabWidth + childResult.GetOccupiedArea().GetBBox().GetWidth(); + if (nextTabStop.GetTabAlignment() == TabAlignment.RIGHT && curWidth + tabAndNextElemWidth < nextTabStop.GetTabPosition()) + { + curWidth = nextTabStop.GetTabPosition(); + } + else + { + curWidth += tabAndNextElemWidth; + } + nextTabStop = null; + } + else + { + curWidth += childResult.GetOccupiedArea().GetBBox().GetWidth(); + } occupiedArea.SetBBox(new Rectangle(layoutBox.GetX(), layoutBox.GetY() + layoutBox .GetHeight() - maxHeight, curWidth, maxHeight)); if (childResult.GetStatus() != LayoutResult.FULL) @@ -237,13 +257,12 @@ public override LayoutResult Layout(LayoutContext layoutContext) split[1] = null; } } - result = new LineLayoutResult(anythingPlaced ? LayoutResult.PARTIAL : LayoutResult - .NOTHING, occupiedArea, split[0], split[1]); - if (childResult.GetStatus() == LayoutResult.PARTIAL && childResult is TextLayoutResult - && ((TextLayoutResult)childResult).IsSplitForcedByNewline()) - { - result.SetSplitForcedByNewline(true); - } + result = new LineLayoutResult(anythingPlaced ? LayoutResult.PARTIAL : LayoutResult.NOTHING, occupiedArea, split[0], split[1], + childResult.GetStatus() == LayoutResult.NOTHING ? childResult.GetCauseOfNothing() : this); + + if (childResult.GetStatus() == LayoutResult.PARTIAL && childResult is TextLayoutResult && ((TextLayoutResult) childResult).IsSplitForcedByNewline()) { + result.SetSplitForcedByNewline(true); + } break; } else @@ -260,7 +279,7 @@ public override LayoutResult Layout(LayoutContext layoutContext) } else { - result = new LineLayoutResult(LayoutResult.NOTHING, occupiedArea, null, this); + result = new LineLayoutResult(LayoutResult.NOTHING, occupiedArea, null, this, this); } } // Consider for now that all the children have the same font, and that after reordering text pieces @@ -392,6 +411,18 @@ public override LayoutResult Layout(LayoutContext layoutContext) overflow.levels = new byte[levels.Length - lineLevels.Length]; System.Array.Copy(levels, lineLevels.Length, overflow.levels, 0, overflow.levels. Length); + if (overflow.levels.Length == 0) + { + overflow.levels = null; + } + } + } + else if (result.GetStatus() == LayoutResult.NOTHING) + { + if (levels != null) + { + ((LineRenderer)result.GetOverflowRenderer()).levels = levels; + } } } @@ -567,7 +598,6 @@ protected internal virtual LineRenderer[] Split() splitRenderer.AddAllProperties(GetOwnProperties()); LineRenderer overflowRenderer = CreateOverflowRenderer(); overflowRenderer.parent = parent; - overflowRenderer.levels = levels; overflowRenderer.AddAllProperties(GetOwnProperties()); return new LineRenderer[] { splitRenderer, overflowRenderer }; } diff --git a/itext/itext.layout/itext/layout/renderer/LineSeparatorRenderer.cs b/itext/itext.layout/itext/layout/renderer/LineSeparatorRenderer.cs index 8b50289ddd..3de5df6f64 100644 --- a/itext/itext.layout/itext/layout/renderer/LineSeparatorRenderer.cs +++ b/itext/itext.layout/itext/layout/renderer/LineSeparatorRenderer.cs @@ -41,6 +41,7 @@ source product. For more information, please contact iText Software Corp. at this address: sales@itextpdf.com */ +using iText.Kernel.Geom; using iText.Kernel.Pdf.Canvas.Draw; using iText.Layout.Element; using iText.Layout.Layout; @@ -48,32 +49,60 @@ source product. namespace iText.Layout.Renderer { public class LineSeparatorRenderer : BlockRenderer { + /// Creates a LineSeparatorRenderer from its corresponding layout object. + /// + /// the + /// + /// which this object should manage + /// public LineSeparatorRenderer(LineSeparator lineSeparator) : base(lineSeparator) { } + /// public override LayoutResult Layout(LayoutContext layoutContext) { + Rectangle parentBBox = layoutContext.GetArea().GetBBox().Clone(); + if (this.GetProperty(Property.ROTATION_ANGLE) != null) { + parentBBox.MoveDown(AbstractRenderer.INF - parentBBox.GetHeight()).SetHeight(AbstractRenderer.INF); + } ILineDrawer lineDrawer = this.GetProperty(Property.LINE_DRAWER); float height = lineDrawer != null ? lineDrawer.GetLineWidth() : 0; - occupiedArea = layoutContext.GetArea().Clone(); + occupiedArea = new LayoutArea(layoutContext.GetArea().GetPageNumber(), parentBBox.Clone()); ApplyMargins(occupiedArea.GetBBox(), false); - if (occupiedArea.GetBBox().GetHeight() < height) { - return new LayoutResult(LayoutResult.NOTHING, null, null, this); + float? calculatedWidth = RetrieveWidth(layoutContext.GetArea().GetBBox().GetWidth()); + if (calculatedWidth == null) { + calculatedWidth = occupiedArea.GetBBox().GetWidth(); + } + if ((occupiedArea.GetBBox().GetHeight() < height || occupiedArea.GetBBox().GetWidth() < calculatedWidth) && + !HasOwnProperty(Property.FORCED_PLACEMENT)) { + return new LayoutResult(LayoutResult.NOTHING, null, null, this, this); } - occupiedArea.GetBBox().MoveUp(occupiedArea.GetBBox().GetHeight() - height).SetHeight(height); + occupiedArea.GetBBox().SetWidth((float)calculatedWidth).MoveUp(occupiedArea.GetBBox().GetHeight() - height + ).SetHeight(height); ApplyMargins(occupiedArea.GetBBox(), true); + if (this.GetProperty(Property.ROTATION_ANGLE) != null) { + ApplyRotationLayout(layoutContext.GetArea().GetBBox().Clone()); + if (IsNotFittingLayoutArea(layoutContext.GetArea())) { + if (!true.Equals(GetPropertyAsBoolean(Property.FORCED_PLACEMENT))) { + return new LayoutResult(LayoutResult.NOTHING, occupiedArea, null, this, this); + } + } + } return new LayoutResult(LayoutResult.FULL, occupiedArea, this, null); } + /// public override IRenderer GetNextRenderer() { return new iText.Layout.Renderer.LineSeparatorRenderer((LineSeparator)modelElement); } - public override void Draw(DrawContext drawContext) { - base.Draw(drawContext); + /// + public override void DrawChildren(DrawContext drawContext) { ILineDrawer lineDrawer = this.GetProperty(Property.LINE_DRAWER); if (lineDrawer != null) { - lineDrawer.Draw(drawContext.GetCanvas(), occupiedArea.GetBBox()); + Rectangle area = GetOccupiedAreaBBox(); + ApplyMargins(area, false); + lineDrawer.Draw(drawContext.GetCanvas(), area); } } } diff --git a/itext/itext.layout/itext/layout/renderer/LinkRenderer.cs b/itext/itext.layout/itext/layout/renderer/LinkRenderer.cs index 3bcb555215..009a77e00f 100644 --- a/itext/itext.layout/itext/layout/renderer/LinkRenderer.cs +++ b/itext/itext.layout/itext/layout/renderer/LinkRenderer.cs @@ -42,18 +42,35 @@ source product. address: sales@itextpdf.com */ using System; +using iText.Kernel.Geom; using iText.Kernel.Pdf; using iText.Kernel.Pdf.Annot; -using iText.Layout.Borders; using iText.Layout.Element; -using iText.Layout.Properties; namespace iText.Layout.Renderer { public class LinkRenderer : TextRenderer { + /// Creates a LinkRenderer from its corresponding layout object. + /// + /// the + /// + /// which this object should manage + /// public LinkRenderer(Link link) : this(link, link.GetText()) { } + /// + /// Creates a LinkRenderer from its corresponding layout object, with a custom + /// text to replace the contents of the + /// + /// . + /// + /// + /// the + /// + /// which this object should manage + /// + /// the replacement text public LinkRenderer(Link linkElement, String text) : base(linkElement, text) { } @@ -65,14 +82,8 @@ public override void Draw(DrawContext drawContext) { ApplyAbsolutePositioningTranslation(false); } PdfLinkAnnotation linkAnnotation = ((Link)modelElement).GetLinkAnnotation(); - linkAnnotation.SetRectangle(new PdfArray(occupiedArea.GetBBox())); - Border border = this.GetProperty(Property.BORDER); - if (border != null) { - linkAnnotation.SetBorder(new PdfArray(new float[] { 0, 0, border.GetWidth() })); - } - else { - linkAnnotation.SetBorder(new PdfArray(new float[] { 0, 0, 0 })); - } + Rectangle pdfBBox = CalculateAbsolutePdfBBox(); + linkAnnotation.SetRectangle(new PdfArray(pdfBBox)); if (isRelativePosition) { ApplyAbsolutePositioningTranslation(true); } diff --git a/itext/itext.layout/itext/layout/renderer/ListItemRenderer.cs b/itext/itext.layout/itext/layout/renderer/ListItemRenderer.cs index 79231d6af1..184273af11 100644 --- a/itext/itext.layout/itext/layout/renderer/ListItemRenderer.cs +++ b/itext/itext.layout/itext/layout/renderer/ListItemRenderer.cs @@ -54,6 +54,12 @@ public class ListItemRenderer : DivRenderer { protected internal float symbolAreaWidth; + /// Creates a ListItemRenderer from its corresponding layout object. + /// + /// the + /// + /// which this object should manage + /// public ListItemRenderer(ListItem modelElement) : base(modelElement) { } diff --git a/itext/itext.layout/itext/layout/renderer/ListRenderer.cs b/itext/itext.layout/itext/layout/renderer/ListRenderer.cs index 7ca7413ffb..77e623ceb6 100644 --- a/itext/itext.layout/itext/layout/renderer/ListRenderer.cs +++ b/itext/itext.layout/itext/layout/renderer/ListRenderer.cs @@ -53,6 +53,12 @@ source product. namespace iText.Layout.Renderer { public class ListRenderer : BlockRenderer { + /// Creates a ListRenderer from its corresponding layout object. + /// + /// the + /// + /// which this object should manage + /// public ListRenderer(List modelElement) : base(modelElement) { } @@ -72,7 +78,8 @@ public override LayoutResult Layout(LayoutContext layoutContext) { LayoutResult listSymbolLayoutResult = currentSymbolRenderer.SetParent(this).Layout(layoutContext); currentSymbolRenderer.SetParent(null); if (listSymbolLayoutResult.GetStatus() != LayoutResult.FULL) { - return new LayoutResult(LayoutResult.NOTHING, null, null, this); + return new LayoutResult(LayoutResult.NOTHING, null, null, this, listSymbolLayoutResult.GetCauseOfNothing() + ); } } } @@ -92,7 +99,20 @@ public override LayoutResult Layout(LayoutContext layoutContext) { } } } - return base.Layout(layoutContext); + LayoutResult result = base.Layout(layoutContext); + // cannot place even the first ListItemRenderer + if (true.Equals(GetPropertyAsBoolean(Property.FORCED_PLACEMENT)) && null != result.GetCauseOfNothing()) { + if (LayoutResult.FULL == result.GetStatus()) { + result = CorrectListSplitting(this, null, result.GetCauseOfNothing(), result.GetOccupiedArea()); + } + else { + if (LayoutResult.PARTIAL == result.GetStatus()) { + result = CorrectListSplitting(result.GetSplitRenderer(), result.GetOverflowRenderer(), result.GetCauseOfNothing + (), result.GetOccupiedArea()); + } + } + } + return result; } public override IRenderer GetNextRenderer() { @@ -195,7 +215,7 @@ protected internal virtual IRenderer MakeListSymbolRenderer(int index, IRenderer == ListNumberingType.ZAPF_DINGBATS_3 || numberingType == ListNumberingType.ZAPF_DINGBATS_4) { String constantFont = (numberingType == ListNumberingType.GREEK_LOWER || numberingType == ListNumberingType .GREEK_UPPER) ? FontConstants.SYMBOL : FontConstants.ZAPFDINGBATS; - textRenderer = new _TextRenderer_187(constantFont, textElement); + textRenderer = new _TextRenderer_201(constantFont, textElement); try { textRenderer.SetProperty(Property.FONT, PdfFontFactory.CreateFont(constantFont)); } @@ -214,8 +234,8 @@ protected internal virtual IRenderer MakeListSymbolRenderer(int index, IRenderer } } - private sealed class _TextRenderer_187 : TextRenderer { - public _TextRenderer_187(String constantFont, Text baseArg1) + private sealed class _TextRenderer_201 : TextRenderer { + public _TextRenderer_201(String constantFont, Text baseArg1) : base(baseArg1) { this.constantFont = constantFont; } @@ -231,5 +251,92 @@ public override void Draw(DrawContext drawContext) { private readonly String constantFont; } + + /// + ///

    + /// Corrects split and overflow renderers when + /// + /// is applied. + /// We assume that + /// + /// is applied when the first + /// + /// cannot be fully layouted. + /// This means that the problem has occurred in one of first list item renderer's child. + /// We consider the right solution to force placement of all first item renderer's childs before the one, + /// which was the cause of + /// + /// , including this child. + ///

    + ///

    + /// Notice that we do not expect + /// + /// to be applied + /// if we can render the first item renderer and strongly recommend not to set + /// + /// manually. + ///

    + ///
    + /// + /// the + /// split renderer + /// before correction + /// + /// + /// the + /// overflow renderer + /// before correction + /// + /// + /// the + /// cause of nothing renderer + /// + /// the area occupied by layouting before correction + /// + /// corrected + /// layout result + /// + private LayoutResult CorrectListSplitting(IRenderer splitRenderer, IRenderer overflowRenderer, IRenderer causeOfNothing + , LayoutArea occupiedArea) { + // the first not rendered child + int firstNotRendered = splitRenderer.GetChildRenderers()[0].GetChildRenderers().IndexOf(causeOfNothing); + if (-1 == firstNotRendered) { + return new LayoutResult(null == overflowRenderer ? LayoutResult.FULL : LayoutResult.PARTIAL, occupiedArea, + splitRenderer, overflowRenderer, this); + } + // Notice that placed item is a son of the first ListItemRenderer (otherwise there would be now FORCED_PLACEMENT applied) + IRenderer firstListItemRenderer = splitRenderer.GetChildRenderers()[0]; + iText.Layout.Renderer.ListRenderer newOverflowRenderer = (iText.Layout.Renderer.ListRenderer)CreateOverflowRenderer + (LayoutResult.PARTIAL); + newOverflowRenderer.DeleteOwnProperty(Property.FORCED_PLACEMENT); + // ListItemRenderer for not rendered children of firstListItemRenderer + newOverflowRenderer.childRenderers.Add(new ListItemRenderer((ListItem)firstListItemRenderer.GetModelElement + ())); + newOverflowRenderer.childRenderers.AddAll(splitRenderer.GetChildRenderers().SubList(1, splitRenderer.GetChildRenderers + ().Count)); + IList childrenStillRemainingToRender = new List(firstListItemRenderer.GetChildRenderers + ().SubList(firstNotRendered + 1, firstListItemRenderer.GetChildRenderers().Count)); + // 'this' renderer will become split renderer + splitRenderer.GetChildRenderers().RemoveAll(splitRenderer.GetChildRenderers().SubList(1, splitRenderer.GetChildRenderers + ().Count)); + if (0 != childrenStillRemainingToRender.Count) { + newOverflowRenderer.GetChildRenderers()[0].GetChildRenderers().AddAll(childrenStillRemainingToRender); + splitRenderer.GetChildRenderers()[0].GetChildRenderers().RemoveAll(childrenStillRemainingToRender); + newOverflowRenderer.GetChildRenderers()[0].SetProperty(Property.MARGIN_LEFT, splitRenderer.GetChildRenderers + ()[0].GetProperty(Property.MARGIN_LEFT)); + } + else { + newOverflowRenderer.childRenderers.JRemoveAt(0); + } + if (null != overflowRenderer) { + newOverflowRenderer.childRenderers.AddAll(overflowRenderer.GetChildRenderers()); + } + if (0 != newOverflowRenderer.childRenderers.Count) { + return new LayoutResult(LayoutResult.PARTIAL, occupiedArea, splitRenderer, newOverflowRenderer, this); + } + else { + return new LayoutResult(LayoutResult.FULL, occupiedArea, null, null, this); + } + } } } diff --git a/itext/itext.layout/itext/layout/renderer/ParagraphRenderer.cs b/itext/itext.layout/itext/layout/renderer/ParagraphRenderer.cs index bff5f9ff58..52a03e30d8 100644 --- a/itext/itext.layout/itext/layout/renderer/ParagraphRenderer.cs +++ b/itext/itext.layout/itext/layout/renderer/ParagraphRenderer.cs @@ -52,18 +52,50 @@ source product. using iText.Layout.Properties; namespace iText.Layout.Renderer { + /// + /// This class represents the + /// renderer + /// object for a + /// + /// object. It will draw the glyphs of the textual content on the + /// + /// . + /// public class ParagraphRenderer : BlockRenderer { protected internal float previousDescent = 0; protected internal IList lines = null; + /// Creates a ParagraphRenderer from its corresponding layout object. + /// + /// the + /// + /// which this object should manage + /// public ParagraphRenderer(Paragraph modelElement) : base(modelElement) { } + /// public override LayoutResult Layout(LayoutContext layoutContext) { int pageNumber = layoutContext.GetArea().GetPageNumber(); + bool anythingPlaced = false; + bool firstLineInBox = true; + LineRenderer currentRenderer = (LineRenderer)new LineRenderer().SetParent(this); Rectangle parentBBox = layoutContext.GetArea().GetBBox().Clone(); + if (0 == childRenderers.Count) { + anythingPlaced = true; + currentRenderer = null; + SetProperty(Property.MARGIN_TOP, 0); + SetProperty(Property.MARGIN_RIGHT, 0); + SetProperty(Property.MARGIN_BOTTOM, 0); + SetProperty(Property.MARGIN_LEFT, 0); + SetProperty(Property.PADDING_TOP, 0); + SetProperty(Property.PADDING_RIGHT, 0); + SetProperty(Property.PADDING_BOTTOM, 0); + SetProperty(Property.PADDING_LEFT, 0); + SetProperty(Property.BORDER, Border.NO_BORDER); + } if (this.GetProperty(Property.ROTATION_ANGLE) != null) { parentBBox.MoveDown(AbstractRenderer.INF - parentBBox.GetHeight()).SetHeight(AbstractRenderer.INF); } @@ -94,30 +126,10 @@ public override LayoutResult Layout(LayoutContext layoutContext) { GetHeight(), parentBBox.GetWidth(), 0)); int currentAreaPos = 0; Rectangle layoutBox = areas[0].Clone(); - bool anythingPlaced = false; - bool firstLineInBox = true; lines = new List(); - LineRenderer currentRenderer = (LineRenderer)new LineRenderer().SetParent(this); foreach (IRenderer child in childRenderers) { currentRenderer.AddChild(child); } - if (0 == childRenderers.Count) { - anythingPlaced = true; - currentRenderer = null; - // TODO is this really needed?? - SetProperty(Property.MARGIN_TOP, 0); - SetProperty(Property.MARGIN_RIGHT, 0); - SetProperty(Property.MARGIN_BOTTOM, 0); - SetProperty(Property.MARGIN_LEFT, 0); - SetProperty(Property.PADDING_TOP, 0); - SetProperty(Property.PADDING_RIGHT, 0); - SetProperty(Property.PADDING_BOTTOM, 0); - SetProperty(Property.PADDING_LEFT, 0); - SetProperty(Property.BORDER, Border.NO_BORDER); - margins = GetMargins(); - borders = GetBorders(); - paddings = GetPaddings(); - } float lastYLine = layoutBox.GetY() + layoutBox.GetHeight(); Leading leading = this.GetProperty(Property.LEADING); float leadingValue = 0; @@ -190,7 +202,8 @@ public override LayoutResult Layout(LayoutContext layoutContext) { else { bool keepTogether = IsKeepTogether(); if (keepTogether) { - return new LayoutResult(LayoutResult.NOTHING, occupiedArea, null, this); + return new LayoutResult(LayoutResult.NOTHING, occupiedArea, null, this, null == result.GetCauseOfNothing() + ? this : result.GetCauseOfNothing()); } else { ApplyPaddings(occupiedArea.GetBBox(), paddings, true); @@ -212,12 +225,25 @@ public override LayoutResult Layout(LayoutContext layoutContext) { } else { if (true.Equals(GetPropertyAsBoolean(Property.FORCED_PLACEMENT))) { + occupiedArea.SetBBox(Rectangle.GetCommonRectangle(occupiedArea.GetBBox(), currentRenderer.GetOccupiedArea( + ).GetBBox())); parent.SetProperty(Property.FULL, true); lines.Add(currentRenderer); - return new LayoutResult(LayoutResult.FULL, occupiedArea, null, this); + // Force placement of children we have and do not force placement of the others + if (LayoutResult.PARTIAL == result.GetStatus()) { + IRenderer childNotRendered = result.GetCauseOfNothing(); + int firstNotRendered = currentRenderer.childRenderers.IndexOf(childNotRendered); + currentRenderer.childRenderers.RetainAll(currentRenderer.childRenderers.SubList(0, firstNotRendered)); + split[1].childRenderers.RemoveAll(split[1].childRenderers.SubList(0, firstNotRendered)); + return new LayoutResult(LayoutResult.PARTIAL, occupiedArea, this, split[1]); + } + else { + return new LayoutResult(LayoutResult.FULL, occupiedArea, null, null, this); + } } else { - return new LayoutResult(LayoutResult.NOTHING, occupiedArea, null, this); + return new LayoutResult(LayoutResult.NOTHING, occupiedArea, null, this, null == result.GetCauseOfNothing() + ? this : result.GetCauseOfNothing()); } } } @@ -260,19 +286,21 @@ public override LayoutResult Layout(LayoutContext layoutContext) { ApplyMargins(occupiedArea.GetBBox(), margins, true); if (this.GetProperty(Property.ROTATION_ANGLE) != null) { ApplyRotationLayout(layoutContext.GetArea().GetBBox().Clone()); - if (IsNotFittingHeight(layoutContext.GetArea())) { - if (!layoutContext.GetArea().IsEmptyArea()) { - return new LayoutResult(LayoutResult.NOTHING, occupiedArea, null, this); + if (IsNotFittingLayoutArea(layoutContext.GetArea())) { + if (!true.Equals(GetPropertyAsBoolean(Property.FORCED_PLACEMENT))) { + return new LayoutResult(LayoutResult.NOTHING, occupiedArea, null, this, this); } } } return new LayoutResult(LayoutResult.FULL, occupiedArea, null, null); } + /// public override IRenderer GetNextRenderer() { return new iText.Layout.Renderer.ParagraphRenderer((Paragraph)modelElement); } + /// public override T1 GetDefaultProperty(int property) { if ((property == Property.MARGIN_TOP || property == Property.MARGIN_BOTTOM) && parent is CellRenderer) { return (T1)(Object)0f; @@ -280,31 +308,7 @@ public override T1 GetDefaultProperty(int property) { return base.GetDefaultProperty(property); } - protected internal virtual iText.Layout.Renderer.ParagraphRenderer CreateOverflowRenderer() { - iText.Layout.Renderer.ParagraphRenderer overflowRenderer = (iText.Layout.Renderer.ParagraphRenderer)GetNextRenderer - (); - // Reset first line indent in case of overflow. - float firstLineIndent = (float)this.GetPropertyAsFloat(Property.FIRST_LINE_INDENT); - if (firstLineIndent != 0) { - overflowRenderer.SetProperty(Property.FIRST_LINE_INDENT, 0); - } - return overflowRenderer; - } - - protected internal virtual iText.Layout.Renderer.ParagraphRenderer CreateSplitRenderer() { - return (iText.Layout.Renderer.ParagraphRenderer)GetNextRenderer(); - } - - protected internal virtual iText.Layout.Renderer.ParagraphRenderer[] Split() { - iText.Layout.Renderer.ParagraphRenderer splitRenderer = CreateSplitRenderer(); - splitRenderer.occupiedArea = occupiedArea.Clone(); - splitRenderer.parent = parent; - splitRenderer.isLastRendererForModelElement = false; - iText.Layout.Renderer.ParagraphRenderer overflowRenderer = CreateOverflowRenderer(); - overflowRenderer.parent = parent; - return new iText.Layout.Renderer.ParagraphRenderer[] { splitRenderer, overflowRenderer }; - } - + /// public override String ToString() { StringBuilder sb = new StringBuilder(); if (lines != null && lines.Count > 0) { @@ -320,6 +324,7 @@ public override String ToString() { return sb.ToString(); } + /// public override void DrawChildren(DrawContext drawContext) { if (lines != null) { foreach (LineRenderer line in lines) { @@ -328,6 +333,7 @@ public override void DrawChildren(DrawContext drawContext) { } } + /// public override void Move(float dxRight, float dyUp) { occupiedArea.GetBBox().MoveRight(dxRight); occupiedArea.GetBBox().MoveUp(dyUp); @@ -342,5 +348,45 @@ public override void Move(float dxRight, float dyUp) { } return lines[0].GetFirstYLineRecursively(); } + + [Obsolete] + protected internal virtual iText.Layout.Renderer.ParagraphRenderer CreateOverflowRenderer() { + return (iText.Layout.Renderer.ParagraphRenderer)GetNextRenderer(); + } + + [Obsolete] + protected internal virtual iText.Layout.Renderer.ParagraphRenderer CreateSplitRenderer() { + return (iText.Layout.Renderer.ParagraphRenderer)GetNextRenderer(); + } + + protected internal virtual iText.Layout.Renderer.ParagraphRenderer CreateOverflowRenderer(IRenderer parent + ) { + iText.Layout.Renderer.ParagraphRenderer overflowRenderer = CreateOverflowRenderer(); + overflowRenderer.parent = parent; + FixOverflowRenderer(overflowRenderer); + return overflowRenderer; + } + + protected internal virtual iText.Layout.Renderer.ParagraphRenderer CreateSplitRenderer(IRenderer parent) { + iText.Layout.Renderer.ParagraphRenderer splitRenderer = CreateSplitRenderer(); + splitRenderer.parent = parent; + return splitRenderer; + } + + protected internal virtual iText.Layout.Renderer.ParagraphRenderer[] Split() { + iText.Layout.Renderer.ParagraphRenderer splitRenderer = CreateSplitRenderer(parent); + splitRenderer.occupiedArea = occupiedArea.Clone(); + splitRenderer.isLastRendererForModelElement = false; + iText.Layout.Renderer.ParagraphRenderer overflowRenderer = CreateOverflowRenderer(parent); + return new iText.Layout.Renderer.ParagraphRenderer[] { splitRenderer, overflowRenderer }; + } + + private void FixOverflowRenderer(iText.Layout.Renderer.ParagraphRenderer overflowRenderer) { + // Reset first line indent in case of overflow. + float firstLineIndent = (float)overflowRenderer.GetPropertyAsFloat(Property.FIRST_LINE_INDENT); + if (firstLineIndent != 0) { + overflowRenderer.SetProperty(Property.FIRST_LINE_INDENT, 0); + } + } } } diff --git a/itext/itext.layout/itext/layout/renderer/RootRenderer.cs b/itext/itext.layout/itext/layout/renderer/RootRenderer.cs index 8e8fbbe0c0..4df5cdb5fd 100644 --- a/itext/itext.layout/itext/layout/renderer/RootRenderer.cs +++ b/itext/itext.layout/itext/layout/renderer/RootRenderer.cs @@ -56,6 +56,10 @@ public abstract class RootRenderer : AbstractRenderer { protected internal int currentPageNumber; + private IRenderer keepWithNextHangingRenderer; + + private LayoutResult keepWithNextHangingRendererLayoutResult; + public override void AddChild(IRenderer renderer) { base.AddChild(renderer); if (currentArea == null) { @@ -65,6 +69,7 @@ public override void AddChild(IRenderer renderer) { if (currentArea != null && !childRenderers.IsEmpty() && childRenderers[childRenderers.Count - 1] == renderer ) { childRenderers.JRemoveAt(childRenderers.Count - 1); + ProcessWaitingKeepWithNextElement(renderer); IList resultRenderers = new List(); LayoutResult result = null; LayoutArea storedArea = null; @@ -95,6 +100,7 @@ public override void AddChild(IRenderer renderer) { UpdateCurrentArea(result); } ((ImageRenderer)result.GetOverflowRenderer()).AutoScale(currentArea); + result.GetOverflowRenderer().SetProperty(Property.FORCED_PLACEMENT, true); } else { if (currentArea.IsEmptyArea() && !(renderer is AreaBreakRenderer)) { @@ -112,9 +118,24 @@ public override void AddChild(IRenderer renderer) { storedArea = currentArea; } else { - result.GetOverflowRenderer().SetProperty(Property.FORCED_PLACEMENT, true); - ILogger logger = LoggerFactory.GetLogger(typeof(RootRenderer)); - logger.Warn(String.Format(LogMessageConstant.ELEMENT_DOES_NOT_FIT_AREA, "")); + if (null != result.GetCauseOfNothing() && true.Equals(result.GetCauseOfNothing().GetProperty(Property + .KEEP_TOGETHER))) { + // set KEEP_TOGETHER false on the deepest parent (maybe the element itself) to have KEEP_TOGETHER == true + IRenderer theDeepestKeptTogether = result.GetCauseOfNothing(); + while (null == theDeepestKeptTogether.GetModelElement() || null == theDeepestKeptTogether.GetModelElement( + ).GetOwnProperty(Property.KEEP_TOGETHER)) { + theDeepestKeptTogether = ((AbstractRenderer)theDeepestKeptTogether).parent; + } + theDeepestKeptTogether.GetModelElement().SetProperty(Property.KEEP_TOGETHER, false); + ILogger logger = LoggerFactory.GetLogger(typeof(RootRenderer)); + logger.Warn(String.Format(LogMessageConstant.ELEMENT_DOES_NOT_FIT_AREA, "KeepTogether property of inner element will be ignored." + )); + } + else { + result.GetOverflowRenderer().SetProperty(Property.FORCED_PLACEMENT, true); + ILogger logger = LoggerFactory.GetLogger(typeof(RootRenderer)); + logger.Warn(String.Format(LogMessageConstant.ELEMENT_DOES_NOT_FIT_AREA, "")); + } } renderer = result.GetOverflowRenderer(); continue; @@ -133,17 +154,20 @@ public override void AddChild(IRenderer renderer) { } renderer = result.GetOverflowRenderer(); } - if (currentArea != null) { - System.Diagnostics.Debug.Assert(result != null && result.GetOccupiedArea() != null); - currentArea.GetBBox().SetHeight(currentArea.GetBBox().GetHeight() - result.GetOccupiedArea().GetBBox().GetHeight - ()); - currentArea.SetEmptyArea(false); - if (renderer != null) { - ProcessRenderer(renderer, resultRenderers); + // Keep renderer until next element is added for future keep with next adjustments + if (renderer != null && true.Equals(renderer.GetProperty(Property.KEEP_WITH_NEXT))) { + if (true.Equals(renderer.GetProperty(Property.FORCED_PLACEMENT))) { + ILogger logger = LoggerFactory.GetLogger(typeof(RootRenderer)); + logger.Warn(LogMessageConstant.ELEMENT_WAS_FORCE_PLACED_KEEP_WITH_NEXT_WILL_BE_IGNORED); + UpdateCurrentAreaAndProcessRenderer(renderer, resultRenderers, result); + } + else { + keepWithNextHangingRenderer = renderer; + keepWithNextHangingRendererLayoutResult = result; } } - if (!immediateFlush) { - childRenderers.AddAll(resultRenderers); + else { + UpdateCurrentAreaAndProcessRenderer(renderer, resultRenderers, result); } } else { @@ -162,7 +186,9 @@ public override void AddChild(IRenderer renderer) { } } - // Drawing of content. Might need to rename. + // TODO Drawing of content. Might need to rename. + /// Draws (flushes) the content. + /// public virtual void Flush() { foreach (IRenderer resultRenderer in childRenderers) { FlushSingleRenderer(resultRenderer); @@ -174,6 +200,28 @@ public virtual void Flush() { positionedRenderers.Clear(); } + /// + /// This method correctly closes the + /// + /// instance. + /// There might be hanging elements, like in case of + /// + /// is set to true + /// and when no consequent element has been added. This method addresses such situations. + /// + public virtual void Close() { + if (keepWithNextHangingRenderer != null) { + keepWithNextHangingRenderer.SetProperty(Property.KEEP_WITH_NEXT, false); + IRenderer rendererToBeAdded = keepWithNextHangingRenderer; + keepWithNextHangingRenderer = null; + AddChild(rendererToBeAdded); + } + if (!immediateFlush) { + Flush(); + } + } + + /// public override LayoutResult Layout(LayoutContext layoutContext) { throw new InvalidOperationException("Layout is not supported for root renderers."); } @@ -198,5 +246,109 @@ private void ProcessRenderer(IRenderer renderer, IList resultRenderer resultRenderers.Add(renderer); } } + + private void UpdateCurrentAreaAndProcessRenderer(IRenderer renderer, IList resultRenderers, LayoutResult + result) { + if (currentArea != null) { + currentArea.GetBBox().SetHeight(currentArea.GetBBox().GetHeight() - result.GetOccupiedArea().GetBBox().GetHeight + ()); + currentArea.SetEmptyArea(false); + if (renderer != null) { + ProcessRenderer(renderer, resultRenderers); + } + } + if (!immediateFlush) { + childRenderers.AddAll(resultRenderers); + } + } + + private void ProcessWaitingKeepWithNextElement(IRenderer renderer) { + if (keepWithNextHangingRenderer != null) { + LayoutArea rest = currentArea.Clone(); + rest.GetBBox().SetHeight(rest.GetBBox().GetHeight() - keepWithNextHangingRendererLayoutResult.GetOccupiedArea + ().GetBBox().GetHeight()); + bool ableToProcessKeepWithNext = false; + if (renderer.SetParent(this).Layout(new LayoutContext(rest)).GetStatus() != LayoutResult.NOTHING) { + // The area break will not be introduced and we are safe to place everything as is + UpdateCurrentAreaAndProcessRenderer(keepWithNextHangingRenderer, new List(), keepWithNextHangingRendererLayoutResult + ); + ableToProcessKeepWithNext = true; + } + else { + float originalElementHeight = keepWithNextHangingRendererLayoutResult.GetOccupiedArea().GetBBox().GetHeight + (); + IList trySplitHeightPoints = new List(); + float delta = 35; + for (int i = 1; i <= 5 && originalElementHeight - delta * i > originalElementHeight / 2; i++) { + trySplitHeightPoints.Add(originalElementHeight - delta * i); + } + for (int i_1 = 0; i_1 < trySplitHeightPoints.Count && !ableToProcessKeepWithNext; i_1++) { + float curElementSplitHeight = trySplitHeightPoints[i_1]; + LayoutArea firstElementSplitLayoutArea = currentArea.Clone(); + firstElementSplitLayoutArea.GetBBox().SetHeight(curElementSplitHeight).MoveUp(currentArea.GetBBox().GetHeight + () - curElementSplitHeight); + LayoutResult firstElementSplitLayoutResult = keepWithNextHangingRenderer.SetParent(this).Layout(new LayoutContext + (firstElementSplitLayoutArea.Clone())); + if (firstElementSplitLayoutResult.GetStatus() == LayoutResult.PARTIAL) { + LayoutArea storedArea = currentArea; + UpdateCurrentArea(firstElementSplitLayoutResult); + LayoutResult firstElementOverflowLayoutResult = firstElementSplitLayoutResult.GetOverflowRenderer().Layout + (new LayoutContext(currentArea.Clone())); + if (firstElementOverflowLayoutResult.GetStatus() == LayoutResult.FULL) { + LayoutArea secondElementLayoutArea = currentArea.Clone(); + secondElementLayoutArea.GetBBox().SetHeight(secondElementLayoutArea.GetBBox().GetHeight() - firstElementOverflowLayoutResult + .GetOccupiedArea().GetBBox().GetHeight()); + LayoutResult secondElementLayoutResult = renderer.SetParent(this).Layout(new LayoutContext(secondElementLayoutArea + )); + if (secondElementLayoutResult.GetStatus() != LayoutResult.NOTHING) { + ableToProcessKeepWithNext = true; + currentArea = firstElementSplitLayoutArea; + currentPageNumber = firstElementSplitLayoutArea.GetPageNumber(); + UpdateCurrentAreaAndProcessRenderer(firstElementSplitLayoutResult.GetSplitRenderer(), new List( + ), firstElementSplitLayoutResult); + UpdateCurrentArea(firstElementSplitLayoutResult); + UpdateCurrentAreaAndProcessRenderer(firstElementSplitLayoutResult.GetOverflowRenderer(), new List(), firstElementOverflowLayoutResult); + } + } + if (!ableToProcessKeepWithNext) { + currentArea = storedArea; + currentPageNumber = storedArea.GetPageNumber(); + } + } + } + } + if (!ableToProcessKeepWithNext && !currentArea.IsEmptyArea()) { + LayoutArea storedArea = currentArea; + UpdateCurrentArea(null); + LayoutResult firstElementLayoutResult = keepWithNextHangingRenderer.SetParent(this).Layout(new LayoutContext + (currentArea.Clone())); + if (firstElementLayoutResult.GetStatus() == LayoutResult.FULL) { + LayoutArea secondElementLayoutArea = currentArea.Clone(); + secondElementLayoutArea.GetBBox().SetHeight(secondElementLayoutArea.GetBBox().GetHeight() - firstElementLayoutResult + .GetOccupiedArea().GetBBox().GetHeight()); + LayoutResult secondElementLayoutResult = renderer.SetParent(this).Layout(new LayoutContext(secondElementLayoutArea + )); + if (secondElementLayoutResult.GetStatus() != LayoutResult.NOTHING) { + ableToProcessKeepWithNext = true; + UpdateCurrentAreaAndProcessRenderer(keepWithNextHangingRenderer, new List(), keepWithNextHangingRendererLayoutResult + ); + } + } + if (!ableToProcessKeepWithNext) { + currentArea = storedArea; + currentPageNumber = storedArea.GetPageNumber(); + } + } + if (!ableToProcessKeepWithNext) { + ILogger logger = LoggerFactory.GetLogger(typeof(RootRenderer)); + logger.Warn(LogMessageConstant.RENDERER_WAS_NOT_ABLE_TO_PROCESS_KEEP_WITH_NEXT); + UpdateCurrentAreaAndProcessRenderer(keepWithNextHangingRenderer, new List(), keepWithNextHangingRendererLayoutResult + ); + } + keepWithNextHangingRenderer = null; + keepWithNextHangingRendererLayoutResult = null; + } + } } } diff --git a/itext/itext.layout/itext/layout/renderer/TabRenderer.cs b/itext/itext.layout/itext/layout/renderer/TabRenderer.cs index ffe443a29e..c4d21cf7e1 100644 --- a/itext/itext.layout/itext/layout/renderer/TabRenderer.cs +++ b/itext/itext.layout/itext/layout/renderer/TabRenderer.cs @@ -50,6 +50,12 @@ source product. namespace iText.Layout.Renderer { public class TabRenderer : AbstractRenderer { + /// Creates a TabRenderer from its corresponding layout object + /// + /// the + /// + /// which this object should manage + /// public TabRenderer(Tab tab) : base(tab) { } diff --git a/itext/itext.layout/itext/layout/renderer/TableRenderer.cs b/itext/itext.layout/itext/layout/renderer/TableRenderer.cs index 0da04de7cf..3143b5761a 100644 --- a/itext/itext.layout/itext/layout/renderer/TableRenderer.cs +++ b/itext/itext.layout/itext/layout/renderer/TableRenderer.cs @@ -114,6 +114,7 @@ public TableRenderer(Table modelElement) : this(modelElement, new Table.RowRange(0, modelElement.GetNumberOfRows() - 1)) { } + /// public override void AddChild(IRenderer renderer) { if (renderer is CellRenderer) { // In case rowspan or colspan save cell into bottom left corner. @@ -127,6 +128,7 @@ public override void AddChild(IRenderer renderer) { } } + /// public override LayoutResult Layout(LayoutContext layoutContext) { LayoutArea area = layoutContext.GetArea(); Rectangle layoutBox = area.GetBBox().Clone(); @@ -136,6 +138,14 @@ public override LayoutResult Layout(LayoutContext layoutContext) { if (rowRange.GetStartRow() != 0) { SetProperty(Property.MARGIN_TOP, 0); } + // we can invoke #layout() twice (processing KEEP_TOGETHER for instance) + // so we need to clear the results of previous #layout() invocation + heights.Clear(); + childRenderers.Clear(); + // Cells' up moves occured while split processing + // key is column number (there can be only one move during one split + // value is the previous row number of the cell + IDictionary rowMoves = new Dictionary(); ApplyMargins(layoutBox, false); ApplyBorderBox(layoutBox, false); if (IsPositioned()) { @@ -163,7 +173,7 @@ public override LayoutResult Layout(LayoutContext layoutContext) { LayoutResult result = headerRenderer.Layout(new LayoutContext(new LayoutArea(area.GetPageNumber(), layoutBox ))); if (result.GetStatus() != LayoutResult.FULL) { - return new LayoutResult(LayoutResult.NOTHING, null, null, this); + return new LayoutResult(LayoutResult.NOTHING, null, null, this, result.GetCauseOfNothing()); } float headerHeight = result.GetOccupiedArea().GetBBox().GetHeight(); layoutBox.DecreaseHeight(headerHeight); @@ -176,7 +186,7 @@ public override LayoutResult Layout(LayoutContext layoutContext) { LayoutResult result = footerRenderer.Layout(new LayoutContext(new LayoutArea(area.GetPageNumber(), layoutBox ))); if (result.GetStatus() != LayoutResult.FULL) { - return new LayoutResult(LayoutResult.NOTHING, null, null, this); + return new LayoutResult(LayoutResult.NOTHING, null, null, this, result.GetCauseOfNothing()); } float footerHeight = result.GetOccupiedArea().GetBBox().GetHeight(); footerRenderer.Move(0, -(layoutBox.GetHeight() - footerHeight)); @@ -205,25 +215,32 @@ public override LayoutResult Layout(LayoutContext layoutContext) { bool cellWithBigRowspanAdded = false; IList currChildRenderers = new List(); // Process in a queue, because we might need to add a cell from the future, i.e. having big rowspan in case of split. - Queue cellProcessingQueue = new Queue(); + LinkedList cellProcessingQueue = new LinkedList(); for (int col = 0; col < currentRow.Length; col++) { if (currentRow[col] != null) { - cellProcessingQueue.Enqueue(new TableRenderer.CellRendererInfo(currentRow[col], col, row)); + cellProcessingQueue.AddLast(new TableRenderer.CellRendererInfo(currentRow[col], col, row)); } } - while (!cellProcessingQueue.IsEmpty()) { - TableRenderer.CellRendererInfo currentCellInfo = cellProcessingQueue.Dequeue(); + // the element which was the first to cause Layout.Nothing + IRenderer firstCauseOfNothing = null; + while (cellProcessingQueue.Count > 0) { + TableRenderer.CellRendererInfo currentCellInfo = cellProcessingQueue.JRemoveFirst(); int col_1 = currentCellInfo.column; CellRenderer cell = currentCellInfo.cellRenderer; if (cell != null) { - BuildBordersArrays(cell, row, ((Cell)cell.GetModelElement()).GetRowspan(), ((Cell)cell.GetModelElement()). - GetColspan(), true); + BuildBordersArrays(cell, row, true); } if (row + 1 < rows.Count) { CellRenderer nextCell = rows[row + 1][col_1]; if (nextCell != null) { - BuildBordersArrays(nextCell, row + 1, ((Cell)nextCell.GetModelElement()).GetRowspan(), ((Cell)nextCell.GetModelElement - ()).GetColspan(), true); + BuildBordersArrays(nextCell, row + 1, true); + } + } + if (col_1 + 1 < rows[row].Length) { + CellRenderer nextCell = rows[row][col_1 + 1]; + if (nextCell != null) { + BuildBordersArrays(nextCell, row, true); } } targetOverflowRowIndex[col_1] = currentCellInfo.finishRowInd; @@ -254,10 +271,15 @@ public override LayoutResult Layout(LayoutContext layoutContext) { cell.SetProperty(Property.VERTICAL_ALIGNMENT, null); LayoutResult cellResult = cell.SetParent(this).Layout(new LayoutContext(cellArea)); cell.SetProperty(Property.VERTICAL_ALIGNMENT, verticalAlignment); - //width of BlockRenderer depends on child areas, while in cell case it is hardly define. + // width of BlockRenderer depends on child areas, while in cell case it is hardly define. if (cellResult.GetStatus() != LayoutResult.NOTHING) { cell.GetOccupiedArea().GetBBox().SetWidth(cellWidth); } + else { + if (null == firstCauseOfNothing) { + firstCauseOfNothing = cellResult.GetCauseOfNothing(); + } + } if (currentCellHasBigRowspan) { // cell from the future if (cellResult.GetStatus() == LayoutResult.PARTIAL) { @@ -267,6 +289,7 @@ public override LayoutResult Layout(LayoutContext layoutContext) { else { rows[currentCellInfo.finishRowInd][col_1] = null; currentRow[col_1] = cell; + rowMoves[col_1] = currentCellInfo.finishRowInd; } } else { @@ -285,7 +308,7 @@ public override LayoutResult Layout(LayoutContext layoutContext) { cellProcessingQueue.Clear(); for (int addCol = 0; addCol < currentRow.Length; addCol++) { if (currentRow[addCol] != null) { - cellProcessingQueue.Enqueue(new TableRenderer.CellRendererInfo(currentRow[addCol], addCol, row)); + cellProcessingQueue.AddLast(new TableRenderer.CellRendererInfo(currentRow[addCol], addCol, row)); } } footerRenderer = null; @@ -304,7 +327,7 @@ public override LayoutResult Layout(LayoutContext layoutContext) { verticalAlignment = addRenderer.GetProperty(Property.VERTICAL_ALIGNMENT); if (verticalAlignment != null && verticalAlignment.Equals(VerticalAlignment.BOTTOM)) { if (row + addRenderer.GetPropertyAsInteger(Property.ROWSPAN) - 1 < addRow) { - cellProcessingQueue.Enqueue(new TableRenderer.CellRendererInfo(addRenderer, addCol_1, addRow)); + cellProcessingQueue.AddLast(new TableRenderer.CellRendererInfo(addRenderer, addCol_1, addRow)); cellWithBigRowspanAdded = true; } else { @@ -329,7 +352,7 @@ public override LayoutResult Layout(LayoutContext layoutContext) { } else { if (row + addRenderer.GetPropertyAsInteger(Property.ROWSPAN) - 1 >= addRow) { - cellProcessingQueue.Enqueue(new TableRenderer.CellRendererInfo(addRenderer, addCol_1, addRow)); + cellProcessingQueue.AddLast(new TableRenderer.CellRendererInfo(addRenderer, addCol_1, addRow)); cellWithBigRowspanAdded = true; } } @@ -337,6 +360,14 @@ public override LayoutResult Layout(LayoutContext layoutContext) { } } } + else { + // if cell in current row has big rowspan + // we need to process it specially too, + // because some problems (for instance, borders related) can occur + if (((Cell)cell.GetModelElement()).GetRowspan() > 1) { + cellWithBigRowspanAdded = true; + } + } } } split = true; @@ -404,7 +435,9 @@ public override LayoutResult Layout(LayoutContext layoutContext) { if (hasContent || cellWithBigRowspanAdded || splits[col_1].GetStatus() == LayoutResult.NOTHING) { currentRow[col_1] = null; CellRenderer cellOverflow = (CellRenderer)splits[col_1].GetOverflowRenderer(); - cellOverflow.SetBorders(cellOverflow.GetBorders()[2], 0); + if (splits[col_1].GetStatus() != LayoutResult.NOTHING) { + cellOverflow.SetBorders(cellOverflow.GetBorders()[2], 0); + } rows[targetOverflowRowIndex[col_1]][col_1] = (CellRenderer)cellOverflow.SetParent(splitResult[1]); } else { @@ -423,7 +456,7 @@ public override LayoutResult Layout(LayoutContext layoutContext) { minRowspan = Math.Min(minRowspan, rowspans[col_2]); } } - for (int col_3 = 0; col_3 < columnsWithCellToBeSplitted.Length; col_3++) { + for (int col_3 = 0; col_3 < numberOfColumns; col_3++) { if (columnsWithCellToBeSplitted[col_3]) { if (1 == minRowspan) { // Here we use the same cell, but create a new renderer which doesn't have any children, @@ -443,7 +476,7 @@ public override LayoutResult Layout(LayoutContext layoutContext) { rows[i + 1][col_3] = null; } // the number of cells behind is less then minRowspan-1 - // so we should process the last cell in the columnt as in the case 1 == minRowspan + // so we should process the last cell in the column as in the case 1 == minRowspan if (i != row + minRowspan - 1 && null != rows[i][col_3]) { Cell overflowCell = ((Cell)rows[i][col_3].GetModelElement()); rows[i][col_3].isLastRendererForModelElement = false; @@ -466,9 +499,18 @@ public override LayoutResult Layout(LayoutContext layoutContext) { } ApplyBorderBox(occupiedArea.GetBBox(), true); ApplyMargins(occupiedArea.GetBBox(), true); - if (IsKeepTogether() && !true.Equals(GetPropertyAsBoolean(Property.FORCED_PLACEMENT)) && !(this.parent is - CellRenderer)) { - return new LayoutResult(LayoutResult.NOTHING, occupiedArea, null, this); + // On the next page we need to process rows without any changes except moves connected to actual cell splitting + foreach (KeyValuePair entry in rowMoves) { + // Move the cell back to its row if there was no actual split + if (null == splitResult[1].rows[(int)entry.Value - splitResult[0].rows.Count][entry.Key]) { + splitResult[1].rows[(int)entry.Value - splitResult[0].rows.Count][entry.Key] = splitResult[1].rows[row - splitResult + [0].rows.Count][entry.Key]; + splitResult[1].rows[row - splitResult[0].rows.Count][entry.Key] = null; + } + } + if (IsKeepTogether() && !true.Equals(GetPropertyAsBoolean(Property.FORCED_PLACEMENT))) { + return new LayoutResult(LayoutResult.NOTHING, occupiedArea, null, this, null == firstCauseOfNothing ? this + : firstCauseOfNothing); } else { int status = (childRenderers.IsEmpty() && footerRenderer == null) ? LayoutResult.NOTHING : LayoutResult.PARTIAL; @@ -476,7 +518,8 @@ public override LayoutResult Layout(LayoutContext layoutContext) { return new LayoutResult(LayoutResult.FULL, occupiedArea, null, null); } else { - return new LayoutResult(status, occupiedArea, splitResult[0], splitResult[1]); + return new LayoutResult(status, occupiedArea, splitResult[0], splitResult[1], LayoutResult.NOTHING == status + ? firstCauseOfNothing : null); } } } @@ -499,6 +542,7 @@ public override LayoutResult Layout(LayoutContext layoutContext) { return new LayoutResult(LayoutResult.FULL, occupiedArea, null, null); } + /// public override void Draw(DrawContext drawContext) { PdfDocument document = drawContext.GetDocument(); bool isTagged = drawContext.IsTaggingEnabled() && GetModelElement() is IAccessibleElement; @@ -532,6 +576,7 @@ public override void Draw(DrawContext drawContext) { } } + /// public override void DrawChildren(DrawContext drawContext) { Table modelElement = (Table)GetModelElement(); if (headerRenderer != null) { @@ -615,12 +660,14 @@ public override void DrawChildren(DrawContext drawContext) { } } + /// public override IRenderer GetNextRenderer() { iText.Layout.Renderer.TableRenderer nextTable = new iText.Layout.Renderer.TableRenderer(); nextTable.modelElement = modelElement; return nextTable; } + /// public override void Move(float dxRight, float dyUp) { base.Move(dxRight, dyUp); if (headerRenderer != null) { @@ -778,9 +825,11 @@ protected internal virtual void DrawBorders(DrawContext drawContext) { } Border lastBorder = borders.Count > j - 1 ? borders[j - 1] : null; if (lastBorder != null) { - if (verticalBorders[j].Count > 0) { + if (verticalBorders != null && verticalBorders[j] != null && verticalBorders[j].Count > 0) { if (i == 0) { - x2 += verticalBorders[j][i].GetWidth() / 2; + if (verticalBorders[j][i] != null) { + x2 += verticalBorders[j][i].GetWidth() / 2; + } } else { if (i == horizontalBorders.Count - 1 && verticalBorders[j].Count >= i - 1 && verticalBorders[j][i - 1] != @@ -897,7 +946,9 @@ private bool CanFitRowsInGivenArea(LayoutArea layoutArea, int startRow, float[] return true; } - private void BuildBordersArrays(CellRenderer cell, int row, int rowspan, int colspan, bool hasContent) { + private void BuildBordersArrays(CellRenderer cell, int row, bool hasContent) { + int colspan = (int)cell.GetPropertyAsInteger(Property.COLSPAN); + int rowspan = (int)cell.GetPropertyAsInteger(Property.ROWSPAN); int colN = ((Cell)cell.GetModelElement()).GetCol(); Border[] cellBorders = cell.GetBorders(); if (row + 1 - rowspan < 0) { diff --git a/itext/itext.layout/itext/layout/renderer/TextRenderer.cs b/itext/itext.layout/itext/layout/renderer/TextRenderer.cs index 6a8eeeba38..cc9e163dac 100644 --- a/itext/itext.layout/itext/layout/renderer/TextRenderer.cs +++ b/itext/itext.layout/itext/layout/renderer/TextRenderer.cs @@ -60,1116 +60,968 @@ source product. using iText.Layout.Properties; using iText.Layout.Splitting; -namespace iText.Layout.Renderer -{ - /// - /// This class represents the - /// renderer - /// object for a - /// - /// object. It will draw the glyphs of the textual content on the - /// - /// . - /// - public class TextRenderer : AbstractRenderer - { - protected internal const float TEXT_SPACE_COEFF = FontProgram.UNITS_NORMALIZATION; - - private const float ITALIC_ANGLE = 0.21256f; - - private const float BOLD_SIMULATION_STROKE_COEFF = 1 / 30f; - - private const float TYPO_ASCENDER_SCALE_COEFF = 1.2f; - - protected internal float yLineOffset; - - protected internal GlyphLine text; - - protected internal GlyphLine line; - - protected internal String strToBeConverted; - - protected internal bool otfFeaturesApplied = false; - - protected internal float tabAnchorCharacterPosition = -1; - - /// Creates a TextRenderer from its corresponding layout object. - /// - /// the - /// - /// which this object should manage - /// - public TextRenderer(Text textElement) - : this(textElement, textElement.GetText()) - { - } - - /// - /// Creates a TextRenderer from its corresponding layout object, with a custom - /// text to replace the contents of the - /// - /// . - /// - /// - /// the - /// - /// which this object should manage - /// - /// the replacement text - public TextRenderer(Text textElement, String text) - : base(textElement) - { - this.strToBeConverted = text; - } - - protected internal TextRenderer(iText.Layout.Renderer.TextRenderer other) - : base(other) - { - this.text = other.text; - this.line = other.line; - this.strToBeConverted = other.strToBeConverted; - this.otfFeaturesApplied = other.otfFeaturesApplied; - this.tabAnchorCharacterPosition = other.tabAnchorCharacterPosition; - } - - public override LayoutResult Layout(LayoutContext layoutContext) - { - ConvertWaitingStringToGlyphLine(); - LayoutArea area = layoutContext.GetArea(); - float[] margins = GetMargins(); - Rectangle layoutBox = ApplyMargins(area.GetBBox().Clone(), margins, false); - Border[] borders = GetBorders(); - ApplyBorderBox(layoutBox, borders, false); - occupiedArea = new LayoutArea(area.GetPageNumber(), new Rectangle(layoutBox.GetX( - ), layoutBox.GetY() + layoutBox.GetHeight(), 0, 0)); - bool anythingPlaced = false; - int currentTextPos = text.start; - float fontSize = (float)this.GetPropertyAsFloat(Property.FONT_SIZE); - float textRise = (float)this.GetPropertyAsFloat(Property.TEXT_RISE); - float? characterSpacing = this.GetPropertyAsFloat(Property.CHARACTER_SPACING); - float? wordSpacing = this.GetPropertyAsFloat(Property.WORD_SPACING); - PdfFont font = this.GetPropertyAsFont(Property.FONT); - float? hScale = this.GetProperty(Property.HORIZONTAL_SCALING, (float?)1f); - ISplitCharacters splitCharacters = this.GetProperty(Property.SPLIT_CHARACTERS); - float italicSkewAddition = true.Equals(GetPropertyAsBoolean(Property.ITALIC_SIMULATION)) ? ITALIC_ANGLE * fontSize : 0; - float boldSimulationAddition = true.Equals(GetPropertyAsBoolean(Property.BOLD_SIMULATION)) ? BOLD_SIMULATION_STROKE_COEFF * fontSize : 0; - line = new GlyphLine(text); - line.start = line.end = -1; - FontMetrics fontMetrics = font.GetFontProgram().GetFontMetrics(); - float ascender; - float descender; - if (fontMetrics.GetWinAscender() == 0 || fontMetrics.GetWinDescender() == 0 || fontMetrics - .GetTypoAscender() == fontMetrics.GetWinAscender() && fontMetrics.GetTypoDescender - () == fontMetrics.GetWinDescender()) - { - ascender = fontMetrics.GetTypoAscender() * TYPO_ASCENDER_SCALE_COEFF; - descender = fontMetrics.GetTypoDescender() * TYPO_ASCENDER_SCALE_COEFF; - } - else - { - ascender = fontMetrics.GetWinAscender(); - descender = fontMetrics.GetWinDescender(); - } - float currentLineAscender = 0; - float currentLineDescender = 0; - float currentLineHeight = 0; - int initialLineTextPos = currentTextPos; - float currentLineWidth = 0; - int previousCharPos = -1; - char? tabAnchorCharacter = this.GetProperty(Property.TAB_ANCHOR); - TextLayoutResult result = null; - // true in situations like "\nHello World" - bool isSplitForcedByImmediateNewLine = false; - // true in situations like "Hello\nWorld" - bool isSplitForcedByNewLineAndWeNeedToIgnoreNewLineSymbol = false; - while (currentTextPos < text.end) - { - if (NoPrint(text.Get(currentTextPos))) - { - currentTextPos++; - continue; - } - int nonBreakablePartEnd = text.end - 1; - float nonBreakablePartFullWidth = 0; - float nonBreakablePartWidthWhichDoesNotExceedAllowedWidth = 0; - float nonBreakablePartMaxAscender = 0; - float nonBreakablePartMaxDescender = 0; - float nonBreakablePartMaxHeight = 0; - int firstCharacterWhichExceedsAllowedWidth = -1; - for (int ind = currentTextPos; ind < text.end; ind++) - { - if (IsNewLine(text, ind)) - { - isSplitForcedByNewLineAndWeNeedToIgnoreNewLineSymbol = true; - firstCharacterWhichExceedsAllowedWidth = ind + 1; - if (text.start == currentTextPos) - { - isSplitForcedByImmediateNewLine = true; - // Notice that in that case we do not need to ignore the new line symbol ('\n') - isSplitForcedByNewLineAndWeNeedToIgnoreNewLineSymbol = false; - } - break; - } - Glyph currentGlyph = text.Get(ind); - if (NoPrint(currentGlyph)) - { - continue; - } - if (tabAnchorCharacter != null && tabAnchorCharacter == (int)text.Get(ind).GetUnicode - ()) - { - tabAnchorCharacterPosition = currentLineWidth + nonBreakablePartFullWidth; - tabAnchorCharacter = (char?)null; - } - float glyphWidth = GetCharWidth(currentGlyph, fontSize, hScale, characterSpacing, - wordSpacing) / TEXT_SPACE_COEFF; - float xAdvance = previousCharPos != -1 ? text.Get(previousCharPos).GetXAdvance() : - 0; - if (xAdvance != 0) - { - xAdvance = ScaleXAdvance(xAdvance, fontSize, hScale) / TEXT_SPACE_COEFF; - } - if ((nonBreakablePartFullWidth + glyphWidth + xAdvance + italicSkewAddition + boldSimulationAddition - ) > layoutBox.GetWidth() - currentLineWidth && firstCharacterWhichExceedsAllowedWidth - == -1) - { - firstCharacterWhichExceedsAllowedWidth = ind; - } - if (firstCharacterWhichExceedsAllowedWidth == -1) - { - nonBreakablePartWidthWhichDoesNotExceedAllowedWidth += glyphWidth + xAdvance; - } - nonBreakablePartFullWidth += glyphWidth + xAdvance; - nonBreakablePartMaxAscender = Math.Max(nonBreakablePartMaxAscender, ascender); - nonBreakablePartMaxDescender = Math.Min(nonBreakablePartMaxDescender, descender); - nonBreakablePartMaxHeight = (nonBreakablePartMaxAscender - nonBreakablePartMaxDescender - ) * fontSize / TEXT_SPACE_COEFF + textRise; - previousCharPos = ind; - if (nonBreakablePartFullWidth + italicSkewAddition + boldSimulationAddition > layoutBox - .GetWidth()) - { - // we have extracted all the information we wanted and we do not want to continue. - // we will have to split the word anyway. - break; - } - if (splitCharacters.IsSplitCharacter(text, ind) || ind + 1 == text.end || splitCharacters - .IsSplitCharacter(text, ind + 1) && (char.IsWhiteSpace((char)(int)text.Get(ind + - 1).GetUnicode()) || char.IsSeparator((char)(int)text.Get(ind + 1).GetUnicode()) - )) - { - nonBreakablePartEnd = ind; - break; - } - } - if (firstCharacterWhichExceedsAllowedWidth == -1) - { - // can fit the whole word in a line - if (line.start == -1) - { - line.start = currentTextPos; - } - line.end = Math.Max(line.end, nonBreakablePartEnd + 1); - currentLineAscender = Math.Max(currentLineAscender, nonBreakablePartMaxAscender); - currentLineDescender = Math.Min(currentLineDescender, nonBreakablePartMaxDescender - ); - currentLineHeight = Math.Max(currentLineHeight, nonBreakablePartMaxHeight); - currentTextPos = nonBreakablePartEnd + 1; - currentLineWidth += nonBreakablePartFullWidth; - anythingPlaced = true; - } - else - { - // check if line height exceeds the allowed height - if (Math.Max(currentLineHeight, nonBreakablePartMaxHeight) > layoutBox.GetHeight( - )) - { - // the line does not fit because of height - full overflow - iText.Layout.Renderer.TextRenderer[] splitResult = Split(initialLineTextPos); - ApplyBorderBox(occupiedArea.GetBBox(), borders, true); - ApplyMargins(occupiedArea.GetBBox(), margins, true); - return new TextLayoutResult(LayoutResult.NOTHING, occupiedArea, splitResult[0], splitResult - [1]); - } - else - { - // cannot fit a word as a whole - bool wordSplit = false; - bool hyphenationApplied = false; - HyphenationConfig hyphenationConfig = this.GetProperty(Property.HYPHENATION); - if (hyphenationConfig != null) - { - int[] wordBounds = GetWordBoundsForHyphenation(text, currentTextPos, text.end, Math - .Max(currentTextPos, firstCharacterWhichExceedsAllowedWidth - 1)); - if (wordBounds != null) - { - String word = text.ToUnicodeString(wordBounds[0], wordBounds[1]); - iText.Layout.Hyphenation.Hyphenation hyph = hyphenationConfig.Hyphenate(word - ); - if (hyph != null) - { - for (int i = hyph.Length() - 1; i >= 0; i--) - { - String pre = hyph.GetPreHyphenText(i); - String pos = hyph.GetPostHyphenText(i); - float currentHyphenationChoicePreTextWidth = GetGlyphLineWidth(ConvertToGlyphLine - (pre + hyphenationConfig.GetHyphenSymbol()), fontSize, hScale, characterSpacing, - wordSpacing); - if (currentLineWidth + currentHyphenationChoicePreTextWidth + italicSkewAddition - + boldSimulationAddition <= layoutBox.GetWidth()) - { - hyphenationApplied = true; - if (line.start == -1) - { - line.start = currentTextPos; - } - line.end = Math.Max(line.end, currentTextPos + pre.Length); - GlyphLine lineCopy = line.Copy(line.start, line.end); - lineCopy.Add(font.GetGlyph(hyphenationConfig.GetHyphenSymbol())); - lineCopy.end++; - line = lineCopy; - // TODO these values are based on whole word. recalculate properly based on hyphenated part - currentLineAscender = Math.Max(currentLineAscender, nonBreakablePartMaxAscender); - currentLineDescender = Math.Min(currentLineDescender, nonBreakablePartMaxDescender - ); - currentLineHeight = Math.Max(currentLineHeight, nonBreakablePartMaxHeight); - currentLineWidth += currentHyphenationChoicePreTextWidth; - currentTextPos += pre.Length; - break; - } - } - } - } - } - if ((nonBreakablePartFullWidth > layoutBox.GetWidth() && !anythingPlaced && !hyphenationApplied - ) || (isSplitForcedByImmediateNewLine)) - { - // if the word is too long for a single line we will have to split it - wordSplit = true; - if (line.start == -1) - { - line.start = currentTextPos; - } - currentTextPos = firstCharacterWhichExceedsAllowedWidth; - line.end = Math.Max(line.end, firstCharacterWhichExceedsAllowedWidth); - if (nonBreakablePartFullWidth > layoutBox.GetWidth() && !anythingPlaced && !hyphenationApplied) - { - currentLineAscender = Math.Max(currentLineAscender, nonBreakablePartMaxAscender); - currentLineDescender = Math.Min(currentLineDescender, nonBreakablePartMaxDescender - ); - currentLineHeight = Math.Max(currentLineHeight, nonBreakablePartMaxHeight); - currentLineWidth += nonBreakablePartWidthWhichDoesNotExceedAllowedWidth; - } - else - { - // process empty line (e.g. '\n') - currentLineAscender = ascender; - currentLineDescender = descender; - currentLineHeight = (currentLineAscender - currentLineDescender) * fontSize / TEXT_SPACE_COEFF - + textRise; - currentLineWidth += GetCharWidth(line.Get(0), fontSize, hScale, characterSpacing, - wordSpacing) / TEXT_SPACE_COEFF; - } - } - if (line.end <= 0) - { - result = new TextLayoutResult(LayoutResult.NOTHING, occupiedArea, null, this); - } - else - { - result = new TextLayoutResult(LayoutResult.PARTIAL, occupiedArea, null, null).SetWordHasBeenSplit - (wordSplit); - } - break; - } - } - } - if (result != null && result.GetStatus() == LayoutResult.NOTHING) - { - return result; - } - else - { - if (currentLineHeight > layoutBox.GetHeight() && !true.Equals(GetPropertyAsBoolean(Property.FORCED_PLACEMENT))) - { - ApplyBorderBox(occupiedArea.GetBBox(), borders, true); - ApplyMargins(occupiedArea.GetBBox(), margins, true); - return new TextLayoutResult(LayoutResult.NOTHING, occupiedArea, null, this); - } - yLineOffset = currentLineAscender * fontSize / TEXT_SPACE_COEFF; - occupiedArea.GetBBox().MoveDown(currentLineHeight); - occupiedArea.GetBBox().SetHeight(occupiedArea.GetBBox().GetHeight() + currentLineHeight - ); - occupiedArea.GetBBox().SetWidth(Math.Max(occupiedArea.GetBBox().GetWidth(), currentLineWidth - )); - layoutBox.SetHeight(area.GetBBox().GetHeight() - currentLineHeight); - occupiedArea.GetBBox().SetWidth(occupiedArea.GetBBox().GetWidth() + italicSkewAddition - + boldSimulationAddition); - ApplyBorderBox(occupiedArea.GetBBox(), borders, true); - ApplyMargins(occupiedArea.GetBBox(), margins, true); - if (result != null) - { - iText.Layout.Renderer.TextRenderer[] split; - if (isSplitForcedByNewLineAndWeNeedToIgnoreNewLineSymbol) - { - // ignore '\n' - split = Split(currentTextPos + 1); - } - else - { - split = Split(currentTextPos); - } - // if (split[1].length() > 0 && split[1].charAt(0) != null && split[1].charAt(0) == '\n') { - if (isSplitForcedByNewLineAndWeNeedToIgnoreNewLineSymbol) - { - result.SetSplitForcedByNewline(true); - } - result.SetSplitRenderer(split[0]); - // no sense to process empty renderer - if (split[1].text.start != split[1].text.end) - { - result.SetOverflowRenderer(split[1]); - } - } - else - { - result = new TextLayoutResult(LayoutResult.FULL, occupiedArea, null, null); - } - } - return result; - } - - public virtual void ApplyOtf() - { - ConvertWaitingStringToGlyphLine(); - UnicodeScript? script = this.GetProperty(Property.FONT_SCRIPT); - if (!otfFeaturesApplied) - { - if (script == null && TypographyUtils.IsTypographyModuleInitialized()) - { - // Try to autodetect complex script. - ICollection supportedScripts = TypographyUtils.GetSupportedScripts - (); - IDictionary scriptFrequency = new Dictionary(); - for (int i = text.start; i < text.end; i++) - { - int unicode = text.Get(i).GetUnicode(); - UnicodeScript? glyphScript = unicode > -1 ? iText.IO.Util.UnicodeScriptUtil.Of - (unicode) : (UnicodeScript?) null; - if (glyphScript != null) - { - if (scriptFrequency.ContainsKey((UnicodeScript)glyphScript)) - { - scriptFrequency[(UnicodeScript)glyphScript] = scriptFrequency.Get((UnicodeScript)glyphScript) + 1; - } - else - { - scriptFrequency[(UnicodeScript)glyphScript] = 1; - } - } - } - int? max = 0; - UnicodeScript? selectScript = null; - foreach (KeyValuePair entry in scriptFrequency) - { - UnicodeScript? entryScript = entry.Key; - if (entry.Value > max && !UnicodeScript.COMMON.Equals(entryScript) && !UnicodeScript - .UNKNOWN.Equals(entryScript)) - { - max = entry.Value; - selectScript = entryScript; - } - } - if (selectScript == UnicodeScript.ARABIC || selectScript == UnicodeScript.HEBREW - && parent is LineRenderer) - { - SetProperty(Property.BASE_DIRECTION, BaseDirection.DEFAULT_BIDI - ); - } - if (selectScript != null && supportedScripts != null && supportedScripts.Contains - ((UnicodeScript)selectScript)) - { - script = selectScript; - } - } - PdfFont font = GetPropertyAsFont(Property.FONT); - if (IsOtfFont(font) && script != null) - { - TypographyUtils.ApplyOtfScript(font.GetFontProgram(), text, script); - } - FontKerning fontKerning = (FontKerning)this.GetProperty(Property.FONT_KERNING, FontKerning.NO); - if (fontKerning == FontKerning.YES) - { - TypographyUtils.ApplyKerning(font.GetFontProgram(), text); - } - otfFeaturesApplied = true; - } - } - - public override void Draw(DrawContext drawContext) - { - base.Draw(drawContext); - PdfDocument document = drawContext.GetDocument(); - bool isTagged = drawContext.IsTaggingEnabled() && GetModelElement() is IAccessibleElement; - bool isArtifact = false; - TagTreePointer tagPointer = null; - IAccessibleElement accessibleElement = null; - if (isTagged) - { - accessibleElement = (IAccessibleElement)GetModelElement(); - PdfName role = accessibleElement.GetRole(); - if (role != null && !PdfName.Artifact.Equals(role)) - { - tagPointer = document.GetTagStructureContext().GetAutoTaggingPointer(); - if (!tagPointer.IsElementConnectedToTag(accessibleElement)) - { - AccessibleAttributesApplier.ApplyLayoutAttributes(accessibleElement.GetRole(), this - , document); - } - tagPointer.AddTag(accessibleElement, true); - } - else - { - isTagged = false; - if (PdfName.Artifact.Equals(role)) - { - isArtifact = true; - } - } - } - bool isRelativePosition = IsRelativePosition(); - if (isRelativePosition) - { - ApplyAbsolutePositioningTranslation(false); - } - float leftBBoxX = occupiedArea.GetBBox().GetX(); - if (line.end > line.start) - { - PdfFont font = GetPropertyAsFont(Property.FONT); - float fontSize = (float)this.GetPropertyAsFloat(Property.FONT_SIZE); - Color fontColor = GetPropertyAsColor(Property.FONT_COLOR); - int? textRenderingMode = this.GetProperty(Property.TEXT_RENDERING_MODE); - float? textRise = this.GetPropertyAsFloat(Property.TEXT_RISE); - float? characterSpacing = this.GetPropertyAsFloat(Property.CHARACTER_SPACING); - float? wordSpacing = this.GetPropertyAsFloat(Property.WORD_SPACING); - float? horizontalScaling = this.GetProperty(Property.HORIZONTAL_SCALING); - float?[] skew = this.GetProperty(Property.SKEW); - bool italicSimulation = true.Equals(GetPropertyAsBoolean(Property.ITALIC_SIMULATION)); - bool boldSimulation = true.Equals(GetPropertyAsBoolean(Property.BOLD_SIMULATION)); - float? strokeWidth = null; - if (boldSimulation) - { - textRenderingMode = PdfCanvasConstants.TextRenderingMode.FILL_STROKE; - strokeWidth = fontSize / 30; - } - PdfCanvas canvas = drawContext.GetCanvas(); - if (isTagged) - { - canvas.OpenTag(tagPointer.GetTagReference()); - } - else - { - if (isArtifact) - { - canvas.OpenTag(new CanvasArtifact()); - } - } - canvas.SaveState().BeginText().SetFontAndSize(font, fontSize); - if (skew != null && skew.Length == 2) - { - canvas.SetTextMatrix(1, (float)skew[0], (float)skew[1], 1, leftBBoxX, GetYLine()); - } - else - { - if (italicSimulation) - { - canvas.SetTextMatrix(1, 0, ITALIC_ANGLE, 1, leftBBoxX, GetYLine()); - } - else - { - canvas.MoveText(leftBBoxX, GetYLine()); - } - } - if (textRenderingMode != PdfCanvasConstants.TextRenderingMode.FILL) - { - canvas.SetTextRenderingMode((int)textRenderingMode); - } - if (textRenderingMode == PdfCanvasConstants.TextRenderingMode.STROKE || textRenderingMode - == PdfCanvasConstants.TextRenderingMode.FILL_STROKE) - { - if (strokeWidth == null) - { - strokeWidth = this.GetPropertyAsFloat(Property.STROKE_WIDTH); - } - if (strokeWidth != null && strokeWidth != 1f) - { - canvas.SetLineWidth((float)strokeWidth); - } - Color strokeColor = GetPropertyAsColor(Property.STROKE_COLOR); - if (strokeColor == null) - { - strokeColor = fontColor; - } - if (strokeColor != null) - { - canvas.SetStrokeColor(strokeColor); - } - } - if (fontColor != null) - { - canvas.SetFillColor(fontColor); - } - if (textRise != null && textRise != 0) - { - canvas.SetTextRise((float)textRise); - } - if (characterSpacing != null && characterSpacing != 0) - { - canvas.SetCharacterSpacing((float)characterSpacing); - } - if (wordSpacing != null && wordSpacing != 0) - { - canvas.SetWordSpacing((float)wordSpacing); - } - if (horizontalScaling != null && horizontalScaling != 1) - { - canvas.SetHorizontalScaling((float)horizontalScaling * 100); - } - GlyphLine.IGlyphLineFilter filter = new _IGlyphLineFilter_546(); - if (HasOwnProperty(Property.REVERSED)) { - //We should mark a RTL written text - IDictionary outputs = GetOutputChunks(); - foreach (KeyValuePair output in outputs) - { - GlyphLine o = output.Key.Filter(filter); - if ((bool)output.Value) - { - canvas.OpenTag(new CanvasTag(PdfName.ReversedChars)); - } - canvas.ShowText(o); - if ((bool)output.Value) - { - canvas.CloseTag(); - } - } - } - else - { - canvas.ShowText(line.Filter(filter)); - } - canvas.EndText().RestoreState(); - if (isTagged || isArtifact) - { - canvas.CloseTag(); - } - Object underlines = this.GetProperty(Property.UNDERLINE); - if (underlines is IList) - { - foreach (Object underline in (IList)underlines) - { - if (underline is Underline) - { - DrawSingleUnderline((Underline)underline, fontColor, canvas, fontSize, italicSimulation - ? ITALIC_ANGLE : 0); - } - } - } - else - { - if (underlines is Underline) - { - DrawSingleUnderline((Underline)underlines, fontColor, canvas, fontSize, italicSimulation - ? ITALIC_ANGLE : 0); - } - } - } - if (isRelativePosition) - { - ApplyAbsolutePositioningTranslation(false); - } - if (isTagged) - { - tagPointer.MoveToParent(); - if (isLastRendererForModelElement) - { - tagPointer.RemoveElementConnectionToTag(accessibleElement); - } - } - } - - private sealed class _IGlyphLineFilter_546 : GlyphLine.IGlyphLineFilter - { - public _IGlyphLineFilter_546() - { - } - - public bool Accept(Glyph glyph) - { - return !iText.Layout.Renderer.TextRenderer.NoPrint(glyph); - } - } - - public override void DrawBackground(DrawContext drawContext) - { - Background background = this.GetProperty(Property.BACKGROUND); - float? textRise = this.GetPropertyAsFloat(Property.TEXT_RISE); - float bottomBBoxY = occupiedArea.GetBBox().GetY(); - float leftBBoxX = occupiedArea.GetBBox().GetX(); - if (background != null) - { - bool isTagged = drawContext.IsTaggingEnabled() && GetModelElement() is IAccessibleElement; - PdfCanvas canvas = drawContext.GetCanvas(); - if (isTagged) - { - canvas.OpenTag(new CanvasArtifact()); - } - canvas.SaveState().SetFillColor(background.GetColor()); - canvas.Rectangle(leftBBoxX - background.GetExtraLeft(), bottomBBoxY + (float)textRise - - background.GetExtraBottom(), occupiedArea.GetBBox().GetWidth() + background.GetExtraLeft - () + background.GetExtraRight(), occupiedArea.GetBBox().GetHeight() - (float)textRise - + background.GetExtraTop() + background.GetExtraBottom()); - canvas.Fill().RestoreState(); - if (isTagged) - { - canvas.CloseTag(); - } - } - } - - /// - /// Trims any whitespace characters from the start of the - /// - /// to be rendered. - /// - public virtual void TrimFirst() - { - ConvertWaitingStringToGlyphLine(); - if (text != null) - { - Glyph glyph; - while (text.start < text.end && (glyph = text.Get(text.start)).HasValidUnicode() - && char.IsWhiteSpace((char)(int)glyph.GetUnicode()) && !IsNewLine(text, text.start - )) - { - text.start++; - } - } - } - - /// - /// Trims any whitespace characters from the end of the - /// - /// to - /// be rendered. - /// - /// the amount of space in points which the text was trimmed by - public virtual float TrimLast() - { - float trimmedSpace = 0; - if (line.end <= 0) - { - return trimmedSpace; - } - float fontSize = (float)this.GetPropertyAsFloat(Property.FONT_SIZE); - float? characterSpacing = this.GetPropertyAsFloat(Property.CHARACTER_SPACING); - float? wordSpacing = this.GetPropertyAsFloat(Property.WORD_SPACING); - float? hScale = this.GetPropertyAsFloat(Property.HORIZONTAL_SCALING, 1f); - int firstNonSpaceCharIndex = line.end - 1; - while (firstNonSpaceCharIndex >= line.start) - { - Glyph currentGlyph = line.Get(firstNonSpaceCharIndex); - if (!currentGlyph.HasValidUnicode() || !char.IsWhiteSpace((char)(int)currentGlyph - .GetUnicode())) - { - break; - } - float currentCharWidth = GetCharWidth(currentGlyph, fontSize, hScale, characterSpacing - , wordSpacing) / TEXT_SPACE_COEFF; - float xAdvance = firstNonSpaceCharIndex > line.start ? ScaleXAdvance(line.Get(firstNonSpaceCharIndex - - 1).GetXAdvance(), fontSize, hScale) / TEXT_SPACE_COEFF : 0; - trimmedSpace += currentCharWidth - xAdvance; - occupiedArea.GetBBox().SetWidth(occupiedArea.GetBBox().GetWidth() - currentCharWidth - ); - firstNonSpaceCharIndex--; - } - line.end = firstNonSpaceCharIndex + 1; - return trimmedSpace; - } - - /// Gets the maximum offset above the base line that this Text extends to. - /// - /// the upwards vertical offset of this - /// - /// - public virtual float GetAscent() - { - return yLineOffset; - } - - /// Gets the maximum offset below the base line that this Text extends to. - /// - /// the downwards vertical offset of this - /// - /// - public virtual float GetDescent() - { - return -(occupiedArea.GetBBox().GetHeight() - yLineOffset - (float)this.GetPropertyAsFloat(Property.TEXT_RISE)); - } - - /// - /// Gets the position on the canvas of the imaginary horizontal line upon which - /// the - /// - /// 's contents will be written. - /// - /// - /// the y position of this text on the - /// - /// - public virtual float GetYLine() - { - return occupiedArea.GetBBox().GetY() + occupiedArea.GetBBox().GetHeight() +namespace iText.Layout.Renderer { + /// + /// This class represents the + /// renderer + /// object for a + /// + /// object. It will draw the glyphs of the textual content on the + /// + /// . + /// + public class TextRenderer : AbstractRenderer { + protected internal const float TEXT_SPACE_COEFF = FontProgram.UNITS_NORMALIZATION; + + private const float ITALIC_ANGLE = 0.21256f; + + private const float BOLD_SIMULATION_STROKE_COEFF = 1 / 30f; + + private const float TYPO_ASCENDER_SCALE_COEFF = 1.2f; + + protected internal float yLineOffset; + + protected internal GlyphLine text; + + protected internal GlyphLine line; + + protected internal String strToBeConverted; + + protected internal bool otfFeaturesApplied = false; + + protected internal float tabAnchorCharacterPosition = -1; + + /// Creates a TextRenderer from its corresponding layout object. + /// + /// the + /// + /// which this object should manage + /// + public TextRenderer(Text textElement) + : this(textElement, textElement.GetText()) { + } + + /// + /// Creates a TextRenderer from its corresponding layout object, with a custom + /// text to replace the contents of the + /// + /// . + /// + /// + /// the + /// + /// which this object should manage + /// + /// the replacement text + public TextRenderer(Text textElement, String text) + : base(textElement) { + this.strToBeConverted = text; + } + + protected internal TextRenderer(iText.Layout.Renderer.TextRenderer other) + : base(other) { + this.text = other.text; + this.line = other.line; + this.strToBeConverted = other.strToBeConverted; + this.otfFeaturesApplied = other.otfFeaturesApplied; + this.tabAnchorCharacterPosition = other.tabAnchorCharacterPosition; + } + + public override LayoutResult Layout(LayoutContext layoutContext) { + ConvertWaitingStringToGlyphLine(); + LayoutArea area = layoutContext.GetArea(); + float[] margins = GetMargins(); + Rectangle layoutBox = ApplyMargins(area.GetBBox().Clone(), margins, false); + Border[] borders = GetBorders(); + ApplyBorderBox(layoutBox, borders, false); + occupiedArea = new LayoutArea(area.GetPageNumber(), new Rectangle(layoutBox.GetX( + ), layoutBox.GetY() + layoutBox.GetHeight(), 0, 0)); + bool anythingPlaced = false; + int currentTextPos = text.start; + float fontSize = (float)this.GetPropertyAsFloat(Property.FONT_SIZE); + float textRise = (float)this.GetPropertyAsFloat(Property.TEXT_RISE); + float? characterSpacing = this.GetPropertyAsFloat(Property.CHARACTER_SPACING); + float? wordSpacing = this.GetPropertyAsFloat(Property.WORD_SPACING); + PdfFont font = this.GetPropertyAsFont(Property.FONT); + float? hScale = this.GetProperty(Property.HORIZONTAL_SCALING, (float?)1f); + ISplitCharacters splitCharacters = this.GetProperty(Property.SPLIT_CHARACTERS); + float italicSkewAddition = true.Equals(GetPropertyAsBoolean(Property.ITALIC_SIMULATION)) ? ITALIC_ANGLE * fontSize : 0; + float boldSimulationAddition = true.Equals(GetPropertyAsBoolean(Property.BOLD_SIMULATION)) ? BOLD_SIMULATION_STROKE_COEFF * fontSize : 0; + line = new GlyphLine(text); + line.start = line.end = -1; + FontMetrics fontMetrics = font.GetFontProgram().GetFontMetrics(); + float ascender; + float descender; + if (fontMetrics.GetWinAscender() == 0 || fontMetrics.GetWinDescender() == 0 || fontMetrics + .GetTypoAscender() == fontMetrics.GetWinAscender() && fontMetrics.GetTypoDescender + () == fontMetrics.GetWinDescender()) { + ascender = fontMetrics.GetTypoAscender() * TYPO_ASCENDER_SCALE_COEFF; + descender = fontMetrics.GetTypoDescender() * TYPO_ASCENDER_SCALE_COEFF; + } else { + ascender = fontMetrics.GetWinAscender(); + descender = fontMetrics.GetWinDescender(); + } + float currentLineAscender = 0; + float currentLineDescender = 0; + float currentLineHeight = 0; + int initialLineTextPos = currentTextPos; + float currentLineWidth = 0; + int previousCharPos = -1; + char? tabAnchorCharacter = this.GetProperty(Property.TAB_ANCHOR); + TextLayoutResult result = null; + // true in situations like "\nHello World" + bool isSplitForcedByImmediateNewLine = false; + // true in situations like "Hello\nWorld" + bool isSplitForcedByNewLineAndWeNeedToIgnoreNewLineSymbol = false; + while (currentTextPos < text.end) { + if (NoPrint(text.Get(currentTextPos))) { + currentTextPos++; + continue; + } + int nonBreakablePartEnd = text.end - 1; + float nonBreakablePartFullWidth = 0; + float nonBreakablePartWidthWhichDoesNotExceedAllowedWidth = 0; + float nonBreakablePartMaxAscender = 0; + float nonBreakablePartMaxDescender = 0; + float nonBreakablePartMaxHeight = 0; + int firstCharacterWhichExceedsAllowedWidth = -1; + for (int ind = currentTextPos; ind < text.end; ind++) { + if (IsNewLine(text, ind)) { + isSplitForcedByNewLineAndWeNeedToIgnoreNewLineSymbol = true; + firstCharacterWhichExceedsAllowedWidth = ind + 1; + if (text.start == currentTextPos) { + isSplitForcedByImmediateNewLine = true; + // Notice that in that case we do not need to ignore the new line symbol ('\n') + isSplitForcedByNewLineAndWeNeedToIgnoreNewLineSymbol = false; + } + break; + } + Glyph currentGlyph = text.Get(ind); + if (NoPrint(currentGlyph)) { + continue; + } + if (tabAnchorCharacter != null && tabAnchorCharacter == text.Get(ind).GetUnicode()) { + tabAnchorCharacterPosition = currentLineWidth + nonBreakablePartFullWidth; + tabAnchorCharacter = (char?)null; + } + float glyphWidth = GetCharWidth(currentGlyph, fontSize, hScale, characterSpacing, + wordSpacing) / TEXT_SPACE_COEFF; + float xAdvance = previousCharPos != -1 ? text.Get(previousCharPos).GetXAdvance() : + 0; + if (xAdvance != 0) { + xAdvance = ScaleXAdvance(xAdvance, fontSize, hScale) / TEXT_SPACE_COEFF; + } + if ((nonBreakablePartFullWidth + glyphWidth + xAdvance + italicSkewAddition + boldSimulationAddition + ) > layoutBox.GetWidth() - currentLineWidth && firstCharacterWhichExceedsAllowedWidth + == -1) { + firstCharacterWhichExceedsAllowedWidth = ind; + } + if (firstCharacterWhichExceedsAllowedWidth == -1) { + nonBreakablePartWidthWhichDoesNotExceedAllowedWidth += glyphWidth + xAdvance; + } + nonBreakablePartFullWidth += glyphWidth + xAdvance; + nonBreakablePartMaxAscender = Math.Max(nonBreakablePartMaxAscender, ascender); + nonBreakablePartMaxDescender = Math.Min(nonBreakablePartMaxDescender, descender); + nonBreakablePartMaxHeight = (nonBreakablePartMaxAscender - nonBreakablePartMaxDescender + ) * fontSize / TEXT_SPACE_COEFF + textRise; + previousCharPos = ind; + if (nonBreakablePartFullWidth + italicSkewAddition + boldSimulationAddition > layoutBox + .GetWidth()) { + // we have extracted all the information we wanted and we do not want to continue. + // we will have to split the word anyway. + break; + } + if (splitCharacters.IsSplitCharacter(text, ind) || ind + 1 == text.end || splitCharacters + .IsSplitCharacter(text, ind + 1) && (char.IsWhiteSpace((char)text.Get(ind + + 1).GetUnicode()) || char.IsSeparator((char)text.Get(ind + 1).GetUnicode()) + )) { + nonBreakablePartEnd = ind; + break; + } + } + if (firstCharacterWhichExceedsAllowedWidth == -1) { + // can fit the whole word in a line + if (line.start == -1) { + line.start = currentTextPos; + } + line.end = Math.Max(line.end, nonBreakablePartEnd + 1); + currentLineAscender = Math.Max(currentLineAscender, nonBreakablePartMaxAscender); + currentLineDescender = Math.Min(currentLineDescender, nonBreakablePartMaxDescender + ); + currentLineHeight = Math.Max(currentLineHeight, nonBreakablePartMaxHeight); + currentTextPos = nonBreakablePartEnd + 1; + currentLineWidth += nonBreakablePartFullWidth; + anythingPlaced = true; + } else { + // check if line height exceeds the allowed height + if (Math.Max(currentLineHeight, nonBreakablePartMaxHeight) > layoutBox.GetHeight()) { + ApplyBorderBox(occupiedArea.GetBBox(), borders, true); + ApplyMargins(occupiedArea.GetBBox(), margins, true); + // Force to place what we can + if (line.start == -1) { + line.start = currentTextPos; + } + line.end = Math.Max(line.end, firstCharacterWhichExceedsAllowedWidth - 1); + + // the line does not fit because of height - full overflow + iText.Layout.Renderer.TextRenderer[] splitResult = Split(initialLineTextPos); + return new TextLayoutResult(LayoutResult.NOTHING, occupiedArea, splitResult[0], splitResult[1], this); + } else { + // cannot fit a word as a whole + bool wordSplit = false; + bool hyphenationApplied = false; + HyphenationConfig hyphenationConfig = this.GetProperty(Property.HYPHENATION); + if (hyphenationConfig != null) { + int[] wordBounds = GetWordBoundsForHyphenation(text, currentTextPos, text.end, Math + .Max(currentTextPos, firstCharacterWhichExceedsAllowedWidth - 1)); + if (wordBounds != null) { + String word = text.ToUnicodeString(wordBounds[0], wordBounds[1]); + iText.Layout.Hyphenation.Hyphenation hyph = hyphenationConfig.Hyphenate(word + ); + if (hyph != null) { + for (int i = hyph.Length() - 1; i >= 0; i--) { + String pre = hyph.GetPreHyphenText(i); + String pos = hyph.GetPostHyphenText(i); + float currentHyphenationChoicePreTextWidth = GetGlyphLineWidth(ConvertToGlyphLine + (pre + hyphenationConfig.GetHyphenSymbol()), fontSize, hScale, characterSpacing, + wordSpacing); + if (currentLineWidth + currentHyphenationChoicePreTextWidth + italicSkewAddition + + boldSimulationAddition <= layoutBox.GetWidth()) { + hyphenationApplied = true; + if (line.start == -1) { + line.start = currentTextPos; + } + line.end = Math.Max(line.end, currentTextPos + pre.Length); + GlyphLine lineCopy = line.Copy(line.start, line.end); + lineCopy.Add(font.GetGlyph(hyphenationConfig.GetHyphenSymbol())); + lineCopy.end++; + line = lineCopy; + // TODO these values are based on whole word. recalculate properly based on hyphenated part + currentLineAscender = Math.Max(currentLineAscender, nonBreakablePartMaxAscender); + currentLineDescender = Math.Min(currentLineDescender, nonBreakablePartMaxDescender + ); + currentLineHeight = Math.Max(currentLineHeight, nonBreakablePartMaxHeight); + currentLineWidth += currentHyphenationChoicePreTextWidth; + currentTextPos += pre.Length; + break; + } + } + } + } + } + if ((nonBreakablePartFullWidth > layoutBox.GetWidth() && !anythingPlaced && !hyphenationApplied + ) || (isSplitForcedByImmediateNewLine)) { + // if the word is too long for a single line we will have to split it + wordSplit = true; + if (line.start == -1) { + line.start = currentTextPos; + } + currentTextPos = firstCharacterWhichExceedsAllowedWidth; + line.end = Math.Max(line.end, firstCharacterWhichExceedsAllowedWidth); + if (nonBreakablePartFullWidth > layoutBox.GetWidth() && !anythingPlaced && !hyphenationApplied) { + currentLineAscender = Math.Max(currentLineAscender, nonBreakablePartMaxAscender); + currentLineDescender = Math.Min(currentLineDescender, nonBreakablePartMaxDescender + ); + currentLineHeight = Math.Max(currentLineHeight, nonBreakablePartMaxHeight); + currentLineWidth += nonBreakablePartWidthWhichDoesNotExceedAllowedWidth; + } else { + // process empty line (e.g. '\n') + currentLineAscender = ascender; + currentLineDescender = descender; + currentLineHeight = (currentLineAscender - currentLineDescender) * fontSize / TEXT_SPACE_COEFF + + textRise; + currentLineWidth += GetCharWidth(line.Get(0), fontSize, hScale, characterSpacing, + wordSpacing) / TEXT_SPACE_COEFF; + } + } + if (line.end <= line.start) { + return new TextLayoutResult(LayoutResult.NOTHING, + occupiedArea, null, this, this); + } else { + result = new TextLayoutResult(LayoutResult.PARTIAL, occupiedArea, null, null).SetWordHasBeenSplit + (wordSplit); + } + break; + } + } + } + // indicates whether the placing is forced while the layout result is LayoutResult.NOTHING + bool isPlacingForcedWhileNothing = false; + if (currentLineHeight > layoutBox.GetHeight()) { + if (!true.Equals(GetPropertyAsBoolean(Property.FORCED_PLACEMENT))) { + ApplyBorderBox(occupiedArea.GetBBox(), borders, true); + ApplyMargins(occupiedArea.GetBBox(), margins, true); + return new TextLayoutResult(LayoutResult.NOTHING, occupiedArea, null, this, this); + } else { + isPlacingForcedWhileNothing = true; + } + } + + yLineOffset = currentLineAscender * fontSize / TEXT_SPACE_COEFF; + occupiedArea.GetBBox().MoveDown(currentLineHeight); + occupiedArea.GetBBox().SetHeight(occupiedArea.GetBBox().GetHeight() + currentLineHeight + ); + occupiedArea.GetBBox().SetWidth(Math.Max(occupiedArea.GetBBox().GetWidth(), currentLineWidth + )); + layoutBox.SetHeight(area.GetBBox().GetHeight() - currentLineHeight); + occupiedArea.GetBBox().SetWidth(occupiedArea.GetBBox().GetWidth() + italicSkewAddition + + boldSimulationAddition); + ApplyBorderBox(occupiedArea.GetBBox(), borders, true); + ApplyMargins(occupiedArea.GetBBox(), margins, true); + if (result != null) { + iText.Layout.Renderer.TextRenderer[] split; + if (isSplitForcedByNewLineAndWeNeedToIgnoreNewLineSymbol) { + // ignore '\n' + split = SplitIgnoreFirstNewLine(currentTextPos); + } else { + split = Split(currentTextPos); + } + // if (split[1].length() > 0 && split[1].charAt(0) != null && split[1].charAt(0) == '\n') { + if (isSplitForcedByNewLineAndWeNeedToIgnoreNewLineSymbol) { + result.SetSplitForcedByNewline(true); + } + result.SetSplitRenderer(split[0]); + // no sense to process empty renderer + if (split[1].text.start != split[1].text.end) { + result.SetOverflowRenderer(split[1]); + } + } else { + result = new TextLayoutResult(LayoutResult.FULL, occupiedArea, null, null, + isPlacingForcedWhileNothing ? this : null); + } + return result; + } + + public virtual void ApplyOtf() { + ConvertWaitingStringToGlyphLine(); + UnicodeScript? script = this.GetProperty(Property.FONT_SCRIPT); + if (!otfFeaturesApplied) { + if (script == null && TypographyUtils.IsTypographyModuleInitialized()) { + // Try to autodetect complex script. + ICollection supportedScripts = TypographyUtils.GetSupportedScripts + (); + IDictionary scriptFrequency = new Dictionary(); + for (int i = text.start; i < text.end; i++) { + int unicode = text.Get(i).GetUnicode(); + UnicodeScript? glyphScript = unicode > -1 ? iText.IO.Util.UnicodeScriptUtil.Of + (unicode) : (UnicodeScript?)null; + if (glyphScript != null) { + if (scriptFrequency.ContainsKey((UnicodeScript)glyphScript)) { + scriptFrequency[(UnicodeScript)glyphScript] = scriptFrequency.Get((UnicodeScript)glyphScript) + 1; + } else { + scriptFrequency[(UnicodeScript)glyphScript] = 1; + } + } + } + int? max = 0; + UnicodeScript? selectScript = null; + foreach (KeyValuePair entry in scriptFrequency) { + UnicodeScript? entryScript = entry.Key; + if (entry.Value > max && !UnicodeScript.COMMON.Equals(entryScript) && !UnicodeScript.UNKNOWN.Equals(entryScript) + && !UnicodeScript.INHERITED.Equals(entryScript)) { + + max = entry.Value; + selectScript = entryScript; + } + } + if (selectScript == UnicodeScript.ARABIC || selectScript == UnicodeScript.HEBREW + && parent is LineRenderer) { + SetProperty(Property.BASE_DIRECTION, BaseDirection.DEFAULT_BIDI + ); + } + if (selectScript != null && supportedScripts != null && supportedScripts.Contains + ((UnicodeScript)selectScript)) { + script = selectScript; + } + } + PdfFont font = GetPropertyAsFont(Property.FONT); + if (IsOtfFont(font) && script != null) { + TypographyUtils.ApplyOtfScript(font.GetFontProgram(), text, script); + } + FontKerning fontKerning = (FontKerning)this.GetProperty(Property.FONT_KERNING, FontKerning.NO); + if (fontKerning == FontKerning.YES) { + TypographyUtils.ApplyKerning(font.GetFontProgram(), text); + } + otfFeaturesApplied = true; + } + } + + public override void Draw(DrawContext drawContext) { + base.Draw(drawContext); + PdfDocument document = drawContext.GetDocument(); + bool isTagged = drawContext.IsTaggingEnabled() && GetModelElement() is IAccessibleElement; + bool isArtifact = false; + TagTreePointer tagPointer = null; + IAccessibleElement accessibleElement = null; + if (isTagged) { + accessibleElement = (IAccessibleElement)GetModelElement(); + PdfName role = accessibleElement.GetRole(); + if (role != null && !PdfName.Artifact.Equals(role)) { + tagPointer = document.GetTagStructureContext().GetAutoTaggingPointer(); + if (!tagPointer.IsElementConnectedToTag(accessibleElement)) { + AccessibleAttributesApplier.ApplyLayoutAttributes(accessibleElement.GetRole(), this + , document); + } + tagPointer.AddTag(accessibleElement, true); + } else { + isTagged = false; + if (PdfName.Artifact.Equals(role)) { + isArtifact = true; + } + } + } + + ApplyBorderBox(occupiedArea.GetBBox(), false); + + bool isRelativePosition = IsRelativePosition(); + if (isRelativePosition) { + ApplyAbsolutePositioningTranslation(false); + } + float leftBBoxX = occupiedArea.GetBBox().GetX(); + if (line.end > line.start) { + PdfFont font = GetPropertyAsFont(Property.FONT); + float fontSize = (float)this.GetPropertyAsFloat(Property.FONT_SIZE); + Color fontColor = GetPropertyAsColor(Property.FONT_COLOR); + int? textRenderingMode = this.GetProperty(Property.TEXT_RENDERING_MODE); + float? textRise = this.GetPropertyAsFloat(Property.TEXT_RISE); + float? characterSpacing = this.GetPropertyAsFloat(Property.CHARACTER_SPACING); + float? wordSpacing = this.GetPropertyAsFloat(Property.WORD_SPACING); + float? horizontalScaling = this.GetProperty(Property.HORIZONTAL_SCALING); + float?[] skew = this.GetProperty(Property.SKEW); + bool italicSimulation = true.Equals(GetPropertyAsBoolean(Property.ITALIC_SIMULATION)); + bool boldSimulation = true.Equals(GetPropertyAsBoolean(Property.BOLD_SIMULATION)); + float? strokeWidth = null; + if (boldSimulation) { + textRenderingMode = PdfCanvasConstants.TextRenderingMode.FILL_STROKE; + strokeWidth = fontSize / 30; + } + PdfCanvas canvas = drawContext.GetCanvas(); + if (isTagged) { + canvas.OpenTag(tagPointer.GetTagReference()); + } else { + if (isArtifact) { + canvas.OpenTag(new CanvasArtifact()); + } + } + canvas.SaveState().BeginText().SetFontAndSize(font, fontSize); + if (skew != null && skew.Length == 2) { + canvas.SetTextMatrix(1, (float)skew[0], (float)skew[1], 1, leftBBoxX, GetYLine()); + } else { + if (italicSimulation) { + canvas.SetTextMatrix(1, 0, ITALIC_ANGLE, 1, leftBBoxX, GetYLine()); + } else { + canvas.MoveText(leftBBoxX, GetYLine()); + } + } + if (textRenderingMode != PdfCanvasConstants.TextRenderingMode.FILL) { + canvas.SetTextRenderingMode((int)textRenderingMode); + } + if (textRenderingMode == PdfCanvasConstants.TextRenderingMode.STROKE || textRenderingMode + == PdfCanvasConstants.TextRenderingMode.FILL_STROKE) { + if (strokeWidth == null) { + strokeWidth = this.GetPropertyAsFloat(Property.STROKE_WIDTH); + } + if (strokeWidth != null && strokeWidth != 1f) { + canvas.SetLineWidth((float)strokeWidth); + } + Color strokeColor = GetPropertyAsColor(Property.STROKE_COLOR); + if (strokeColor == null) { + strokeColor = fontColor; + } + if (strokeColor != null) { + canvas.SetStrokeColor(strokeColor); + } + } + if (fontColor != null) { + canvas.SetFillColor(fontColor); + } + if (textRise != null && textRise != 0) { + canvas.SetTextRise((float)textRise); + } + if (characterSpacing != null && characterSpacing != 0) { + canvas.SetCharacterSpacing((float)characterSpacing); + } + if (wordSpacing != null && wordSpacing != 0) { + canvas.SetWordSpacing((float)wordSpacing); + } + if (horizontalScaling != null && horizontalScaling != 1) { + canvas.SetHorizontalScaling((float)horizontalScaling * 100); + } + GlyphLine.IGlyphLineFilter filter = new _IGlyphLineFilter_546(); + + bool appearanceStreamLayout = GetPropertyAsBoolean(Property.APPEARANCE_STREAM_LAYOUT) == true; + + if (HasOwnProperty(Property.REVERSED)) { + //We should mark a RTL written text + IDictionary outputs = GetOutputChunks(); + foreach (KeyValuePair output in outputs) { + GlyphLine o = output.Key.Filter(filter); + bool writeReversedChars = !appearanceStreamLayout && (bool)output.Value; + if (writeReversedChars) { + canvas.OpenTag(new CanvasTag(PdfName.ReversedChars)); + } + if (appearanceStreamLayout) { + o.SetActualText(o.start, o.end, null); + } + canvas.ShowText(o); + if (writeReversedChars) { + canvas.CloseTag(); + } + } + } else { + if (appearanceStreamLayout) { + line.SetActualText(line.start, line.end, null); + } + canvas.ShowText(line.Filter(filter)); + } + canvas.EndText().RestoreState(); + if (isTagged || isArtifact) { + canvas.CloseTag(); + } + Object underlines = this.GetProperty(Property.UNDERLINE); + if (underlines is IList) { + foreach (Object underline in (IList)underlines) { + if (underline is Underline) { + DrawSingleUnderline((Underline)underline, fontColor, canvas, fontSize, italicSimulation + ? ITALIC_ANGLE : 0); + } + } + } else { + if (underlines is Underline) { + DrawSingleUnderline((Underline)underlines, fontColor, canvas, fontSize, italicSimulation + ? ITALIC_ANGLE : 0); + } + } + } + if (isRelativePosition) { + ApplyAbsolutePositioningTranslation(false); + } + + ApplyBorderBox(occupiedArea.GetBBox(), true); + + if (isTagged) { + tagPointer.MoveToParent(); + if (isLastRendererForModelElement) { + tagPointer.RemoveElementConnectionToTag(accessibleElement); + } + } + } + + private sealed class _IGlyphLineFilter_546 : GlyphLine.IGlyphLineFilter { + public _IGlyphLineFilter_546() { + } + + public bool Accept(Glyph glyph) { + return !iText.Layout.Renderer.TextRenderer.NoPrint(glyph); + } + } + + public override void DrawBackground(DrawContext drawContext) { + Background background = this.GetProperty(Property.BACKGROUND); + float? textRise = this.GetPropertyAsFloat(Property.TEXT_RISE); + float bottomBBoxY = occupiedArea.GetBBox().GetY(); + float leftBBoxX = occupiedArea.GetBBox().GetX(); + if (background != null) { + bool isTagged = drawContext.IsTaggingEnabled() && GetModelElement() is IAccessibleElement; + PdfCanvas canvas = drawContext.GetCanvas(); + if (isTagged) { + canvas.OpenTag(new CanvasArtifact()); + } + canvas.SaveState().SetFillColor(background.GetColor()); + canvas.Rectangle(leftBBoxX - background.GetExtraLeft(), bottomBBoxY + (float)textRise + - background.GetExtraBottom(), occupiedArea.GetBBox().GetWidth() + background.GetExtraLeft + () + background.GetExtraRight(), occupiedArea.GetBBox().GetHeight() - (float)textRise + + background.GetExtraTop() + background.GetExtraBottom()); + canvas.Fill().RestoreState(); + if (isTagged) { + canvas.CloseTag(); + } + } + } + + /// + /// Trims any whitespace characters from the start of the + /// + /// to be rendered. + /// + public virtual void TrimFirst() { + ConvertWaitingStringToGlyphLine(); + if (text != null) { + Glyph glyph; + while (text.start < text.end && (glyph = text.Get(text.start)).HasValidUnicode() + && char.IsWhiteSpace((char)glyph.GetUnicode()) && !IsNewLine(text, text.start + )) { + text.start++; + } + } + } + + /// + /// Trims any whitespace characters from the end of the + /// + /// to + /// be rendered. + /// + /// the amount of space in points which the text was trimmed by + public virtual float TrimLast() { + float trimmedSpace = 0; + if (line.end <= 0) { + return trimmedSpace; + } + float fontSize = (float)this.GetPropertyAsFloat(Property.FONT_SIZE); + float? characterSpacing = this.GetPropertyAsFloat(Property.CHARACTER_SPACING); + float? wordSpacing = this.GetPropertyAsFloat(Property.WORD_SPACING); + float? hScale = this.GetPropertyAsFloat(Property.HORIZONTAL_SCALING, 1f); + int firstNonSpaceCharIndex = line.end - 1; + while (firstNonSpaceCharIndex >= line.start) { + Glyph currentGlyph = line.Get(firstNonSpaceCharIndex); + if (!currentGlyph.HasValidUnicode() || !char.IsWhiteSpace((char)currentGlyph + .GetUnicode())) { + break; + } + float currentCharWidth = GetCharWidth(currentGlyph, fontSize, hScale, characterSpacing + , wordSpacing) / TEXT_SPACE_COEFF; + float xAdvance = firstNonSpaceCharIndex > line.start ? ScaleXAdvance(line.Get(firstNonSpaceCharIndex + - 1).GetXAdvance(), fontSize, hScale) / TEXT_SPACE_COEFF : 0; + trimmedSpace += currentCharWidth - xAdvance; + occupiedArea.GetBBox().SetWidth(occupiedArea.GetBBox().GetWidth() - currentCharWidth + ); + firstNonSpaceCharIndex--; + } + line.end = firstNonSpaceCharIndex + 1; + return trimmedSpace; + } + + /// Gets the maximum offset above the base line that this Text extends to. + /// + /// the upwards vertical offset of this + /// + /// + public virtual float GetAscent() { + return yLineOffset; + } + + /// Gets the maximum offset below the base line that this Text extends to. + /// + /// the downwards vertical offset of this + /// + /// + public virtual float GetDescent() { + return -(occupiedArea.GetBBox().GetHeight() - yLineOffset - (float)this.GetPropertyAsFloat(Property.TEXT_RISE)); + } + + /// + /// Gets the position on the canvas of the imaginary horizontal line upon which + /// the + /// + /// 's contents will be written. + /// + /// + /// the y position of this text on the + /// + /// + public virtual float GetYLine() { + return occupiedArea.GetBBox().GetY() + occupiedArea.GetBBox().GetHeight() - yLineOffset - (float)this.GetPropertyAsFloat(Property.TEXT_RISE); - } - - /// Moves the vertical position to the parameter's value. - /// the new vertical position of the Text - public virtual void MoveYLineTo(float y) - { - float curYLine = GetYLine(); - float delta = y - curYLine; - occupiedArea.GetBBox().SetY(occupiedArea.GetBBox().GetY() + delta); - } - - /// - /// Manually sets the contents of the Text's representation on the canvas, - /// regardless of the Text's own contents. - /// - /// the replacement text - public virtual void SetText(String text) - { - GlyphLine glyphLine = ConvertToGlyphLine(text); - SetText(glyphLine, glyphLine.start, glyphLine.end); - } - - /// - /// Manually sets a GlyphLine to be rendered with a specific start and end - /// point. - /// - /// - /// a - /// - /// - /// the leftmost end of the GlyphLine - /// the rightmost end of the GlyphLine - public virtual void SetText(GlyphLine text, int leftPos, int rightPos) - { - this.text = new GlyphLine(text); - this.text.start = leftPos; - this.text.end = rightPos; - this.otfFeaturesApplied = false; - } - - public virtual GlyphLine GetText() - { - ConvertWaitingStringToGlyphLine(); - return text; - } - - /// The length of the whole text assigned to this renderer. - /// the text length - public virtual int Length() - { - return text == null ? 0 : text.end - text.start; - } - - public override String ToString() - { - return line != null ? line.ToUnicodeString(line.start, line.end) : strToBeConverted; - } - - /// Gets char code at given position for the text belonging to this renderer. - /// - /// the position in range [0; length()) - /// Unicode char code - public virtual int CharAt(int pos) - { - return text.Get(pos + text.start).GetUnicode(); - } - - public virtual float GetTabAnchorCharacterPosition() - { - return tabAnchorCharacterPosition; - } - - public override IRenderer GetNextRenderer() - { - return new iText.Layout.Renderer.TextRenderer((Text)modelElement, null); - } - - private bool IsNewLine(GlyphLine text, int ind) - { - return text.Get(ind).HasValidUnicode() && text.Get(ind).GetUnicode() == '\n'; - } - - private GlyphLine ConvertToGlyphLine(String text) - { - PdfFont font = GetPropertyAsFont(Property.FONT); + } + + /// Moves the vertical position to the parameter's value. + /// the new vertical position of the Text + public virtual void MoveYLineTo(float y) { + float curYLine = GetYLine(); + float delta = y - curYLine; + occupiedArea.GetBBox().SetY(occupiedArea.GetBBox().GetY() + delta); + } + + /// + /// Manually sets the contents of the Text's representation on the canvas, + /// regardless of the Text's own contents. + /// + /// the replacement text + public virtual void SetText(String text) { + GlyphLine glyphLine = ConvertToGlyphLine(text); + SetText(glyphLine, glyphLine.start, glyphLine.end); + } + + /// + /// Manually sets a GlyphLine to be rendered with a specific start and end + /// point. + /// + /// + /// a + /// + /// + /// the leftmost end of the GlyphLine + /// the rightmost end of the GlyphLine + public virtual void SetText(GlyphLine text, int leftPos, int rightPos) { + this.text = new GlyphLine(text); + this.text.start = leftPos; + this.text.end = rightPos; + this.otfFeaturesApplied = false; + } + + public virtual GlyphLine GetText() { + ConvertWaitingStringToGlyphLine(); + return text; + } + + /// The length of the whole text assigned to this renderer. + /// the text length + public virtual int Length() { + return text == null ? 0 : text.end - text.start; + } + + public override String ToString() { + return line != null ? line.ToUnicodeString(line.start, line.end) : strToBeConverted; + } + + /// Gets char code at given position for the text belonging to this renderer. + /// + /// the position in range [0; length()) + /// Unicode char code + public virtual int CharAt(int pos) { + return text.Get(pos + text.start).GetUnicode(); + } + + public virtual float GetTabAnchorCharacterPosition() { + return tabAnchorCharacterPosition; + } + + public override IRenderer GetNextRenderer() { + return new iText.Layout.Renderer.TextRenderer((Text)modelElement, null); + } + + protected internal static bool IsNewLine(GlyphLine text, int ind) { + int unicode = text.Get(ind).GetUnicode(); + return unicode == '\n' || unicode == '\r'; + } + + private TextRenderer[] SplitIgnoreFirstNewLine(int currentTextPos) { + if (text.Get(currentTextPos).HasValidUnicode() && text.Get(currentTextPos).GetUnicode() == '\r') { + int next = currentTextPos + 1 < text.end ? text.Get(currentTextPos + 1).GetUnicode() : -1; + if (next == '\n') { + return Split(currentTextPos + 2); + } else { + return Split(currentTextPos + 1); + } + } else { + return Split(currentTextPos + 1); + } + } + + private GlyphLine ConvertToGlyphLine(String text) { + PdfFont font = GetPropertyAsFont(Property.FONT); return font.CreateGlyphLine(text); - } - - private bool IsOtfFont(PdfFont font) - { - return font is PdfType0Font && font.GetFontProgram() is TrueTypeFont; - } - - protected internal override float? GetFirstYLineRecursively() - { - return GetYLine(); - } - - /// - /// Returns the length of the - /// line - /// which is the result of the layout call. - /// - protected internal virtual int LineLength() - { - return line.end > 0 ? line.end - line.start : 0; - } - - protected internal virtual int BaseCharactersCount() - { - int count = 0; - for (int i = line.start; i < line.end; i++) - { - Glyph glyph = line.Get(i); - if (!glyph.HasPlacement()) - { - count++; - } - } - return count; - } - - protected internal virtual int GetNumberOfSpaces() - { - if (line.end <= 0) - { - return 0; - } - int spaces = 0; - for (int i = line.start; i < line.end; i++) - { - Glyph currentGlyph = line.Get(i); - if (currentGlyph.HasValidUnicode() && currentGlyph.GetUnicode() == ' ') - { - spaces++; - } - } - return spaces; - } - - protected internal virtual iText.Layout.Renderer.TextRenderer CreateSplitRenderer - () - { - return (iText.Layout.Renderer.TextRenderer)GetNextRenderer(); - } - - protected internal virtual iText.Layout.Renderer.TextRenderer CreateOverflowRenderer - () - { - return (iText.Layout.Renderer.TextRenderer)GetNextRenderer(); - } - - protected internal virtual iText.Layout.Renderer.TextRenderer[] Split(int initialOverflowTextPos - ) - { - iText.Layout.Renderer.TextRenderer splitRenderer = CreateSplitRenderer(); - splitRenderer.SetText(text, text.start, initialOverflowTextPos); - splitRenderer.line = line; - splitRenderer.occupiedArea = occupiedArea.Clone(); - splitRenderer.parent = parent; - splitRenderer.yLineOffset = yLineOffset; - splitRenderer.otfFeaturesApplied = otfFeaturesApplied; - splitRenderer.isLastRendererForModelElement = false; - splitRenderer.AddAllProperties(GetOwnProperties()); - iText.Layout.Renderer.TextRenderer overflowRenderer = CreateOverflowRenderer - (); - overflowRenderer.SetText(text, initialOverflowTextPos, text.end); - overflowRenderer.otfFeaturesApplied = otfFeaturesApplied; - overflowRenderer.parent = parent; - overflowRenderer.AddAllProperties(GetOwnProperties()); - return new iText.Layout.Renderer.TextRenderer[] { splitRenderer, overflowRenderer - }; - } - - protected internal virtual void DrawSingleUnderline(Underline underline, Color fontStrokeColor, + } + + private bool IsOtfFont(PdfFont font) { + return font is PdfType0Font && font.GetFontProgram() is TrueTypeFont; + } + + protected internal override float? GetFirstYLineRecursively() { + return GetYLine(); + } + + /// + /// Returns the length of the which is the result of the layout call. + /// + /// the length of the line + protected internal virtual int LineLength() { + return line.end > 0 ? line.end - line.start : 0; + } + + protected internal virtual int BaseCharactersCount() { + int count = 0; + for (int i = line.start; i < line.end; i++) { + Glyph glyph = line.Get(i); + if (!glyph.HasPlacement()) { + count++; + } + } + return count; + } + + protected internal virtual int GetNumberOfSpaces() { + if (line.end <= 0) { + return 0; + } + int spaces = 0; + for (int i = line.start; i < line.end; i++) { + Glyph currentGlyph = line.Get(i); + if (currentGlyph.HasValidUnicode() && currentGlyph.GetUnicode() == ' ') { + spaces++; + } + } + return spaces; + } + + protected internal virtual iText.Layout.Renderer.TextRenderer CreateSplitRenderer + () { + return (iText.Layout.Renderer.TextRenderer)GetNextRenderer(); + } + + protected internal virtual iText.Layout.Renderer.TextRenderer CreateOverflowRenderer + () { + return (iText.Layout.Renderer.TextRenderer)GetNextRenderer(); + } + + protected internal virtual iText.Layout.Renderer.TextRenderer[] Split(int initialOverflowTextPos + ) { + iText.Layout.Renderer.TextRenderer splitRenderer = CreateSplitRenderer(); + splitRenderer.SetText(text, text.start, initialOverflowTextPos); + splitRenderer.line = line; + splitRenderer.occupiedArea = occupiedArea.Clone(); + splitRenderer.parent = parent; + splitRenderer.yLineOffset = yLineOffset; + splitRenderer.otfFeaturesApplied = otfFeaturesApplied; + splitRenderer.isLastRendererForModelElement = false; + splitRenderer.AddAllProperties(GetOwnProperties()); + iText.Layout.Renderer.TextRenderer overflowRenderer = CreateOverflowRenderer + (); + overflowRenderer.SetText(text, initialOverflowTextPos, text.end); + overflowRenderer.otfFeaturesApplied = otfFeaturesApplied; + overflowRenderer.parent = parent; + overflowRenderer.AddAllProperties(GetOwnProperties()); + return new iText.Layout.Renderer.TextRenderer[] { splitRenderer, overflowRenderer + }; + } + + protected internal virtual void DrawSingleUnderline(Underline underline, Color fontStrokeColor, PdfCanvas canvas, float fontSize, float italicAngleTan) { - Color underlineColor = underline.GetColor() != null ? underline - .GetColor() : fontStrokeColor; - canvas.SaveState(); - if (underlineColor != null) - { - canvas.SetStrokeColor(underlineColor); - } + Color underlineColor = underline.GetColor() != null ? underline + .GetColor() : fontStrokeColor; + canvas.SaveState(); + if (underlineColor != null) { + canvas.SetStrokeColor(underlineColor); + } canvas.SetLineCapStyle(underline.GetLineCapStyle()); - float underlineThickness = underline.GetThickness(fontSize); - if (underlineThickness != 0) - { - canvas.SetLineWidth(underlineThickness); - float yLine = GetYLine(); - float underlineYPosition = underline.GetYPosition(fontSize) + yLine; - float italicWidthSubstraction = .5f * fontSize * italicAngleTan; - canvas.MoveTo(occupiedArea.GetBBox().GetX(), underlineYPosition).LineTo(occupiedArea - .GetBBox().GetX() + occupiedArea.GetBBox().GetWidth() - italicWidthSubstraction, - underlineYPosition).Stroke(); - } - canvas.RestoreState(); - } - - protected internal virtual float CalculateLineWidth() - { - return GetGlyphLineWidth(line, (float)this.GetPropertyAsFloat(Property.FONT_SIZE), - this.GetPropertyAsFloat(Property.HORIZONTAL_SCALING, 1f), - this.GetPropertyAsFloat(Property.CHARACTER_SPACING), + float underlineThickness = underline.GetThickness(fontSize); + if (underlineThickness != 0) { + canvas.SetLineWidth(underlineThickness); + float yLine = GetYLine(); + float underlineYPosition = underline.GetYPosition(fontSize) + yLine; + float italicWidthSubstraction = .5f * fontSize * italicAngleTan; + canvas.MoveTo(occupiedArea.GetBBox().GetX(), underlineYPosition).LineTo(occupiedArea + .GetBBox().GetX() + occupiedArea.GetBBox().GetWidth() - italicWidthSubstraction, + underlineYPosition).Stroke(); + } + canvas.RestoreState(); + } + + protected internal virtual float CalculateLineWidth() { + return GetGlyphLineWidth(line, (float)this.GetPropertyAsFloat(Property.FONT_SIZE), + this.GetPropertyAsFloat(Property.HORIZONTAL_SCALING, 1f), + this.GetPropertyAsFloat(Property.CHARACTER_SPACING), this.GetPropertyAsFloat(Property.WORD_SPACING)); - } - - /// This method return a LinkedHashMap with glyphlines as its keys. - /// - /// This method return a LinkedHashMap with glyphlines as its keys. Values are boolean flags indicating if a - /// glyphline is written in a reversed order (right to left text). - /// - private IDictionary GetOutputChunks() - { - IList reversedRange = this.GetProperty>(Property.REVERSED); - IDictionary outputs = new LinkedDictionary(); - if (reversedRange != null) - { - if (reversedRange[0][0] > 0) - { - outputs[line.Copy(0, reversedRange[0][0])] = false; - } - for (int i = 0; i < reversedRange.Count; i++) - { - int[] range = reversedRange[i]; - outputs[line.Copy(range[0], range[1] + 1)] = true; - if (i != reversedRange.Count - 1) - { - outputs[line.Copy(range[1] + 1, reversedRange[i + 1][0])] = false; - } - } - int lastIndex = reversedRange[reversedRange.Count - 1][1]; - if (lastIndex < line.Size()) - { - outputs[line.Copy(lastIndex + 1, line.Size())] = false; - } - } - else - { - outputs[line] = false; - } - return outputs; - } - - private static bool NoPrint(Glyph g) - { - if (!g.HasValidUnicode()) - { - return false; - } - int c = g.GetUnicode(); - return c >= 0x200b && c <= 0x200f || c >= 0x202a && c <= 0x202e || c == '\u00AD'; - } - - private float GetCharWidth(Glyph g, float fontSize, float? hScale, float? characterSpacing - , float? wordSpacing) - { - if (hScale == null) - { - hScale = 1f; - } - float resultWidth = g.GetWidth() * fontSize * (float)hScale; - if (characterSpacing != null) - { - resultWidth += (float)characterSpacing * (float)hScale * TEXT_SPACE_COEFF; - } - if (wordSpacing != null && g.HasValidUnicode() && g.GetUnicode() == ' ') - { - resultWidth += (float)wordSpacing * (float)hScale * TEXT_SPACE_COEFF; - } - return resultWidth; - } - - private float ScaleXAdvance(float xAdvance, float fontSize, float? hScale) - { - return xAdvance * fontSize * (float)hScale; - } - - private float GetGlyphLineWidth(GlyphLine glyphLine, float fontSize, float? hScale - , float? characterSpacing, float? wordSpacing) - { - float width = 0; - for (int i = glyphLine.start; i < glyphLine.end; i++) - { - float charWidth = GetCharWidth(glyphLine.Get(i), fontSize, hScale, characterSpacing - , wordSpacing); - width += charWidth; - float xAdvance = (i != glyphLine.start) ? ScaleXAdvance(glyphLine.Get(i - 1).GetXAdvance - (), fontSize, hScale) : 0; - width += xAdvance; - } - return width / TEXT_SPACE_COEFF; - } - - private int[] GetWordBoundsForHyphenation(GlyphLine text, int leftTextPos, int rightTextPos - , int wordMiddleCharPos) - { - while (wordMiddleCharPos >= leftTextPos && !IsGlyphPartOfWordForHyphenation(text. - Get(wordMiddleCharPos)) && !IsWhitespaceGlyph(text.Get(wordMiddleCharPos))) - { - wordMiddleCharPos--; - } - if (wordMiddleCharPos >= leftTextPos) - { - int left = wordMiddleCharPos; - while (left >= leftTextPos && IsGlyphPartOfWordForHyphenation(text.Get(left))) - { - left--; - } - int right = wordMiddleCharPos; - while (right < rightTextPos && IsGlyphPartOfWordForHyphenation(text.Get(right))) - { - right++; - } - return new int[] { left + 1, right }; - } - else - { - return null; - } - } - - private bool IsGlyphPartOfWordForHyphenation(Glyph g) - { - return g.HasValidUnicode() && (char.IsLetter((char)(int)g.GetUnicode()) || char.IsDigit - ((char)(int)g.GetUnicode()) || '\u00ad' == g.GetUnicode()); - } - - private bool IsWhitespaceGlyph(Glyph g) - { - return g.HasValidUnicode() && g.GetUnicode() == ' '; - } - - private void ConvertWaitingStringToGlyphLine() - { - if (strToBeConverted != null) - { - GlyphLine glyphLine = ConvertToGlyphLine(strToBeConverted); - SetText(glyphLine, glyphLine.start, glyphLine.end); - strToBeConverted = null; - } - } - } + } + + /// This method return a LinkedHashMap with glyphlines as its keys. + /// + /// This method return a LinkedHashMap with glyphlines as its keys. Values are boolean flags indicating if a + /// glyphline is written in a reversed order (right to left text). + /// + private IDictionary GetOutputChunks() { + IList reversedRange = this.GetProperty>(Property.REVERSED); + IDictionary outputs = new LinkedDictionary(); + if (reversedRange != null) { + if (reversedRange[0][0] > 0) { + outputs[line.Copy(0, reversedRange[0][0])] = false; + } + for (int i = 0; i < reversedRange.Count; i++) { + int[] range = reversedRange[i]; + outputs[line.Copy(range[0], range[1] + 1)] = true; + if (i != reversedRange.Count - 1) { + outputs[line.Copy(range[1] + 1, reversedRange[i + 1][0])] = false; + } + } + int lastIndex = reversedRange[reversedRange.Count - 1][1]; + if (lastIndex < line.Size()) { + outputs[line.Copy(lastIndex + 1, line.Size())] = false; + } + } else { + outputs[line] = false; + } + return outputs; + } + + private static bool NoPrint(Glyph g) { + if (!g.HasValidUnicode()) { + return false; + } + int c = g.GetUnicode(); + return c >= 0x200b && c <= 0x200f || c >= 0x202a && c <= 0x202e || c == '\u00AD'; + } + + private float GetCharWidth(Glyph g, float fontSize, float? hScale, float? characterSpacing + , float? wordSpacing) { + if (hScale == null) { + hScale = 1f; + } + float resultWidth = g.GetWidth() * fontSize * (float)hScale; + if (characterSpacing != null) { + resultWidth += (float)characterSpacing * (float)hScale * TEXT_SPACE_COEFF; + } + if (wordSpacing != null && g.HasValidUnicode() && g.GetUnicode() == ' ') { + resultWidth += (float)wordSpacing * (float)hScale * TEXT_SPACE_COEFF; + } + return resultWidth; + } + + private float ScaleXAdvance(float xAdvance, float fontSize, float? hScale) { + return xAdvance * fontSize * (float)hScale; + } + + private float GetGlyphLineWidth(GlyphLine glyphLine, float fontSize, float? hScale + , float? characterSpacing, float? wordSpacing) { + float width = 0; + for (int i = glyphLine.start; i < glyphLine.end; i++) { + float charWidth = GetCharWidth(glyphLine.Get(i), fontSize, hScale, characterSpacing + , wordSpacing); + width += charWidth; + float xAdvance = (i != glyphLine.start) ? ScaleXAdvance(glyphLine.Get(i - 1).GetXAdvance + (), fontSize, hScale) : 0; + width += xAdvance; + } + return width / TEXT_SPACE_COEFF; + } + + private int[] GetWordBoundsForHyphenation(GlyphLine text, int leftTextPos, int rightTextPos + , int wordMiddleCharPos) { + while (wordMiddleCharPos >= leftTextPos && !IsGlyphPartOfWordForHyphenation(text. + Get(wordMiddleCharPos)) && !IsWhitespaceGlyph(text.Get(wordMiddleCharPos))) { + wordMiddleCharPos--; + } + if (wordMiddleCharPos >= leftTextPos) { + int left = wordMiddleCharPos; + while (left >= leftTextPos && IsGlyphPartOfWordForHyphenation(text.Get(left))) { + left--; + } + int right = wordMiddleCharPos; + while (right < rightTextPos && IsGlyphPartOfWordForHyphenation(text.Get(right))) { + right++; + } + return new int[] { left + 1, right }; + } else { + return null; + } + } + + private bool IsGlyphPartOfWordForHyphenation(Glyph g) { + return g.HasValidUnicode() && (char.IsLetter((char)g.GetUnicode()) || char.IsDigit + ((char)g.GetUnicode()) || '\u00ad' == g.GetUnicode()); + } + + private bool IsWhitespaceGlyph(Glyph g) { + return g.HasValidUnicode() && g.GetUnicode() == ' '; + } + + private void ConvertWaitingStringToGlyphLine() { + if (strToBeConverted != null) { + GlyphLine glyphLine = ConvertToGlyphLine(strToBeConverted); + SetText(glyphLine, glyphLine.start, glyphLine.end); + strToBeConverted = null; + } + } + } } diff --git a/itext/itext.layout/itext/layout/renderer/TypographyUtils.cs b/itext/itext.layout/itext/layout/renderer/TypographyUtils.cs index 1fd9400574..db63535c92 100644 --- a/itext/itext.layout/itext/layout/renderer/TypographyUtils.cs +++ b/itext/itext.layout/itext/layout/renderer/TypographyUtils.cs @@ -55,16 +55,49 @@ namespace iText.Layout.Renderer { internal class TypographyUtils { private static readonly ILogger logger = LoggerFactory.GetLogger(typeof(TypographyUtils)); - private const String TYPOGRAPHY_PACKAGE = "com.itextpdf.typography."; + private const String TYPOGRAPHY_PACKAGE = "iText.Typography."; + + private const String SHAPER = "Shaping.Shaper,iText.Typography"; + + private const String BIDI_CHARACTER_MAP = "Bidi.BidiCharacterMap,iText.Typography"; + + private const String BIDI_BRACKET_MAP = "Bidi.BidiBracketMap,iText.Typography"; + + private const String BIDI_ALGORITHM = "Bidi.BidiAlgorithm,iText.Typography"; + + private const String APPLY_OTF_SCRIPT = "ApplyOtfScript"; + + private const String APPLY_KERNING = "ApplyKerning"; + + private const String GET_SUPPORTED_SCRIPTS = "GetSupportedScripts"; + + private const String GET_CHARACTER_TYPES = "GetCharacterTypes"; + + private const String GET_BRACKET_TYPES = "GetBracketTypes"; + + private const String GET_BRACKET_VALUES = "GetBracketValues"; + + private const String GET_PAIRED_BRACKET = "GetPairedBracket"; + + private const String GET_LEVELS = "GetLevels"; + + private const String COMPUTE_REORDERING = "ComputeReordering"; + + private const String INVERSE_REORDERING = "InverseReordering"; private static readonly ICollection SUPPORTED_SCRIPTS; private static readonly bool TYPOGRAPHY_MODULE_INITIALIZED; + private static IDictionary cachedClasses = new Dictionary(); + + private static IDictionary cachedMethods = new Dictionary + (); + static TypographyUtils() { bool moduleFound = false; try { - Type type = System.Type.GetType("com.itextpdf.typography.shaping.Shaper"); + Type type = System.Type.GetType(TYPOGRAPHY_PACKAGE + SHAPER); if (type != null) { moduleFound = true; } @@ -86,24 +119,24 @@ internal static void ApplyOtfScript(FontProgram fontProgram, GlyphLine text, Uni ); } else { - CallMethod(TYPOGRAPHY_PACKAGE + "shaping.Shaper", "applyOtfScript", new Type[] { typeof(TrueTypeFont), typeof( - GlyphLine), typeof(UnicodeScript?) }, fontProgram, text, script); + CallMethod(TYPOGRAPHY_PACKAGE + SHAPER, APPLY_OTF_SCRIPT, new Type[] { typeof(TrueTypeFont), typeof(GlyphLine + ), typeof(UnicodeScript?) }, fontProgram, text, script); } } - //Shaper.applyOtfScript((TrueTypeFont)font.getFontProgram(), text, script); + // Shaper.applyOtfScript((TrueTypeFont)fontProgram, text, script); internal static void ApplyKerning(FontProgram fontProgram, GlyphLine text) { if (!TYPOGRAPHY_MODULE_INITIALIZED) { logger.Warn("Cannot find advanced typography module, which was implicitly required by one of the layout properties" ); } else { - CallMethod(TYPOGRAPHY_PACKAGE + "shaping.Shaper", "applyKerning", new Type[] { typeof(FontProgram), typeof( - GlyphLine) }, fontProgram, text); + CallMethod(TYPOGRAPHY_PACKAGE + SHAPER, APPLY_KERNING, new Type[] { typeof(FontProgram), typeof(GlyphLine) + }, fontProgram, text); } } - //Shaper.applyKerning(font.getFontProgram(), text); + // Shaper.applyKerning(fontProgram, text); internal static byte[] GetBidiLevels(BaseDirection baseDirection, int[] unicodeIds) { if (!TYPOGRAPHY_MODULE_INITIALIZED) { logger.Warn("Cannot find advanced typography module, which was implicitly required by one of the layout properties" @@ -129,22 +162,22 @@ internal static byte[] GetBidiLevels(BaseDirection baseDirection, int[] unicodeI } } int len = unicodeIds.Length; - byte[] types = (byte[])CallMethod(TYPOGRAPHY_PACKAGE + "bidi.BidiCharacterMap", "getCharacterTypes", new Type - [] { typeof(int[]), typeof(int), typeof(int) }, unicodeIds, 0, len); - //byte[] types = BidiCharacterMap.getCharacterTypes(unicodeIds, 0, text.end - text.start; - byte[] pairTypes = (byte[])CallMethod(TYPOGRAPHY_PACKAGE + "bidi.BidiBracketMap", "getBracketTypes", new Type - [] { typeof(int[]), typeof(int), typeof(int) }, unicodeIds, 0, len); - //byte[] pairTypes = BidiBracketMap.getBracketTypes(unicodeIds, 0, text.end - text.start); - int[] pairValues = (int[])CallMethod(TYPOGRAPHY_PACKAGE + "bidi.BidiBracketMap", "getBracketValues", new Type - [] { typeof(int[]), typeof(int), typeof(int) }, unicodeIds, 0, len); - //int[] pairValues = BidiBracketMap.getBracketValues(unicodeIds, 0, text.end - text.start); - Object bidiReorder = CallConstructor(TYPOGRAPHY_PACKAGE + "bidi.BidiAlgorithm", new Type[] { typeof(byte[] - ), typeof(byte[]), typeof(int[]), typeof(byte) }, types, pairTypes, pairValues, direction); - //BidiAlgorithm bidiReorder = new BidiAlgorithm(types, pairTypes, pairValues, direction); - return (byte[])CallMethod(TYPOGRAPHY_PACKAGE + "bidi.BidiAlgorithm", "getLevels", bidiReorder, new Type[] - { typeof(int[]) }, new int[] { len }); - } - //levels = bidiReorder.getLevels(new int[]{text.end - text.start}); + byte[] types = (byte[])CallMethod(TYPOGRAPHY_PACKAGE + BIDI_CHARACTER_MAP, GET_CHARACTER_TYPES, new Type[] + { typeof(int[]), typeof(int), typeof(int) }, unicodeIds, 0, len); + // byte[] types = BidiCharacterMap.getCharacterTypes(unicodeIds, 0, len); + byte[] pairTypes = (byte[])CallMethod(TYPOGRAPHY_PACKAGE + BIDI_BRACKET_MAP, GET_BRACKET_TYPES, new Type[] + { typeof(int[]), typeof(int), typeof(int) }, unicodeIds, 0, len); + // byte[] pairTypes = BidiBracketMap.getBracketTypes(unicodeIds, 0, len); + int[] pairValues = (int[])CallMethod(TYPOGRAPHY_PACKAGE + BIDI_BRACKET_MAP, GET_BRACKET_VALUES, new Type[] + { typeof(int[]), typeof(int), typeof(int) }, unicodeIds, 0, len); + // int[] pairValues = BidiBracketMap.getBracketValues(unicodeIds, 0, len); + Object bidiReorder = CallConstructor(TYPOGRAPHY_PACKAGE + BIDI_ALGORITHM, new Type[] { typeof(byte[]), typeof( + byte[]), typeof(int[]), typeof(byte) }, types, pairTypes, pairValues, direction); + // BidiAlgorithm bidiReorder = new BidiAlgorithm(types, pairTypes, pairValues, direction); + return (byte[])CallMethod(TYPOGRAPHY_PACKAGE + BIDI_ALGORITHM, GET_LEVELS, bidiReorder, new Type[] { typeof( + int[]) }, new int[] { len }); + } + // return bidiReorder.getLevels(new int[]{len}); return null; } @@ -158,23 +191,39 @@ internal static int[] ReorderLine(IList line, byte[] if (levels == null) { return null; } - int[] reorder = (int[])CallMethod(TYPOGRAPHY_PACKAGE + "bidi.BidiAlgorithm", "computeReordering", new Type - [] { typeof(byte[]) }, lineLevels); - //int[] reorder = BidiAlgorithm.computeReordering(lineLevels); + int[] reorder = (int[])CallMethod(TYPOGRAPHY_PACKAGE + BIDI_ALGORITHM, COMPUTE_REORDERING, new Type[] { typeof( + byte[]) }, lineLevels); + // int[] reorder = BidiAlgorithm.computeReordering(lineLevels); + int[] inverseReorder = (int[])CallMethod(TYPOGRAPHY_PACKAGE + BIDI_ALGORITHM, INVERSE_REORDERING, new Type + [] { typeof(int[]) }, reorder); + // int[] inverseReorder = BidiAlgorithm.inverseReordering(reorder); IList reorderedLine = new List(lineLevels.Length); for (int i = 0; i < line.Count; i++) { reorderedLine.Add(line[reorder[i]]); // Mirror RTL glyphs if (levels[reorder[i]] % 2 == 1) { if (reorderedLine[i].glyph.HasValidUnicode()) { - int pairedBracket = (int)CallMethod(TYPOGRAPHY_PACKAGE + "bidi.BidiBracketMap", "getPairedBracket", new Type - [] { typeof(int) }, reorderedLine[i].glyph.GetUnicode()); - PdfFont font = reorderedLine[i].renderer.GetPropertyAsFont(Property.FONT); - //BidiBracketMap.getPairedBracket(reorderedLine.get(i).getUnicode()) - reorderedLine[i] = new LineRenderer.RendererGlyph(font.GetGlyph(pairedBracket), reorderedLine[i].renderer); + int unicode = reorderedLine[i].glyph.GetUnicode(); + int pairedBracket = (int)CallMethod(TYPOGRAPHY_PACKAGE + BIDI_BRACKET_MAP, GET_PAIRED_BRACKET, new Type[] + { typeof(int) }, unicode); + // int pairedBracket = BidiBracketMap.getPairedBracket(reorderedLine.get(i).glyph.getUnicode()); + if (pairedBracket != unicode) { + PdfFont font = reorderedLine[i].renderer.GetPropertyAsFont(Property.FONT); + reorderedLine[i] = new LineRenderer.RendererGlyph(font.GetGlyph(pairedBracket), reorderedLine[i].renderer); + } } } } + // fix anchorDelta + for (int i_1 = 0; i_1 < reorderedLine.Count; i_1++) { + Glyph glyph = reorderedLine[i_1].glyph; + if (glyph.HasPlacement()) { + int oldAnchor = reorder[i_1] + glyph.GetAnchorDelta(); + int newPos = inverseReorder[oldAnchor]; + int newAnchorDelta = newPos - i_1; + glyph.SetAnchorDelta((short)newAnchorDelta); + } + } line.Clear(); line.AddAll(reorderedLine); return reorder; @@ -193,12 +242,13 @@ internal static ICollection GetSupportedScripts() { return SUPPORTED_SCRIPTS; } else { - return (ICollection)CallMethod(TYPOGRAPHY_PACKAGE + "shaping.Shaper", "getSupportedScripts" - , new Type[] { }); + return (ICollection)CallMethod(TYPOGRAPHY_PACKAGE + SHAPER, GET_SUPPORTED_SCRIPTS, new Type + [] { }); } } } + // return (Collection) Shaper.getSupportedScripts(); internal static bool IsTypographyModuleInitialized() { return TYPOGRAPHY_MODULE_INITIALIZED; } @@ -211,7 +261,7 @@ private static Object CallMethod(String className, String methodName, Type[] par private static Object CallMethod(String className, String methodName, Object target, Type[] parameterTypes , params Object[] args) { try { - MethodInfo method = System.Type.GetType(className).GetMethod(methodName, parameterTypes); + MethodInfo method = FindMethod(className, methodName, parameterTypes); return method.Invoke(target, args); } catch (MissingMethodException) { @@ -228,7 +278,7 @@ private static Object CallMethod(String className, String methodName, Object tar private static Object CallConstructor(String className, Type[] parameterTypes, params Object[] args) { try { - ConstructorInfo constructor = System.Type.GetType(className).GetConstructor(parameterTypes); + ConstructorInfo constructor = FindConstructor(className, parameterTypes); return constructor.Invoke(args); } catch (MissingMethodException) { @@ -242,5 +292,83 @@ private static Object CallConstructor(String className, Type[] parameterTypes, p } return null; } + + /// + /// + private static MethodInfo FindMethod(String className, String methodName, Type[] parameterTypes) { + TypographyUtils.TypographyMethodSignature tm = new TypographyUtils.TypographyMethodSignature(className, parameterTypes + , methodName); + MethodInfo m = (MethodInfo)cachedMethods.Get(tm); + if (m == null) { + m = FindClass(className).GetMethod(methodName, parameterTypes); + cachedMethods[tm] = m; + } + return m; + } + + /// + /// + private static ConstructorInfo FindConstructor(String className, Type[] parameterTypes) { + TypographyUtils.TypographyMethodSignature tc = new TypographyUtils.TypographyMethodSignature(className, parameterTypes + ); + ConstructorInfo c = (ConstructorInfo)cachedMethods.Get(tc); + if (c == null) { + c = FindClass(className).GetConstructor(parameterTypes); + cachedMethods[tc] = c; + } + return c; + } + + /// + private static Type FindClass(String className) { + Type c = cachedClasses.Get(className); + if (c == null) { + c = System.Type.GetType(className); + cachedClasses[className] = c; + } + return c; + } + + private class TypographyMethodSignature { + protected internal readonly String className; + + protected internal Type[] parameterTypes; + + private readonly String methodName; + + internal TypographyMethodSignature(String className, Type[] parameterTypes) + : this(className, parameterTypes, null) { + } + + internal TypographyMethodSignature(String className, Type[] parameterTypes, String methodName) { + this.methodName = methodName; + this.className = className; + this.parameterTypes = parameterTypes; + } + + public override bool Equals(Object o) { + if (this == o) { + return true; + } + if (o == null || GetType() != o.GetType()) { + return false; + } + TypographyUtils.TypographyMethodSignature that = (TypographyUtils.TypographyMethodSignature)o; + if (!className.Equals(that.className)) { + return false; + } + if (!iText.IO.Util.JavaUtil.ArraysEquals(parameterTypes, that.parameterTypes)) { + return false; + } + return methodName != null ? methodName.Equals(that.methodName) : that.methodName == null; + } + + public override int GetHashCode() { + int result = className.GetHashCode(); + result = 31 * result + iText.IO.Util.JavaUtil.ArraysHashCode(parameterTypes); + result = 31 * result + (methodName != null ? methodName.GetHashCode() : 0); + return result; + } + } } } diff --git a/itext/itext.layout/itext/layout/splitting/DefaultSplitCharacters.cs b/itext/itext.layout/itext/layout/splitting/DefaultSplitCharacters.cs index 4292ab3546..4bed6ea405 100644 --- a/itext/itext.layout/itext/layout/splitting/DefaultSplitCharacters.cs +++ b/itext/itext.layout/itext/layout/splitting/DefaultSplitCharacters.cs @@ -54,7 +54,7 @@ public virtual bool IsSplitCharacter(GlyphLine text, int glyphPos) { if (!text.Get(glyphPos).HasValidUnicode()) { return false; } - int charCode = (int)text.Get(glyphPos).GetUnicode(); + int charCode = text.Get(glyphPos).GetUnicode(); return (charCode <= ' ' || charCode == '-' || charCode == '\u2010' || (charCode >= 0x2002 && charCode <= 0x200b ) || (charCode >= 0x2e80 && charCode < 0xd7a0) || (charCode >= 0xf900 && charCode < 0xfb00) || (charCode >= 0xfe30 && charCode < 0xfe50) || (charCode >= 0xff61 && charCode < 0xffa0)); diff --git a/itext/itext.pdfa/Properties/AssemblyInfo.cs b/itext/itext.pdfa/Properties/AssemblyInfo.cs index a8e6a4b1e9..f8363612e7 100644 --- a/itext/itext.pdfa/Properties/AssemblyInfo.cs +++ b/itext/itext.pdfa/Properties/AssemblyInfo.cs @@ -21,5 +21,5 @@ [assembly: Guid("9fc2f0b3-a8d2-46da-8724-72e00e67a8fa")] -[assembly: AssemblyVersion("7.0.0.0")] -[assembly: AssemblyFileVersion("7.0.0.0")] +[assembly: AssemblyVersion("7.0.1.0")] +[assembly: AssemblyFileVersion("7.0.1.0")] diff --git a/itext/itext.pdfa/itext/pdfa/PdfAConformanceException.cs b/itext/itext.pdfa/itext/pdfa/PdfAConformanceException.cs index db7e4f6aac..3d0b97a2e3 100644 --- a/itext/itext.pdfa/itext/pdfa/PdfAConformanceException.cs +++ b/itext/itext.pdfa/itext/pdfa/PdfAConformanceException.cs @@ -104,7 +104,7 @@ public const String AppearanceDictionaryOfWidgetSubtypeAndBtnFieldTypeShallConta public const String CatalogShallIncludeMarkInfoDictionaryWithMarkedTrueValue = "catalog.dictionary.shall.include.a.markinfo.dictionary.whose.entry.marked.shall.have.a.value.of.true"; - public const String CatalogShallContainLangEntry = "catalog.dictionary.shall.contain.lang.entry"; + public const String CatalogShallContainLangEntry = "catalog.dictionary.should.contain.lang.entry"; public const String CatalogShallContainMetadataEntry = "catalog.dictionary.shall.contain.metadata.entry"; @@ -254,6 +254,12 @@ public const String TintTransformAndAlternateSpaceOfSeparationArraysInTheColoran public const String WidgetAnnotationDictionaryOrFieldDictionaryShallNotIncludeAOrAAEntry = "widget.annotation.dictionary.or.field.dictionary.shall.not.include.a.or.aa.entry"; + public const String AllNonSymbolicTrueTypeFontShallSpecifyMacRomanEncodingOrWinAnsiEncoding = "All non-symbolic TrueType fonts shall specify MacRomanEncoding or WinAnsiEncoding as the value of the Encoding entry in the font dictionary."; + + public const String AllNonSymbolicTrueTypeFontShallSpecifyMacRomanOrWinAnsiEncodingAsTheEncodingEntry = "All non-symbolic TrueType fonts shall specify MacRomanEncoding or WinAnsiEncoding as the value of the Encoding entry in the font dictionary. This also means that Encoding entry in the font dictionary shall not be an encoding dictionary."; + + public const String AllSymbolicTrueTypeFontsShallNotSpecifyEncoding = "All symbolic TrueType fonts shall not specify an Encoding entry in the font dictionary."; + /// Creates a PdfAConformanceException. /// the error message public PdfAConformanceException(String message) diff --git a/itext/itext.pdfa/itext/pdfa/PdfADocument.cs b/itext/itext.pdfa/itext/pdfa/PdfADocument.cs index a40132c341..c24db2a6a0 100644 --- a/itext/itext.pdfa/itext/pdfa/PdfADocument.cs +++ b/itext/itext.pdfa/itext/pdfa/PdfADocument.cs @@ -53,19 +53,59 @@ source product. using iText.Pdfa.Checker; namespace iText.Pdfa { + /// + /// This class extends + /// + /// and is in charge of creating files + /// that comply with the PDF/A standard. + /// Client code is still responsible for making sure the file is actually PDF/A + /// compliant: multiple steps must be undertaken (depending on the + /// + /// ) to ensure that the PDF/A standard is followed. + /// This class will throw exceptions, mostly + /// + /// , + /// and thus refuse to output a PDF/A file if at any point the document does not + /// adhere to the PDF/A guidelines specified by the + /// + /// . + /// public class PdfADocument : PdfDocument { protected internal PdfAChecker checker; + /// Constructs a new PdfADocument for writing purposes, i.e. + /// + /// Constructs a new PdfADocument for writing purposes, i.e. from scratch. A + /// PDF/A file has a conformance level, and must have an explicit output + /// intent. + /// + /// + /// the + /// + /// object to write to + /// + /// the generation and strictness level of the PDF/A that must be followed. + /// + /// a + /// + /// public PdfADocument(PdfWriter writer, PdfAConformanceLevel conformanceLevel, PdfOutputIntent outputIntent) : base(writer) { SetChecker(conformanceLevel); AddOutputIntent(outputIntent); } + /// Opens a PDF/A document in the stamping mode. + /// PDF reader. + /// PDF writer. public PdfADocument(PdfReader reader, PdfWriter writer) : this(reader, writer, new StampingProperties()) { } + /// Open a PDF/A document in stamping mode. + /// PDF reader. + /// PDF writer. + /// properties of the stamping process public PdfADocument(PdfReader reader, PdfWriter writer, StampingProperties properties) : base(reader, writer, properties) { byte[] existingXmpMetadata = GetXmpMetadata(); @@ -195,23 +235,48 @@ public override void CheckIsoConformance(Object obj, IsoKey key, PdfResources re checker.CheckSinglePage((PdfPage)obj); break; } + + case IsoKey.TAG_STRUCTURE_ELEMENT: { + checker.CheckTagStructureElement((PdfObject)obj); + break; + } } } + /// + /// Gets the PdfAConformanceLevel set in the constructor or in the metadata + /// of the + /// + /// . + /// + /// + /// a + /// + /// public virtual PdfAConformanceLevel GetConformanceLevel() { return checker.GetConformanceLevel(); } + protected override void AddCustomMetadataExtensions(XMPMeta xmpMeta) { + if (this.IsTagged()) { + try { + XMPMeta taggedExtensionMeta = XMPMetaFactory.ParseFromString(PdfAXMPUtil.PDF_UA_EXTENSION); + XMPUtils.AppendProperties(taggedExtensionMeta, xmpMeta, true, false); + } + catch (XMPException exc) { + ILogger logger = LoggerFactory.GetLogger(typeof(iText.Pdfa.PdfADocument)); + logger.Error(LogMessageConstant.EXCEPTION_WHILE_UPDATING_XMPMETADATA, exc); + } + } + } + protected override void UpdateXmpMetadata() { try { XMPMeta xmpMeta = UpdateDefaultXmpMetadata(); xmpMeta.SetProperty(XMPConst.NS_PDFA_ID, XMPConst.PART, checker.GetConformanceLevel().GetPart()); xmpMeta.SetProperty(XMPConst.NS_PDFA_ID, XMPConst.CONFORMANCE, checker.GetConformanceLevel().GetConformance ()); - if (this.IsTagged()) { - XMPMeta taggedExtensionMeta = XMPMetaFactory.ParseFromString(PdfAXMPUtil.PDF_UA_EXTENSION); - XMPUtils.AppendProperties(taggedExtensionMeta, xmpMeta, true, false); - } + AddCustomMetadataExtensions(xmpMeta); SetXmpMetadata(xmpMeta); } catch (XMPException e) { @@ -236,10 +301,7 @@ protected override void FlushObject(PdfObject pdfObject, bool canBeInObjStm) { //TODO log unsuccessful call protected override void FlushFonts() { foreach (PdfFont pdfFont in GetDocumentFonts()) { - if (!pdfFont.IsEmbedded()) { - throw new PdfAConformanceException(PdfAConformanceException.AllFontsMustBeEmbeddedThisOneIsnt1).SetMessageParams - (pdfFont.GetFontProgram().GetFontNames().GetFontName()); - } + checker.CheckFont(pdfFont); } base.FlushFonts(); } diff --git a/itext/itext.pdfa/itext/pdfa/PdfAExtensions.cs b/itext/itext.pdfa/itext/pdfa/PdfAExtensions.cs index d502b0fccf..f325722034 100644 --- a/itext/itext.pdfa/itext/pdfa/PdfAExtensions.cs +++ b/itext/itext.pdfa/itext/pdfa/PdfAExtensions.cs @@ -45,6 +45,7 @@ source product. using System; using System.Collections.Generic; using System.IO; +using System.Text; namespace iText.Pdfa { internal static class PdfAExtensions { @@ -56,6 +57,10 @@ public static byte[] GetBytes(this String str) { return System.Text.Encoding.UTF8.GetBytes(str); } + public static byte[] GetBytes(this String str, Encoding encoding) { + return encoding.GetBytes(str); + } + public static TValue Get(this IDictionary col, TKey key) { TValue value = default(TValue); if (key != null) { @@ -69,5 +74,9 @@ public static int JRead(this Stream stream, byte[] buffer, int offset, int count int result = stream.Read(buffer, offset, count); return result == 0 ? -1 : result; } + + public static void RetainAll(this ISet set, ICollection c) { + set.IntersectWith(c); + } } } diff --git a/itext/itext.pdfa/itext/pdfa/checker/PdfA1Checker.cs b/itext/itext.pdfa/itext/pdfa/checker/PdfA1Checker.cs index 83563cb5ca..dd6c53f48c 100644 --- a/itext/itext.pdfa/itext/pdfa/checker/PdfA1Checker.cs +++ b/itext/itext.pdfa/itext/pdfa/checker/PdfA1Checker.cs @@ -43,8 +43,10 @@ source product. */ using System; using System.Collections.Generic; +using iText.IO.Font; using iText.IO.Log; using iText.Kernel.Colors; +using iText.Kernel.Font; using iText.Kernel.Pdf; using iText.Kernel.Pdf.Annot; using iText.Kernel.Pdf.Canvas; @@ -52,6 +54,14 @@ source product. using iText.Pdfa; namespace iText.Pdfa.Checker { + /// + /// PdfA1Checker defines the requirements of the PDF/A-1 standard and contains + /// method implementations from the abstract + /// + /// class. + ///

    + /// The specification implemented by this class is ISO 19005-1 + ///

    public class PdfA1Checker : PdfAChecker { protected internal static readonly ICollection forbiddenAnnotations = new HashSet(iText.IO.Util.JavaUtil.ArraysAsList (PdfName.Sound, PdfName.Movie, PdfName.FileAttachment)); @@ -70,6 +80,11 @@ public class PdfA1Checker : PdfAChecker { protected internal static readonly ICollection allowedRenderingIntents = new HashSet(iText.IO.Util.JavaUtil.ArraysAsList (PdfName.RelativeColorimetric, PdfName.AbsoluteColorimetric, PdfName.Perceptual, PdfName.Saturation)); + /// Creates a PdfA1Checker with the required conformance level + /// + /// the required conformance level, a or + /// b + /// public PdfA1Checker(PdfAConformanceLevel conformanceLevel) : base(conformanceLevel) { } @@ -209,6 +224,41 @@ public override void CheckRenderingIntent(PdfName intent) { } } + public override void CheckFont(PdfFont pdfFont) { + if (!pdfFont.IsEmbedded()) { + throw new PdfAConformanceException(PdfAConformanceException.AllFontsMustBeEmbeddedThisOneIsnt1).SetMessageParams + (pdfFont.GetFontProgram().GetFontNames().GetFontName()); + } + if (pdfFont is PdfTrueTypeFont) { + PdfTrueTypeFont trueTypeFont = (PdfTrueTypeFont)pdfFont; + bool symbolic = trueTypeFont.GetFontEncoding().IsFontSpecific(); + if (symbolic) { + CheckSymbolicTrueTypeFont(trueTypeFont); + } + else { + CheckNonSymbolicTrueTypeFont(trueTypeFont); + } + } + } + + protected internal override void CheckNonSymbolicTrueTypeFont(PdfTrueTypeFont trueTypeFont) { + String encoding = trueTypeFont.GetFontEncoding().GetBaseEncoding(); + // non-symbolic true type font will always has an encoding entry in font dictionary in itext7 + if (!PdfEncodings.WINANSI.Equals(encoding) && !encoding.Equals(PdfEncodings.MACROMAN) || trueTypeFont.GetFontEncoding + ().HasDifferences()) { + throw new PdfAConformanceException(PdfAConformanceException.AllNonSymbolicTrueTypeFontShallSpecifyMacRomanOrWinAnsiEncodingAsTheEncodingEntry + , trueTypeFont); + } + } + + protected internal override void CheckSymbolicTrueTypeFont(PdfTrueTypeFont trueTypeFont) { + if (trueTypeFont.GetFontEncoding().HasDifferences()) { + throw new PdfAConformanceException(PdfAConformanceException.AllSymbolicTrueTypeFontsShallNotSpecifyEncoding + ); + } + } + + // if symbolic font encoding doesn't have differences, itext7 won't write encoding for such font protected internal override void CheckImage(PdfStream image, PdfDictionary currentColorSpaces) { PdfColorSpace colorSpace = null; if (IsAlreadyChecked(image)) { @@ -259,6 +309,7 @@ protected internal override void CheckFormXObject(PdfStream form) { throw new PdfAConformanceException(PdfAConformanceException.AGroupObjectWithAnSKeyWithAValueOfTransparencyShallNotBeIncludedInAFormXobject ); } + CheckResources(form.GetAsDictionary(PdfName.Resources)); } protected internal override void CheckLogicalStructure(PdfDictionary catalog) { @@ -400,6 +451,7 @@ protected internal override void CheckAnnotation(PdfDictionary annotDic) { throw new PdfAConformanceException(PdfAConformanceException.AppearanceDictionaryShallContainOnlyTheNKeyWithStreamValue ); } + CheckResourcesOfAppearanceStreams(ap); } if (PdfName.Widget.Equals(subtype) && (annotDic.ContainsKey(PdfName.AA) || annotDic.ContainsKey(PdfName.A) )) { @@ -426,6 +478,7 @@ protected internal override void CheckForm(PdfDictionary form) { throw new PdfAConformanceException(PdfAConformanceException.NeedAppearancesFlagOfTheInteractiveFormDictionaryShallEitherNotBePresentedOrShallBeFalse ); } + CheckResources(form.GetAsDictionary(PdfName.DR)); PdfArray fields = form.GetAsArray(PdfName.Fields); if (fields != null) { fields = GetFormFields(fields); @@ -435,6 +488,7 @@ protected internal override void CheckForm(PdfDictionary form) { throw new PdfAConformanceException(PdfAConformanceException.WidgetAnnotationDictionaryOrFieldDictionaryShallNotIncludeAOrAAEntry ); } + CheckResources(fieldDic.GetAsDictionary(PdfName.DR)); } } } @@ -497,13 +551,10 @@ protected internal override void CheckTrailer(PdfDictionary trailer) { } } - private PdfArray GetFormFields(PdfArray array) { + protected internal virtual PdfArray GetFormFields(PdfArray array) { PdfArray fields = new PdfArray(); - // explicit iteration to resolve indirect references on get(). - // TODO DEVSIX-591 - for (int i = 0; i < array.Size(); i++) { - PdfDictionary field = array.GetAsDictionary(i); - PdfArray kids = field.GetAsArray(PdfName.Kids); + foreach (PdfObject field in array) { + PdfArray kids = ((PdfDictionary)field).GetAsArray(PdfName.Kids); fields.Add(field); if (kids != null) { fields.AddAll(GetFormFields(kids)); diff --git a/itext/itext.pdfa/itext/pdfa/checker/PdfA2Checker.cs b/itext/itext.pdfa/itext/pdfa/checker/PdfA2Checker.cs index 6f3ccec076..23772d8695 100644 --- a/itext/itext.pdfa/itext/pdfa/checker/PdfA2Checker.cs +++ b/itext/itext.pdfa/itext/pdfa/checker/PdfA2Checker.cs @@ -44,8 +44,10 @@ source product. using System; using System.Collections.Generic; using iText.IO.Colors; +using iText.IO.Font; using iText.IO.Image; using iText.Kernel.Colors; +using iText.Kernel.Font; using iText.Kernel.Geom; using iText.Kernel.Pdf; using iText.Kernel.Pdf.Annot; @@ -55,6 +57,14 @@ source product. using iText.Pdfa; namespace iText.Pdfa.Checker { + /// + /// PdfA2Checker defines the requirements of the PDF/A-2 standard and contains a + /// number of methods that override the implementations of its superclass + /// + /// . + ///

    + /// The specification implemented by this class is ISO 19005-2 + ///

    public class PdfA2Checker : PdfA1Checker { protected internal static readonly ICollection forbiddenAnnotations = new HashSet(iText.IO.Util.JavaUtil.ArraysAsList (PdfName._3D, PdfName.Sound, PdfName.Screen, PdfName.Movie)); @@ -80,6 +90,11 @@ public class PdfA2Checker : PdfA1Checker { private IDictionary separationColorSpaces = new Dictionary(); + /// Creates a PdfA2Checker with the required conformance level + /// + /// the required conformance level, a or + /// u or b + /// public PdfA2Checker(PdfAConformanceLevel conformanceLevel) : base(conformanceLevel) { } @@ -118,15 +133,15 @@ public override void CheckColor(Color color, PdfDictionary currentColorSpaces, b PdfObject colorSpace = shadingDictionary.Get(PdfName.ColorSpace); CheckColorSpace(PdfColorSpace.MakeColorSpace(colorSpace), currentColorSpaces, true, true); PdfDictionary extGStateDict = ((PdfDictionary)pattern.GetPdfObject()).GetAsDictionary(PdfName.ExtGState); - CanvasGraphicsState gState = new _CanvasGraphicsState_137(extGStateDict); + CanvasGraphicsState gState = new _CanvasGraphicsState_152(extGStateDict); CheckExtGState(gState); } } CheckColorSpace(color.GetColorSpace(), currentColorSpaces, true, fill); } - private sealed class _CanvasGraphicsState_137 : CanvasGraphicsState { - public _CanvasGraphicsState_137(PdfDictionary extGStateDict) { + private sealed class _CanvasGraphicsState_152 : CanvasGraphicsState { + public _CanvasGraphicsState_152(PdfDictionary extGStateDict) { this.extGStateDict = extGStateDict; { this.UpdateFromExtGState(new PdfExtGState(extGStateDict)); @@ -279,6 +294,16 @@ public override void CheckExtGState(CanvasGraphicsState extGState) { } } + protected internal override void CheckNonSymbolicTrueTypeFont(PdfTrueTypeFont trueTypeFont) { + String encoding = trueTypeFont.GetFontEncoding().GetBaseEncoding(); + // non-symbolic true type font will always has an encoding entry in font dictionary in itext7 + if (!PdfEncodings.WINANSI.Equals(encoding) && !encoding.Equals(PdfEncodings.MACROMAN)) { + throw new PdfAConformanceException(PdfAConformanceException.AllNonSymbolicTrueTypeFontShallSpecifyMacRomanEncodingOrWinAnsiEncoding + , trueTypeFont); + } + } + + // if font has differences array, itext7 ensures that all names in it are listed in AdobeGlyphList protected internal override double GetMaxRealValue() { return float.MaxValue; } @@ -349,6 +374,7 @@ protected internal override void CheckAnnotation(PdfDictionary annotDic) { ); } } + CheckResourcesOfAppearanceStreams(ap); } else { bool isCorrectRect = false; @@ -381,6 +407,15 @@ protected internal override void CheckForm(PdfDictionary form) { throw new PdfAConformanceException(PdfAConformanceException.TheInteractiveFormDictionaryShallNotContainTheXfaKey ); } + CheckResources(form.GetAsDictionary(PdfName.DR)); + PdfArray fields = form.GetAsArray(PdfName.Fields); + if (fields != null) { + fields = GetFormFields(fields); + foreach (PdfObject field in fields) { + PdfDictionary fieldDic = (PdfDictionary)field; + CheckResources(fieldDic.GetAsDictionary(PdfName.DR)); + } + } } } @@ -473,7 +508,7 @@ protected internal override void CheckCatalogValidEntries(PdfDictionary catalogD if (order.Count != ocgs.Count) { throw new PdfAConformanceException(PdfAConformanceException.OrderArrayShallContainReferencesToAllOcgs); } - order.IntersectWith(ocgs); + order.RetainAll(ocgs); if (order.Count != ocgs.Count) { throw new PdfAConformanceException(PdfAConformanceException.OrderArrayShallContainReferencesToAllOcgs); } @@ -779,6 +814,7 @@ protected internal override void CheckFormXObject(PdfStream form) { CheckColorSpace(PdfColorSpace.MakeColorSpace(cs), currentColorSpaces, true, null); } } + CheckResources(form.GetAsDictionary(PdfName.Resources)); } private void CheckBlendMode(PdfName blendMode) { diff --git a/itext/itext.pdfa/itext/pdfa/checker/PdfA3Checker.cs b/itext/itext.pdfa/itext/pdfa/checker/PdfA3Checker.cs index f2c1c44fd9..7ff2118d1f 100644 --- a/itext/itext.pdfa/itext/pdfa/checker/PdfA3Checker.cs +++ b/itext/itext.pdfa/itext/pdfa/checker/PdfA3Checker.cs @@ -46,10 +46,22 @@ source product. using iText.Pdfa; namespace iText.Pdfa.Checker { + /// + /// PdfA3Checker defines the requirements of the PDF/A-3 standard and contains a + /// number of methods that override the implementations of its superclass + /// + /// . + /// The specification implemented by this class is ISO 19005-3 + /// public class PdfA3Checker : PdfA2Checker { protected internal static readonly ICollection allowedAFRelationships = new HashSet(iText.IO.Util.JavaUtil.ArraysAsList (PdfName.Source, PdfName.Data, PdfName.Alternative, PdfName.Supplement, PdfName.Unspecified)); + /// Creates a PdfA3Checker with the required conformance level + /// + /// the required conformance level, a or + /// u or b + /// public PdfA3Checker(PdfAConformanceLevel conformanceLevel) : base(conformanceLevel) { } diff --git a/itext/itext.pdfa/itext/pdfa/checker/PdfAChecker.cs b/itext/itext.pdfa/itext/pdfa/checker/PdfAChecker.cs index bda73dc799..ff20955406 100644 --- a/itext/itext.pdfa/itext/pdfa/checker/PdfAChecker.cs +++ b/itext/itext.pdfa/itext/pdfa/checker/PdfAChecker.cs @@ -45,22 +45,65 @@ source product. using System.Collections.Generic; using iText.IO.Colors; using iText.Kernel.Colors; +using iText.Kernel.Font; using iText.Kernel.Pdf; using iText.Kernel.Pdf.Canvas; using iText.Kernel.Pdf.Colorspace; namespace iText.Pdfa.Checker { + /// + /// An abstract class that will run through all necessary checks defined in the + /// different PDF/A standards and levels. + /// + /// + /// An abstract class that will run through all necessary checks defined in the + /// different PDF/A standards and levels. A number of common checks are executed + /// in this class, while standard-dependent specifications are implemented in the + /// available subclasses. The standard that is followed is the series of ISO + /// 19005 specifications, currently generations 1 through 3. The ZUGFeRD standard + /// is derived from ISO 19005-3. + /// While it is possible to subclass this method and implement its abstract + /// methods in client code, this is not encouraged and will have little effect. + /// It is not possible to plug custom implementations into iText, because iText + /// should always refuse to create non-compliant PDF/A, which would be possible + /// with client code implementations. Any future generations of the PDF/A + /// standard and its derivates will get their own implementation in the + /// iText 7 - pdfa project. + /// public abstract class PdfAChecker { + /// + /// The Red-Green-Blue color profile as defined by the International Color + /// Consortium. + /// public const String ICC_COLOR_SPACE_RGB = "RGB "; + /// + /// The Cyan-Magenta-Yellow-Key (black) color profile as defined by the + /// International Color Consortium. + /// public const String ICC_COLOR_SPACE_CMYK = "CMYK"; + /// + /// The Grayscale color profile as defined by the International Color + /// Consortium. + /// public const String ICC_COLOR_SPACE_GRAY = "GRAY"; + /// The Output device class public const String ICC_DEVICE_CLASS_OUTPUT_PROFILE = "prtr"; + /// The Monitor device class public const String ICC_DEVICE_CLASS_MONITOR_PROFILE = "mntr"; + /// The maximum Graphics State stack depth in PDF/A documents, i.e. + /// + /// The maximum Graphics State stack depth in PDF/A documents, i.e. the + /// maximum number of graphics state operators with code q that + /// may be opened (i.e. not yet closed by a corresponding Q) at + /// any point in a content stream sequence. + /// Defined as 28 by PDF/A-1 section 6.1.12, by referring to the PDF spec + /// Appendix C table 1 "architectural limits". + /// public const int maxGsStackDepth = 28; protected internal PdfAConformanceLevel conformanceLevel; @@ -93,6 +136,17 @@ protected internal PdfAChecker(PdfAConformanceLevel conformanceLevel) { this.conformanceLevel = conformanceLevel; } + /// + /// This method checks a number of document-wide requirements of the PDF/A + /// standard. + /// + /// + /// This method checks a number of document-wide requirements of the PDF/A + /// standard. The algorithms of some of these checks vary with the PDF/A + /// level and thus are implemented in subclasses; others are implemented + /// as private methods in this class. + /// + /// public virtual void CheckDocument(PdfCatalog catalog) { PdfDictionary catalogDict = catalog.GetPdfObject(); SetPdfAOutputIntentColorSpace(catalogDict); @@ -108,10 +162,20 @@ public virtual void CheckDocument(PdfCatalog catalog) { CheckColorsUsages(); } + /// + /// This method checks all requirements that must be fulfilled by a page in a + /// PDF/A document. + /// + /// the page that must be checked public virtual void CheckSinglePage(PdfPage page) { CheckPage(page); } + /// + /// This method checks the requirements that must be fulfilled by a COS + /// object in a PDF/A document. + /// + /// the COS object that must be checked public virtual void CheckPdfObject(PdfObject obj) { switch (obj.GetObjectType()) { case PdfObject.NUMBER: { @@ -120,10 +184,7 @@ public virtual void CheckPdfObject(PdfObject obj) { } case PdfObject.STREAM: { - PdfStream stream = (PdfStream)obj; - //form xObjects, annotation appearance streams, patterns and type3 glyphs may have their own resources dictionary - CheckResources(stream.GetAsDictionary(PdfName.Resources)); - CheckPdfStream(stream); + CheckPdfStream((PdfStream)obj); break; } @@ -143,27 +204,122 @@ public virtual void CheckPdfObject(PdfObject obj) { } } + /// + /// Gets the + /// + /// for this file. + /// + /// the defined conformance level for this document. public virtual PdfAConformanceLevel GetConformanceLevel() { return conformanceLevel; } + /// + /// Remembers which objects have already been checked, in order to avoid + /// redundant checks. + /// + /// the object to check + /// whether or not the object has already been checked public virtual bool ObjectIsChecked(PdfObject @object) { return checkedObjects.Contains(@object); } + /// + /// This method checks compliance of the tag structure elements, such as struct elements + /// or parent tree entries. + /// + /// an object that represents tag structure element. + public virtual void CheckTagStructureElement(PdfObject obj) { + // We don't check tag structure as there are no strict constraints, + // so we just mark tag structure elements to be able to flush them + checkedObjects.Add(obj); + } + + /// + /// This method checks compliance with the graphics state architectural + /// limitation, explained by + /// + /// . + /// + /// the operation to check the graphics state counter for public abstract void CheckCanvasStack(char stackOperation); + /// + /// This method checks compliance with the inline image restrictions in the + /// PDF/A specs, specifically filter parameters. + /// + /// + /// a + /// + /// containing the inline image + /// + /// + /// a + /// + /// containing the color spaces used in the document + /// public abstract void CheckInlineImage(PdfStream inlineImage, PdfDictionary currentColorSpaces); + /// + /// This method checks compliance with the color restrictions imposed by the + /// available color spaces in the document. + /// + /// the color to check + /// + /// a + /// + /// containing the color spaces used in the document + /// + /// whether the color is used for fill or stroke operations public abstract void CheckColor(Color color, PdfDictionary currentColorSpaces, bool? fill); + /// + /// This method performs a range of checks on the given color space, depending + /// on the type and properties of that color space. + /// + /// the color space to check + /// + /// a + /// + /// containing the color spaces used in the document + /// + /// whether or not to also check the parent color space + /// whether the color space is used for fill or stroke operations public abstract void CheckColorSpace(PdfColorSpace colorSpace, PdfDictionary currentColorSpaces, bool checkAlternate , bool? fill); + /// + /// Checks whether the rendering intent of the document is within the allowed + /// range of intents. + /// + /// + /// Checks whether the rendering intent of the document is within the allowed + /// range of intents. This is defined in ISO 19005-1 section 6.2.9, and + /// unchanged in newer generations of the PDF/A specification. + /// + /// the intent to be analyzed public abstract void CheckRenderingIntent(PdfName intent); + /// + /// Performs a number of checks on the graphics state, among others ISO + /// 19005-1 section 6.2.8 and 6.4 and ISO 19005-2 section 6.2.5 and 6.2.10. + /// + /// the graphics state to be checked public abstract void CheckExtGState(CanvasGraphicsState extGState); + /// Performs a number of checks on the font. + /// + /// Performs a number of checks on the font. See ISO 19005-1 section 6.3, + /// ISO 19005-2 and ISO 19005-3 section 6.2.11. + /// Be aware that not all constraints defined in the ISO are checked in this method, + /// for most of them we consider that iText always creates valid fonts. + /// + /// font to be checked + public virtual void CheckFont(PdfFont pdfFont) { + //TODO iText 7.1: Mark as abstract + throw new Exception("You must override this method"); + } + protected internal abstract ICollection GetForbiddenActions(); protected internal abstract ICollection GetAllowedNamedActions(); @@ -188,6 +344,11 @@ public abstract void CheckColorSpace(PdfColorSpace colorSpace, PdfDictionary cur protected internal abstract void CheckMetaData(PdfDictionary catalog); + //TODO iText 7.1: Mark as abstract + protected internal virtual void CheckNonSymbolicTrueTypeFont(PdfTrueTypeFont trueTypeFont) { + throw new Exception("You must override this method"); + } + protected internal abstract void CheckOutputIntents(PdfDictionary catalog); protected internal abstract void CheckPageObject(PdfDictionary page, PdfDictionary pageResources); @@ -200,6 +361,11 @@ public abstract void CheckColorSpace(PdfColorSpace colorSpace, PdfDictionary cur protected internal abstract void CheckPdfString(PdfString @string); + //TODO iText 7.1: Mark as abstract + protected internal virtual void CheckSymbolicTrueTypeFont(PdfTrueTypeFont trueTypeFont) { + throw new Exception("You must override this method"); + } + protected internal abstract void CheckTrailer(PdfDictionary trailer); protected internal virtual void CheckResources(PdfDictionary resources) { @@ -208,11 +374,17 @@ protected internal virtual void CheckResources(PdfDictionary resources) { } PdfDictionary xObjects = resources.GetAsDictionary(PdfName.XObject); PdfDictionary shadings = resources.GetAsDictionary(PdfName.Shading); + PdfDictionary patterns = resources.GetAsDictionary(PdfName.Pattern); if (xObjects != null) { foreach (PdfObject xObject in xObjects.Values()) { PdfStream xObjStream = (PdfStream)xObject; - PdfObject subtype = xObjStream.Get(PdfName.Subtype); - if (PdfName.Image.Equals(subtype)) { + PdfObject subtype = null; + bool isFlushed = xObjStream.IsFlushed(); + if (!isFlushed) { + subtype = xObjStream.Get(PdfName.Subtype); + } + if (PdfName.Image.Equals(subtype) || isFlushed) { + // if flushed still may be need to check colorspace in given context CheckImage(xObjStream, resources.GetAsDictionary(PdfName.ColorSpace)); } else { @@ -225,8 +397,20 @@ protected internal virtual void CheckResources(PdfDictionary resources) { if (shadings != null) { foreach (PdfObject shading in shadings.Values()) { PdfDictionary shadingDict = (PdfDictionary)shading; - CheckColorSpace(PdfColorSpace.MakeColorSpace(shadingDict.Get(PdfName.ColorSpace)), resources.GetAsDictionary - (PdfName.ColorSpace), true, null); + if (!IsAlreadyChecked(shadingDict)) { + CheckColorSpace(PdfColorSpace.MakeColorSpace(shadingDict.Get(PdfName.ColorSpace)), resources.GetAsDictionary + (PdfName.ColorSpace), true, null); + } + } + } + if (patterns != null) { + foreach (PdfObject p in patterns.Values()) { + if (p.IsStream()) { + PdfStream pStream = (PdfStream)p; + if (!IsAlreadyChecked(pStream)) { + CheckResources(pStream.GetAsDictionary(PdfName.Resources)); + } + } } } } @@ -248,6 +432,24 @@ protected internal virtual bool IsAlreadyChecked(PdfDictionary dictionary) { return false; } + protected internal virtual void CheckResourcesOfAppearanceStreams(PdfDictionary appearanceStreamsDict) { + foreach (PdfObject val in appearanceStreamsDict.Values()) { + if (val is PdfDictionary) { + PdfDictionary ap = (PdfDictionary)val; + if (ap.IsDictionary()) { + CheckResourcesOfAppearanceStreams(ap); + } + else { + if (ap.IsStream()) { + if (!IsAlreadyChecked(ap)) { + CheckResources(ap.GetAsDictionary(PdfName.Resources)); + } + } + } + } + } + } + private void CheckPages(PdfDocument document) { for (int i = 1; i <= document.GetNumberOfPages(); i++) { CheckPage(document.GetPage(i)); @@ -271,27 +473,14 @@ private void CheckPage(PdfPage page) { } private void CheckOpenAction(PdfObject openAction) { - if (openAction == null) { - return; - } - if (openAction.IsDictionary()) { + if (openAction != null && openAction.IsDictionary()) { CheckAction((PdfDictionary)openAction); } - else { - if (openAction.IsArray()) { - PdfArray actions = (PdfArray)openAction; - foreach (PdfObject action in actions) { - CheckAction((PdfDictionary)action); - } - } - } } private void CheckAnnotations(PdfDictionary page) { PdfArray annots = page.GetAsArray(PdfName.Annots); if (annots != null) { - // explicit iteration to resolve indirect references on get(). - // TODO DEVSIX-591 for (int i = 0; i < annots.Size(); i++) { PdfDictionary annot = annots.GetAsDictionary(i); CheckAnnotation(annot); diff --git a/itext/itext.pdftest/Properties/AssemblyInfo.cs b/itext/itext.pdftest/Properties/AssemblyInfo.cs index 44e8137128..df04dcb7b6 100644 --- a/itext/itext.pdftest/Properties/AssemblyInfo.cs +++ b/itext/itext.pdftest/Properties/AssemblyInfo.cs @@ -15,6 +15,6 @@ [assembly: Guid("f9880dc4-f015-4413-af86-66d0e9512774")] -[assembly: AssemblyVersion("7.0.0.0")] -[assembly: AssemblyFileVersion("7.0.0.0")] -[assembly: log4net.Config.XmlConfigurator(Watch = true)] \ No newline at end of file +[assembly: AssemblyVersion("7.0.1.0")] +[assembly: AssemblyFileVersion("7.0.1.0")] +[assembly: log4net.Config.XmlConfigurator(Watch = true)] diff --git a/itext/itext.pdftest/itext.pdftest.csproj b/itext/itext.pdftest/itext.pdftest.csproj index bfbd177c68..1bb20c70fe 100644 --- a/itext/itext.pdftest/itext.pdftest.csproj +++ b/itext/itext.pdftest/itext.pdftest.csproj @@ -39,10 +39,10 @@ - ..\..\packages\NUnit.3.2.1\lib\net40\nunit.framework.dll + $(SolutionDir)\packages\NUnit.3.2.1\lib\net40\nunit.framework.dll - ..\..\packages\log4net.2.0.5\lib\net40-full\log4net.dll + $(SolutionDir)\packages\log4net.2.0.5\lib\net40-full\log4net.dll diff --git a/itext/itext.pdftest/itext/test/ExtendedITextTest.cs b/itext/itext.pdftest/itext/test/ExtendedITextTest.cs index 764ec7d27c..62f1e6fa62 100644 --- a/itext/itext.pdftest/itext/test/ExtendedITextTest.cs +++ b/itext/itext.pdftest/itext/test/ExtendedITextTest.cs @@ -41,15 +41,28 @@ source product. For more information, please contact iText Software Corp. at this address: sales@itextpdf.com */ + +using iText.Test.Attributes; using NUnit.Framework; namespace iText.Test { + /// + /// This class is used for testing when logger output should be tested as well. + /// By default any logger output that is not expected, i.e. marked with + /// will result in crash. + /// [LogListener] public abstract class ExtendedITextTest : ITextTest { + /// + /// This method is called before each test method is executed + /// [SetUp] public virtual void BeforeTestMethodAction() { } + /// + /// This method is called after each test method is executed + /// [TearDown] public virtual void AfterTestMethodAction() { } diff --git a/itext/itext.pdftest/itext/test/ITextMemoryAppender.cs b/itext/itext.pdftest/itext/test/ITextMemoryAppender.cs index d8f716fed0..39a13f413c 100644 --- a/itext/itext.pdftest/itext/test/ITextMemoryAppender.cs +++ b/itext/itext.pdftest/itext/test/ITextMemoryAppender.cs @@ -49,7 +49,9 @@ namespace iText.Test { public class ITextMemoryAppender : MemoryAppender { protected override void Append(LoggingEvent le) { Console.WriteLine(le.LoggerName + ": " + le.RenderedMessage); - base.Append(le); + if (le.Level >= Level.Warn) { + base.Append(le); + } } } } diff --git a/itext/itext.pdftest/itext/test/ITextTest.cs b/itext/itext.pdftest/itext/test/ITextTest.cs index a82bcad78d..fe57a70979 100644 --- a/itext/itext.pdftest/itext/test/ITextTest.cs +++ b/itext/itext.pdftest/itext/test/ITextTest.cs @@ -49,6 +49,10 @@ source product. using NUnit.Framework; namespace iText.Test { + /// + /// This is a generic class for testing. Subclassing it, or its subclasses is considered a good practice of + /// creating your own tests. + /// public abstract class ITextTest { //protected readonly ILogger LOGGER = LoggerFactory.GetLogger(gett); @@ -58,28 +62,31 @@ public static void SetUpFixture() { ResourceUtil.AddToResourceSearch(TestContext.CurrentContext.TestDirectory + "/itext.font_asian.dll"); } + /// + /// Creates a folder with a given path, including all necessary nonexistent parent directories. * + /// If a folder is already present, no action is performed. * + /// + /// the path of the folder to create public static void CreateDestinationFolder(String path) { Directory.CreateDirectory(path); } + /// + /// Creates a directory with given path if it does not exist and clears the contents + /// of the directory in case it exists. + /// + /// the path of the directory to be created/cleared public static void CreateOrClearDestinationFolder(String path) { Directory.CreateDirectory(path); - foreach (String f in Directory.GetFiles(path)) { - File.Delete(f); - } + DeleteDirectoryContents(path, false); } + /// + /// Removes the directory with given path along with its content including all the subdirectories. + /// + /// the path of the directory to be removed public static void DeleteDirectory(String path) { - if (Directory.Exists(path)) { - foreach (string d in Directory.GetDirectories(path)) { - DeleteDirectory(d); - Directory.Delete(d); - } - foreach (string f in Directory.GetFiles(path)) { - File.Delete(f); - } - Directory.Delete(path); - } + DeleteDirectoryContents(path, true); } protected virtual byte[] ReadFile(String filename) { @@ -98,5 +105,20 @@ protected virtual String CreateStringByEscaped(byte[] bytes) } return buf.ToString(); } + + private static void DeleteDirectoryContents(String path, bool removeParentDirectory) { + if (Directory.Exists(path)) { + foreach (string d in Directory.GetDirectories(path)) { + DeleteDirectoryContents(d, false); + Directory.Delete(d); + } + foreach (string f in Directory.GetFiles(path)) { + File.Delete(f); + } + if (removeParentDirectory) { + Directory.Delete(path); + } + } + } } } \ No newline at end of file diff --git a/itext/itext.pdftest/itext/test/LogListener.cs b/itext/itext.pdftest/itext/test/LogListener.cs index 5769f77ee1..410ce17918 100644 --- a/itext/itext.pdftest/itext/test/LogListener.cs +++ b/itext/itext.pdftest/itext/test/LogListener.cs @@ -77,34 +77,30 @@ public override ActionTargets Targets private void CheckLogMessages(ITest testDetails) { - LogMessageAttribute[] attributes = testDetails.Method.GetCustomAttributes(true); + int checkedMessages = 0; + LogMessageAttribute[] attributes = testDetails.Method.GetCustomAttributes(true); if (attributes.Length > 0) { for (int i = 0; i < attributes.Length; i++) { LogMessageAttribute logMessage = attributes[i]; - if (!logMessage.Ignore) + int foundCount = Contains(logMessage.GetMessageTemplate()); + if (foundCount != logMessage.Count && !logMessage.Ignore) { + Assert.Fail("{0} Expected to find {1}, but found {2} messages with the following content: \"{3}\"", + testDetails.FullName, logMessage.Count, foundCount, logMessage.GetMessageTemplate()); + } + else { - int foundedCount = Contains(logMessage.GetMessageTemplate()); - if (foundedCount != logMessage.Count) - { - Assert.Fail("{0} Some log messages are not found in test execution - {1} messages", - testDetails.FullName, - logMessage.Count - foundedCount); - - } + checkedMessages += foundCount; } } } - else + + if (GetSize() > checkedMessages) { - if (GetSize() > 0) - { - Assert.Fail("{0}: The test does not check the message logging - {1} messages", - testDetails.FullName, - GetSize()); - } - + Assert.Fail("{0}: The test does not check the message logging - {1} messages", + testDetails.FullName, + GetSize() - checkedMessages); } } diff --git a/itext/itext.pdftest/itext/test/RunnerSearchConfig.cs b/itext/itext.pdftest/itext/test/RunnerSearchConfig.cs new file mode 100644 index 0000000000..29f4a45459 --- /dev/null +++ b/itext/itext.pdftest/itext/test/RunnerSearchConfig.cs @@ -0,0 +1,98 @@ +/* + This file is part of the iText (R) project. + Copyright (c) 1998-2016 iText Group NV + Authors: Bruno Lowagie, Paulo Soares, et al. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License version 3 + as published by the Free Software Foundation with the addition of the + following permission added to Section 15 as permitted in Section 7(a): + FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY + ITEXT GROUP. ITEXT GROUP DISCLAIMS THE WARRANTY OF NON INFRINGEMENT + OF THIRD PARTY RIGHTS + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Affero General Public License for more details. + You should have received a copy of the GNU Affero General Public License + along with this program; if not, see http://www.gnu.org/licenses or write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA, 02110-1301 USA, or download the license from the following URL: + http://itextpdf.com/terms-of-use/ + + The interactive user interfaces in modified source and object code versions + of this program must display Appropriate Legal Notices, as required under + Section 5 of the GNU Affero General Public License. + + In accordance with Section 7(b) of the GNU Affero General Public License, + a covered work must retain the producer line in every PDF that is created + or manipulated using iText. + + You can be released from the requirements of the license by purchasing + a commercial license. Buying such a license is mandatory as soon as you + develop commercial activities involving the iText software without + disclosing the source code of your own applications. + These activities include: offering paid services to customers as an ASP, + serving PDFs on the fly in a web application, shipping iText with a closed + source product. + + For more information, please contact iText Software Corp. at this + address: sales@itextpdf.com + */ + +using System; +using System.Collections.Generic; +using iText.Test.Attributes; + +namespace iText.Test { + public class RunnerSearchConfig { + private IList searchPackages = new List(); + private IList searchClasses = new List(); + private IList ignoredPaths = new List(); + private bool isToMarkTestsWithoutAnnotationAsIgnored; + + /// + /// Add namespace to search path which is checked for wrapped sample classes. + /// Tests run only if they have attribute. + /// + /// full name of namespace to be checked. + public virtual RunnerSearchConfig AddPackageToRunnerSearchPath(String fullName) { + searchPackages.Add(fullName); + return this; + } + + /// + /// Add class to runner if it has attribute. + /// + /// full name of class to be checked. + public virtual RunnerSearchConfig AddClassToRunnerSearchPath(String fullName) { + searchClasses.Add(fullName); + return this; + } + + /// + /// Add namespace or class to ignore list. Items from this list won't be checked for wrapped sample classes. + /// + /// full or partial name of the namespace or class to be omitted by this runner. + /// E.g. "Highlevel.Appendix" or "iText.Highlevel.Appendix.TableProperties". + public virtual RunnerSearchConfig IgnorePackageOrClass(String name) { + ignoredPaths.Add(name); + return this; + } + + /// + /// If a class was found in search path, and it has DEST field and main method, but it doesn't have + /// WrapToTest attribute, this test will be marked as ignored with corresponding message in case this option is used. + /// + public virtual RunnerSearchConfig MarkTestsWithoutAnnotationAsIgnored() { + isToMarkTestsWithoutAnnotationAsIgnored = true; + return this; + } + + public virtual IList GetSearchPackages() { return searchPackages; } + public virtual IList GetSearchClasses() { return searchClasses; } + public virtual IList GetIgnoredPaths() { return ignoredPaths; } + public virtual bool IsToMarkTestsWithoutAnnotationAsIgnored() { return isToMarkTestsWithoutAnnotationAsIgnored; } + } +} \ No newline at end of file diff --git a/itext/itext.pdftest/itext/test/WrappedSamplesRunner.cs b/itext/itext.pdftest/itext/test/WrappedSamplesRunner.cs new file mode 100644 index 0000000000..b6453fb1c9 --- /dev/null +++ b/itext/itext.pdftest/itext/test/WrappedSamplesRunner.cs @@ -0,0 +1,254 @@ +/* +This file is part of the iText (R) project. +Copyright (c) 1998-2016 iText Group NV +Authors: Bruno Lowagie, Paulo Soares, et al. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License version 3 +as published by the Free Software Foundation with the addition of the +following permission added to Section 15 as permitted in Section 7(a): +FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY +ITEXT GROUP. ITEXT GROUP DISCLAIMS THE WARRANTY OF NON INFRINGEMENT +OF THIRD PARTY RIGHTS + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. +See the GNU Affero General Public License for more details. +You should have received a copy of the GNU Affero General Public License +along with this program; if not, see http://www.gnu.org/licenses or write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +Boston, MA, 02110-1301 USA, or download the license from the following URL: +http://itextpdf.com/terms-of-use/ + +The interactive user interfaces in modified source and object code versions +of this program must display Appropriate Legal Notices, as required under +Section 5 of the GNU Affero General Public License. + +In accordance with Section 7(b) of the GNU Affero General Public License, +a covered work must retain the producer line in every PDF that is created +or manipulated using iText. + +You can be released from the requirements of the license by purchasing +a commercial license. Buying such a license is mandatory as soon as you +develop commercial activities involving the iText software without +disclosing the source code of your own applications. +These activities include: offering paid services to customers as an ASP, +serving PDFs on the fly in a web application, shipping iText with a closed +source product. + +For more information, please contact iText Software Corp. at this +address: sales@itextpdf.com +*/ +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using iText.IO.Util; +using iText.Test.Attributes; +using NUnit.Framework; + +namespace iText.Test { + public abstract class WrappedSamplesRunner { + + protected Type sampleClass; + + private RunnerParams sampleClassParams; + + private String errorMessage; + + protected WrappedSamplesRunner(RunnerParams runnerParams) { + this.sampleClassParams = runnerParams; + } + + protected static ICollection GenerateTestsList(Assembly assembly) { + return GenerateTestsList(assembly, new RunnerSearchConfig().AddPackageToRunnerSearchPath("")); + } + + protected static ICollection GenerateTestsList(Assembly assembly, RunnerSearchConfig searchConfig) { + IList parametersList = new List(); + foreach (Type type in assembly.GetTypes()) { + WrappedSamplesRunner.RunnerParams runnerParams = CheckIfTestAndCreateParams(type, searchConfig); + if (runnerParams != null) { + parametersList.Add(new TestFixtureData(runnerParams)); + } + } + + return parametersList; + } + + /// + public virtual void RunSamples() { + Assume.That(sampleClassParams.ignoreMessage == null, sampleClassParams.ignoreMessage); + + sampleClass = sampleClassParams.sampleType; + System.Console.Out.WriteLine("Starting test " + sampleClassParams); + + string oldCurrentDir = Environment.CurrentDirectory; + Environment.CurrentDirectory = NUnit.Framework.TestContext.CurrentContext.TestDirectory; + + RunMain(); + + String dest = GetDest(); + String cmp = GetCmpPdf(dest); + if (String.IsNullOrEmpty(dest)) { + throw new ArgumentException("Can't verify results, DEST field must not be empty!"); + } + String outPath = GetOutPath(dest); + FileUtil.CreateDirectories(outPath); + System.Console.Out.WriteLine("Test executed successfully, comparing results..."); + ComparePdf(outPath, dest, cmp); + + Environment.CurrentDirectory = oldCurrentDir; + + if (errorMessage != null) { + NUnit.Framework.Assert.Fail(errorMessage); + } + System.Console.Out.WriteLine("Test complete."); + + } + + /// Compares two PDF files using iText's CompareTool. + /// path to the working folder where comparison results and temp files will be created + /// the PDF that resulted from the test + /// the reference PDF + /// + protected internal abstract void ComparePdf(String outPath, String dest, String cmp); + + /// Gets the path to the resulting PDF from the sample class; + /// a path to a resulting PDF + protected internal virtual String GetDest() { + return GetStringField(sampleClassParams.sampleType, "DEST"); + } + + protected internal virtual String GetCmpPdf(String dest) { + if (dest == null) { + return null; + } + int i = dest.LastIndexOf("/"); + return "../../cmpfiles/" + dest.Substring(14, (i + 1) - 14) + "cmp_" + dest.Substring(i + 1); + } + + protected internal virtual String GetOutPath(String dest) { + return Path.GetDirectoryName(dest); + } + + /// + /// Returns a string value that is stored as a static variable + /// inside an example class. + /// + /// the name of the variable + /// the value of the variable + protected internal static String GetStringField(Type c, String name) { + try { + FieldInfo field = c.GetField(name); + if (field == null) { + return null; + } + Object obj = field.GetValue(null); + if (obj == null || !(obj is String)) { + return null; + } + return (String)obj; + } + catch (Exception) { + return null; + } + } + + /// Helper method to construct error messages. + /// part of an error message. + protected internal virtual void AddError(String error) { + if (!string.IsNullOrEmpty(error)) { + if (errorMessage == null) { + errorMessage = ""; + } + else { + errorMessage += "\n"; + } + errorMessage += error; + } + } + + /// + /// + /// + private void RunMain() { + MethodInfo mainMethod = GetMain(sampleClassParams.sampleType); + if (mainMethod == null) { + throw new ArgumentException("Class marked with WrapToTest annotation must have main method."); + } + mainMethod.Invoke(null, new Object[] { null }); + } + + private static MethodInfo GetMain(Type c) { + try { + return c.GetMethod("Main", new[]{ typeof(String[]) } ); + } + catch (MissingMethodException) { + return null; + } + } + + private static WrappedSamplesRunner.RunnerParams CheckIfTestAndCreateParams(Type classType, RunnerSearchConfig searchConfig) { + if (!IsInSearchPath(classType.FullName, searchConfig)) { + return null; + } + if (IsIgnoredClassOrPackage(classType.FullName, searchConfig)) { + return null; + } + + WrappedSamplesRunner.RunnerParams runnerParams = new WrappedSamplesRunner.RunnerParams(); + runnerParams.sampleType = classType; + Attribute attribute = Attribute.GetCustomAttribute(classType, typeof(WrapToTestAttribute)); + if (attribute == null) { + if (searchConfig.IsToMarkTestsWithoutAnnotationAsIgnored() && IsLookLikeTest(classType)) { + runnerParams.ignoreMessage = String.Format("Class {0} seems to be a test but it doesn't have WrapToTest annotation." + , classType.FullName); + return runnerParams; + } + return null; + } + WrapToTestAttribute wrapToTestAttribute = (WrapToTestAttribute) attribute; + if (!String.IsNullOrEmpty(wrapToTestAttribute.IgnoreWithMessage)) { + runnerParams.ignoreMessage = wrapToTestAttribute.IgnoreWithMessage; + } + return runnerParams; + } + + private static bool IsLookLikeTest(Type c) { + return GetStringField(c, "DEST") != null && GetMain(c) != null; + } + + private static bool IsIgnoredClassOrPackage(String fullName, RunnerSearchConfig searchConfig) { + foreach (String ignoredPath in searchConfig.GetIgnoredPaths()) { + if (fullName.Contains(ignoredPath)) { + return true; + } + } + return false; + } + + private static bool IsInSearchPath(String fullName, RunnerSearchConfig searchConfig) { + if (searchConfig.GetSearchClasses().Contains(fullName)) { + return true; + } + foreach (String searchPackage in searchConfig.GetSearchPackages()) { + if (fullName.StartsWith(searchPackage)) { + return true; + } + } + return false; + } + + public class RunnerParams { + internal Type sampleType; + + internal String ignoreMessage; + + public override String ToString() { + return sampleType.FullName; + } + } + } +} diff --git a/itext/itext.pdftest/itext/test/attributes/WrapToTestAttribute.cs b/itext/itext.pdftest/itext/test/attributes/WrapToTestAttribute.cs new file mode 100644 index 0000000000..16ec6f6488 --- /dev/null +++ b/itext/itext.pdftest/itext/test/attributes/WrapToTestAttribute.cs @@ -0,0 +1,69 @@ +/* + This file is part of the iText (R) project. + Copyright (c) 1998-2016 iText Group NV + Authors: Bruno Lowagie, Paulo Soares, et al. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License version 3 + as published by the Free Software Foundation with the addition of the + following permission added to Section 15 as permitted in Section 7(a): + FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY + ITEXT GROUP. ITEXT GROUP DISCLAIMS THE WARRANTY OF NON INFRINGEMENT + OF THIRD PARTY RIGHTS + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Affero General Public License for more details. + You should have received a copy of the GNU Affero General Public License + along with this program; if not, see http://www.gnu.org/licenses or write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA, 02110-1301 USA, or download the license from the following URL: + http://itextpdf.com/terms-of-use/ + + The interactive user interfaces in modified source and object code versions + of this program must display Appropriate Legal Notices, as required under + Section 5 of the GNU Affero General Public License. + + In accordance with Section 7(b) of the GNU Affero General Public License, + a covered work must retain the producer line in every PDF that is created + or manipulated using iText. + + You can be released from the requirements of the license by purchasing + a commercial license. Buying such a license is mandatory as soon as you + develop commercial activities involving the iText software without + disclosing the source code of your own applications. + These activities include: offering paid services to customers as an ASP, + serving PDFs on the fly in a web application, shipping iText with a closed + source product. + + For more information, please contact iText Software Corp. at this + address: sales@itextpdf.com + */ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace iText.Test.Attributes { + + /// + /// This attribute can be used to run a class that contains a public static void Main method as a test in the NUnit test runner. + /// + [AttributeUsage(AttributeTargets.Class)] + public class WrapToTestAttribute : Attribute { + private string ignoreWithMessage = ""; + + /// + /// Makes the test runner ignore the annotated class if a non-empty String is + /// specified. The text should contain a reason for ignoring this test, as it + /// is fed to the test runner. + /// + /// Defaults to the empty String, which does not trigger ignoring the test. + /// + public virtual string IgnoreWithMessage { + get { return ignoreWithMessage; } + set { ignoreWithMessage = value; } + } + } +} diff --git a/itext/itext.sign/Properties/AssemblyInfo.cs b/itext/itext.sign/Properties/AssemblyInfo.cs index fdbaf8e877..d409ca8583 100644 --- a/itext/itext.sign/Properties/AssemblyInfo.cs +++ b/itext/itext.sign/Properties/AssemblyInfo.cs @@ -21,5 +21,5 @@ [assembly: Guid("5092244a-a2ed-49d2-97fb-f513d965a8f7")] -[assembly: AssemblyVersion("7.0.0.0")] -[assembly: AssemblyFileVersion("7.0.0.0")] +[assembly: AssemblyVersion("7.0.1.0")] +[assembly: AssemblyFileVersion("7.0.1.0")] diff --git a/itext/itext.sign/itext.sign.csproj b/itext/itext.sign/itext.sign.csproj index d17c43eacf..97a6d96cd8 100644 --- a/itext/itext.sign/itext.sign.csproj +++ b/itext/itext.sign/itext.sign.csproj @@ -44,7 +44,7 @@ {E2828AC4-3C63-4B2A-B5AD-5F98862775BE} - forms + itext.forms {CEE5E7E1-1BF0-4BE1-9941-903262CE2F83} diff --git a/itext/itext.sign/itext/signatures/PdfPKCS7.cs b/itext/itext.sign/itext/signatures/PdfPKCS7.cs index 18e877738d..795adffe5b 100644 --- a/itext/itext.sign/itext/signatures/PdfPKCS7.cs +++ b/itext/itext.sign/itext/signatures/PdfPKCS7.cs @@ -161,7 +161,7 @@ public PdfPKCS7(byte[] contentsKey, PdfName filterSubtype) { pkcs = din.ReadObject(); } catch (System.IO.IOException) { - throw new ArgumentException(PdfException.CantDecodePkcs7SigneddataObject); + throw new ArgumentException(PdfException.CannotDecodePkcs7SigneddataObject); } if (!(pkcs is Asn1Sequence)) { throw new ArgumentException(PdfException.NotAValidPkcs7ObjectNotASequence); @@ -262,7 +262,7 @@ public PdfPKCS7(byte[] contentsKey, PdfName filterSubtype) { } } if (signCert == null) { - throw new PdfException(PdfException.CantFindSigningCertificateWithSerial1).SetMessageParams(issuer.ToString + throw new PdfException(PdfException.CannotFindSigningCertificateWithSerial1).SetMessageParams(issuer.ToString () + " / " + serialNumber.ToString(16)); } SignCertificateChain(); @@ -940,8 +940,8 @@ private DerSet GetAuthenticatedAttributeSet(byte[] secondDigest, byte[] ocsp, IC // Stefan Santesson // verification /// Verify the digest. - /// on error /// true if the signature checks out, false otherwise + /// on error /// public virtual bool Verify() { if (verified) { @@ -1000,8 +1000,7 @@ public virtual bool VerifyTimestampImprint() { String algOID = info.HashAlgorithm.ObjectID.Id; byte[] md = SignUtils.GetMessageDigest(DigestAlgorithms.GetDigest(algOID)).Digest(digest); byte[] imphashed = imprint.GetHashedMessage(); - bool res = iText.IO.Util.JavaUtil.ArraysEquals(md, imphashed); - return res; + return iText.IO.Util.JavaUtil.ArraysEquals(md, imphashed); } /// All the X.509 certificates in no particular order. @@ -1054,7 +1053,6 @@ private void SignCertificateChain() { if (signCert.Equals(oc[k])) { oc.JRemoveAt(k); --k; - continue; } } bool found = true; diff --git a/itext/itext.sign/itext/signatures/PdfSigner.cs b/itext/itext.sign/itext/signatures/PdfSigner.cs index c546a453d3..33a9f450c9 100644 --- a/itext/itext.sign/itext/signatures/PdfSigner.cs +++ b/itext/itext.sign/itext/signatures/PdfSigner.cs @@ -310,7 +310,7 @@ public virtual void SetFieldName(String fieldName) { throw new ArgumentException(PdfException.FieldTypeIsNotASignatureFieldType); } if (field.GetValue() != null) { - throw new ArgumentException(PdfException.FieldIsAlreadySigned); + throw new ArgumentException(PdfException.FieldAlreadySigned); } appearance.SetFieldName(fieldName); IList widgets = field.GetWidgets(); @@ -378,7 +378,7 @@ public virtual void SignDetached(IExternalSignature externalSignature, X509Certi crlList, IOcspClient ocspClient, ITSAClient tsaClient, int estimatedSize, PdfSigner.CryptoStandard sigtype) { if (closed) { - throw new PdfException(PdfException.ThisInstanceOfPdfSignerIsAlreadyClosed); + throw new PdfException(PdfException.ThisInstanceOfPdfSignerAlreadyClosed); } ICollection crlBytes = null; int i = 0; @@ -454,7 +454,7 @@ public virtual void SignDetached(IExternalSignature externalSignature, X509Certi public virtual void SignExternalContainer(IExternalSignatureContainer externalSignatureContainer, int estimatedSize ) { if (closed) { - throw new PdfException(PdfException.ThisInstanceOfPdfSignerIsAlreadyClosed); + throw new PdfException(PdfException.ThisInstanceOfPdfSignerAlreadyClosed); } PdfSignature dic = new PdfSignature(); PdfSignatureAppearance appearance = GetSignatureAppearance(); @@ -498,7 +498,7 @@ public virtual void SignExternalContainer(IExternalSignatureContainer externalSi /// public virtual void Timestamp(ITSAClient tsa, String signatureName) { if (closed) { - throw new PdfException(PdfException.ThisInstanceOfPdfSignerIsAlreadyClosed); + throw new PdfException(PdfException.ThisInstanceOfPdfSignerAlreadyClosed); } int contentEstimated = tsa.GetTokenSizeEstimate(); AddDeveloperExtension(PdfDeveloperExtension.ESIC_1_7_EXTENSIONLEVEL5); @@ -700,9 +700,15 @@ protected internal virtual void PreClose(IDictionary exclusionSiz } ap.Put(PdfName.N, appearance.GetAppearance().GetPdfObject()); acroForm.AddField(sigField, document.GetPage(pagen)); - acroForm.SetModified(); + if (acroForm.GetPdfObject().IsIndirect()) { + acroForm.SetModified(); + } + else { + //Acroform dictionary is a Direct dictionary, + //for proper flushing, catalog needs to be marked as modified + document.GetCatalog().SetModified(); + } } - // TODO: test this (ain't sure whether I need this) exclusionLocations = new Dictionary(); PdfLiteral lit = new PdfLiteral(80); exclusionLocations[PdfName.ByteRange] = lit; @@ -727,8 +733,9 @@ protected internal virtual void PreClose(IDictionary exclusionSiz PdfDictionary docmdp = new PdfDictionary(); docmdp.Put(PdfName.DocMDP, cryptoDictionary.GetPdfObject()); document.GetCatalog().Put(PdfName.Perms, docmdp); + document.GetCatalog().SetModified(); } - // TODO: setModified? + cryptoDictionary.GetPdfObject().Flush(false); document.Close(); range = new long[exclusionLocations.Count * 2]; long byteRangePosition = exclusionLocations.Get(PdfName.ByteRange).GetPosition(); @@ -827,7 +834,7 @@ protected internal virtual Stream GetRangeStream() { protected internal virtual void Close(PdfDictionary update) { try { if (!preClosed) { - throw new PdfException(PdfException.DocumentMustBePreclosed); + throw new PdfException(PdfException.DocumentMustBePreClosed); } MemoryStream bous = new MemoryStream(); PdfOutputStream os = new PdfOutputStream(bous); diff --git a/itext/itext.sign/itext/signatures/SignExtensions.cs b/itext/itext.sign/itext/signatures/SignExtensions.cs index d85d630490..09957cd317 100644 --- a/itext/itext.sign/itext/signatures/SignExtensions.cs +++ b/itext/itext.sign/itext/signatures/SignExtensions.cs @@ -64,7 +64,19 @@ public static void AddAll(this ICollection t, IEnumerable newItems) { } public static T[] ToArray(this ICollection col, T[] toArray) { - T[] r = col.ToArray(); + T[] r; + int colSize = col.Count; + if (colSize <= toArray.Length) { + col.CopyTo(toArray, 0); + if (colSize != toArray.Length) { + toArray[colSize] = default(T); + } + r = toArray; + } else { + r = new T[colSize]; + col.CopyTo(r, 0); + } + return r; } diff --git a/itext/itext.sign/itext/signatures/SignUtils.cs b/itext/itext.sign/itext/signatures/SignUtils.cs index 8fd8c0004b..e3c5992ab8 100644 --- a/itext/itext.sign/itext/signatures/SignUtils.cs +++ b/itext/itext.sign/itext/signatures/SignUtils.cs @@ -189,7 +189,7 @@ internal static TsaResponse GetTsaResponseForUserRequest(String tsaUrl, byte[] r con.Method = "POST"; if ((tsaUsername != null) && !tsaUsername.Equals("")) { string authInfo = tsaUsername + ":" + tsaPassword; - authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo), Base64FormattingOptions.None); + authInfo = Convert.ToBase64String(Encoding.UTF8.GetBytes(authInfo), Base64FormattingOptions.None); con.Headers["Authorization"] = "Basic " + authInfo; } Stream outp = con.GetRequestStream(); diff --git a/itext/itext.sign/itext/signatures/VerificationOK.cs b/itext/itext.sign/itext/signatures/VerificationOK.cs index 58ebaa6d8e..97c5b47d67 100644 --- a/itext/itext.sign/itext/signatures/VerificationOK.cs +++ b/itext/itext.sign/itext/signatures/VerificationOK.cs @@ -71,7 +71,7 @@ public VerificationOK(X509Certificate certificate, Type verifierClass, String me this.message = message; } - /// A single String explaining which certificate was verified, how and why. + /// Return a single String explaining which certificate was verified, how and why. /// public override String ToString() { StringBuilder sb = new StringBuilder(); diff --git a/port-hash b/port-hash new file mode 100644 index 0000000000..c18b7224bf --- /dev/null +++ b/port-hash @@ -0,0 +1 @@ +14f9149797f6df04bf4a44ac465c9728e9cb96c6