From 5c6c727b0035131a2f8fc194c96025d834f5d2db Mon Sep 17 00:00:00 2001 From: Severiano Jaramillo Date: Tue, 1 Oct 2019 16:39:35 -0500 Subject: [PATCH] Update PDF generation library. - Added the PDFjet library as a Java Library module to the project and moved all the logic to create the transactions PDF in the TransactionsFragment to use the new PDF lib instead of the old one. - Fixed the time formatter that was being used to format the transaction's times in exported PDF/CSV files, it was printing months in the place of minutes. --- PDFJet/.gitignore | 1 + PDFJet/build.gradle | 8 + PDFJet/src/main/java/com/pdfjet/A3.java | 41 + PDFJet/src/main/java/com/pdfjet/A4.java | 41 + PDFJet/src/main/java/com/pdfjet/A5.java | 42 + PDFJet/src/main/java/com/pdfjet/Align.java | 47 + .../src/main/java/com/pdfjet/Annotation.java | 87 + PDFJet/src/main/java/com/pdfjet/B5.java | 41 + PDFJet/src/main/java/com/pdfjet/BMPImage.java | 282 ++ PDFJet/src/main/java/com/pdfjet/Bidi.java | 235 ++ .../src/main/java/com/pdfjet/BitBuffer.java | 62 + PDFJet/src/main/java/com/pdfjet/Bookmark.java | 200 ++ PDFJet/src/main/java/com/pdfjet/Border.java | 43 + PDFJet/src/main/java/com/pdfjet/Box.java | 369 +++ .../main/java/com/pdfjet/CalendarMonth.java | 142 + PDFJet/src/main/java/com/pdfjet/Cap.java | 42 + PDFJet/src/main/java/com/pdfjet/Cell.java | 900 ++++++ PDFJet/src/main/java/com/pdfjet/CheckBox.java | 263 ++ PDFJet/src/main/java/com/pdfjet/Chunk.java | 91 + .../src/main/java/com/pdfjet/ClockWise.java | 47 + PDFJet/src/main/java/com/pdfjet/CodePage.java | 48 + PDFJet/src/main/java/com/pdfjet/Color.java | 191 ++ .../src/main/java/com/pdfjet/Compliance.java | 12 + .../java/com/pdfjet/CompositeTextLine.java | 387 +++ .../src/main/java/com/pdfjet/Compressor.java | 63 + PDFJet/src/main/java/com/pdfjet/CoreFont.java | 53 + PDFJet/src/main/java/com/pdfjet/Courier.java | 238 ++ .../main/java/com/pdfjet/Courier_Bold.java | 238 ++ .../java/com/pdfjet/Courier_BoldOblique.java | 238 ++ .../main/java/com/pdfjet/Courier_Oblique.java | 238 ++ .../main/java/com/pdfjet/Decompressor.java | 57 + .../src/main/java/com/pdfjet/Destination.java | 74 + .../src/main/java/com/pdfjet/Dimension.java | 61 + PDFJet/src/main/java/com/pdfjet/Drawable.java | 47 + PDFJet/src/main/java/com/pdfjet/Effect.java | 41 + PDFJet/src/main/java/com/pdfjet/Embed.java | 41 + .../main/java/com/pdfjet/EmbeddedFile.java | 105 + .../java/com/pdfjet/ErrorCorrectLevel.java | 28 + .../src/main/java/com/pdfjet/Executive.java | 41 + PDFJet/src/main/java/com/pdfjet/FastFont.java | 378 +++ .../src/main/java/com/pdfjet/FastFont2.java | 397 +++ PDFJet/src/main/java/com/pdfjet/Field.java | 75 + .../main/java/com/pdfjet/FileAttachment.java | 102 + PDFJet/src/main/java/com/pdfjet/Font.java | 677 +++++ .../src/main/java/com/pdfjet/FontTable.java | 38 + PDFJet/src/main/java/com/pdfjet/Form.java | 240 ++ PDFJet/src/main/java/com/pdfjet/Glyph.java | 265 ++ .../main/java/com/pdfjet/GraphicsState.java | 30 + .../src/main/java/com/pdfjet/Helvetica.java | 238 ++ .../main/java/com/pdfjet/Helvetica_Bold.java | 238 ++ .../com/pdfjet/Helvetica_BoldOblique.java | 238 ++ .../java/com/pdfjet/Helvetica_Oblique.java | 238 ++ .../main/java/com/pdfjet/ICCBlackScaled.java | 2584 +++++++++++++++++ PDFJet/src/main/java/com/pdfjet/Image.java | 799 +++++ .../src/main/java/com/pdfjet/ImageType.java | 44 + PDFJet/src/main/java/com/pdfjet/JPGImage.java | 237 ++ PDFJet/src/main/java/com/pdfjet/Join.java | 42 + .../src/main/java/com/pdfjet/LZWEncode.java | 112 + PDFJet/src/main/java/com/pdfjet/Legal.java | 40 + PDFJet/src/main/java/com/pdfjet/Letter.java | 41 + PDFJet/src/main/java/com/pdfjet/Line.java | 412 +++ .../src/main/java/com/pdfjet/LookupTable.java | 57 + PDFJet/src/main/java/com/pdfjet/Mark.java | 41 + .../src/main/java/com/pdfjet/MaskPattern.java | 30 + .../src/main/java/com/pdfjet/Operation.java | 41 + .../java/com/pdfjet/OptionalContentGroup.java | 117 + PDFJet/src/main/java/com/pdfjet/PDF.java | 1853 ++++++++++++ PDFJet/src/main/java/com/pdfjet/PDFobj.java | 633 ++++ PDFJet/src/main/java/com/pdfjet/PNGImage.java | 948 ++++++ PDFJet/src/main/java/com/pdfjet/Page.java | 1814 ++++++++++++ .../src/main/java/com/pdfjet/PageLayout.java | 44 + PDFJet/src/main/java/com/pdfjet/PageMode.java | 44 + .../src/main/java/com/pdfjet/Paragraph.java | 75 + PDFJet/src/main/java/com/pdfjet/Path.java | 370 +++ .../src/main/java/com/pdfjet/PlainText.java | 180 ++ PDFJet/src/main/java/com/pdfjet/Point.java | 592 ++++ .../src/main/java/com/pdfjet/Polynomial.java | 79 + PDFJet/src/main/java/com/pdfjet/QRCode.java | 409 +++ PDFJet/src/main/java/com/pdfjet/QRMath.java | 64 + PDFJet/src/main/java/com/pdfjet/QRUtil.java | 165 ++ PDFJet/src/main/java/com/pdfjet/RSBlock.java | 76 + .../src/main/java/com/pdfjet/RadioButton.java | 201 ++ PDFJet/src/main/java/com/pdfjet/Round.java | 37 + PDFJet/src/main/java/com/pdfjet/Salsa20.java | 169 ++ PDFJet/src/main/java/com/pdfjet/Segment.java | 42 + PDFJet/src/main/java/com/pdfjet/Single.java | 38 + PDFJet/src/main/java/com/pdfjet/Standard.java | 427 +++ .../main/java/com/pdfjet/StandardFont.java | 176 ++ PDFJet/src/main/java/com/pdfjet/State.java | 87 + .../src/main/java/com/pdfjet/StructElem.java | 51 + PDFJet/src/main/java/com/pdfjet/Symbol.java | 238 ++ PDFJet/src/main/java/com/pdfjet/Table.java | 819 ++++++ PDFJet/src/main/java/com/pdfjet/Tabloid.java | 41 + PDFJet/src/main/java/com/pdfjet/Text.java | 254 ++ .../src/main/java/com/pdfjet/TextBlock.java | 359 +++ PDFJet/src/main/java/com/pdfjet/TextBox.java | 909 ++++++ .../src/main/java/com/pdfjet/TextFrame.java | 263 ++ PDFJet/src/main/java/com/pdfjet/TextLine.java | 690 +++++ .../src/main/java/com/pdfjet/Times_Bold.java | 238 ++ .../java/com/pdfjet/Times_BoldItalic.java | 238 ++ .../main/java/com/pdfjet/Times_Italic.java | 238 ++ .../src/main/java/com/pdfjet/Times_Roman.java | 238 ++ PDFJet/src/main/java/com/pdfjet/Title.java | 70 + .../main/java/com/pdfjet/ZapfDingbats.java | 238 ++ app/build.gradle | 8 +- .../utils/CSVGenerationTask.kt | 6 +- .../utils/PDFGeneratorTask.kt | 243 +- settings.gradle | 2 +- 108 files changed, 26509 insertions(+), 93 deletions(-) create mode 100644 PDFJet/.gitignore create mode 100644 PDFJet/build.gradle create mode 100644 PDFJet/src/main/java/com/pdfjet/A3.java create mode 100644 PDFJet/src/main/java/com/pdfjet/A4.java create mode 100644 PDFJet/src/main/java/com/pdfjet/A5.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Align.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Annotation.java create mode 100644 PDFJet/src/main/java/com/pdfjet/B5.java create mode 100644 PDFJet/src/main/java/com/pdfjet/BMPImage.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Bidi.java create mode 100644 PDFJet/src/main/java/com/pdfjet/BitBuffer.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Bookmark.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Border.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Box.java create mode 100644 PDFJet/src/main/java/com/pdfjet/CalendarMonth.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Cap.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Cell.java create mode 100644 PDFJet/src/main/java/com/pdfjet/CheckBox.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Chunk.java create mode 100644 PDFJet/src/main/java/com/pdfjet/ClockWise.java create mode 100644 PDFJet/src/main/java/com/pdfjet/CodePage.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Color.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Compliance.java create mode 100644 PDFJet/src/main/java/com/pdfjet/CompositeTextLine.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Compressor.java create mode 100644 PDFJet/src/main/java/com/pdfjet/CoreFont.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Courier.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Courier_Bold.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Courier_BoldOblique.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Courier_Oblique.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Decompressor.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Destination.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Dimension.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Drawable.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Effect.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Embed.java create mode 100644 PDFJet/src/main/java/com/pdfjet/EmbeddedFile.java create mode 100644 PDFJet/src/main/java/com/pdfjet/ErrorCorrectLevel.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Executive.java create mode 100644 PDFJet/src/main/java/com/pdfjet/FastFont.java create mode 100644 PDFJet/src/main/java/com/pdfjet/FastFont2.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Field.java create mode 100644 PDFJet/src/main/java/com/pdfjet/FileAttachment.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Font.java create mode 100644 PDFJet/src/main/java/com/pdfjet/FontTable.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Form.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Glyph.java create mode 100644 PDFJet/src/main/java/com/pdfjet/GraphicsState.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Helvetica.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Helvetica_Bold.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Helvetica_BoldOblique.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Helvetica_Oblique.java create mode 100644 PDFJet/src/main/java/com/pdfjet/ICCBlackScaled.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Image.java create mode 100644 PDFJet/src/main/java/com/pdfjet/ImageType.java create mode 100644 PDFJet/src/main/java/com/pdfjet/JPGImage.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Join.java create mode 100644 PDFJet/src/main/java/com/pdfjet/LZWEncode.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Legal.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Letter.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Line.java create mode 100644 PDFJet/src/main/java/com/pdfjet/LookupTable.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Mark.java create mode 100644 PDFJet/src/main/java/com/pdfjet/MaskPattern.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Operation.java create mode 100644 PDFJet/src/main/java/com/pdfjet/OptionalContentGroup.java create mode 100644 PDFJet/src/main/java/com/pdfjet/PDF.java create mode 100644 PDFJet/src/main/java/com/pdfjet/PDFobj.java create mode 100644 PDFJet/src/main/java/com/pdfjet/PNGImage.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Page.java create mode 100644 PDFJet/src/main/java/com/pdfjet/PageLayout.java create mode 100644 PDFJet/src/main/java/com/pdfjet/PageMode.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Paragraph.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Path.java create mode 100644 PDFJet/src/main/java/com/pdfjet/PlainText.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Point.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Polynomial.java create mode 100644 PDFJet/src/main/java/com/pdfjet/QRCode.java create mode 100644 PDFJet/src/main/java/com/pdfjet/QRMath.java create mode 100644 PDFJet/src/main/java/com/pdfjet/QRUtil.java create mode 100644 PDFJet/src/main/java/com/pdfjet/RSBlock.java create mode 100644 PDFJet/src/main/java/com/pdfjet/RadioButton.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Round.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Salsa20.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Segment.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Single.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Standard.java create mode 100644 PDFJet/src/main/java/com/pdfjet/StandardFont.java create mode 100644 PDFJet/src/main/java/com/pdfjet/State.java create mode 100644 PDFJet/src/main/java/com/pdfjet/StructElem.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Symbol.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Table.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Tabloid.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Text.java create mode 100644 PDFJet/src/main/java/com/pdfjet/TextBlock.java create mode 100644 PDFJet/src/main/java/com/pdfjet/TextBox.java create mode 100644 PDFJet/src/main/java/com/pdfjet/TextFrame.java create mode 100644 PDFJet/src/main/java/com/pdfjet/TextLine.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Times_Bold.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Times_BoldItalic.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Times_Italic.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Times_Roman.java create mode 100644 PDFJet/src/main/java/com/pdfjet/Title.java create mode 100644 PDFJet/src/main/java/com/pdfjet/ZapfDingbats.java diff --git a/PDFJet/.gitignore b/PDFJet/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/PDFJet/.gitignore @@ -0,0 +1 @@ +/build diff --git a/PDFJet/build.gradle b/PDFJet/build.gradle new file mode 100644 index 0000000..68bb776 --- /dev/null +++ b/PDFJet/build.gradle @@ -0,0 +1,8 @@ +apply plugin: 'java-library' + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) +} + +sourceCompatibility = "7" +targetCompatibility = "7" diff --git a/PDFJet/src/main/java/com/pdfjet/A3.java b/PDFJet/src/main/java/com/pdfjet/A3.java new file mode 100644 index 0000000..96fb923 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/A3.java @@ -0,0 +1,41 @@ +/** + * A3.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + + +/** + * Used to specify PDF page with size A3. + * For more information about the page size classes - A3, A4, A5, B5, Executive, Letter, Legal and Tabloid - see the Page class. + * + */ +public class A3 { + public static final float[] PORTRAIT = new float[] {842.0f, 1191.0f}; + public static final float[] LANDSCAPE = new float[] {1191.0f, 842.0f}; +} diff --git a/PDFJet/src/main/java/com/pdfjet/A4.java b/PDFJet/src/main/java/com/pdfjet/A4.java new file mode 100644 index 0000000..3e2a1b8 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/A4.java @@ -0,0 +1,41 @@ +/** + * A4.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + + +/** + * Used to specify PDF page with size A4. + * For more information about the page size classes - A3, A4, A5, B5, Executive, Letter, Legal and Tabloid - see the Page class. + * + */ +public class A4 { + public static final float[] PORTRAIT = new float[] {595.0f, 842.0f}; + public static final float[] LANDSCAPE = new float[] {842.0f, 595.0f}; +} diff --git a/PDFJet/src/main/java/com/pdfjet/A5.java b/PDFJet/src/main/java/com/pdfjet/A5.java new file mode 100644 index 0000000..6a2f880 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/A5.java @@ -0,0 +1,42 @@ +/** + * A5.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + + +/** + * Used to specify PDF page with size A5. + * For more information about the page size classes - A3, A4, A5, B5, Executive, Letter, Legal and Tabloid - see the Page class. + * + */ +public class A5 { + public static final float[] PORTRAIT = new float[] {420.0f, 595.0f}; + public static final float[] LANDSCAPE = new float[] {595.0f, 420.0f}; +} + diff --git a/PDFJet/src/main/java/com/pdfjet/Align.java b/PDFJet/src/main/java/com/pdfjet/Align.java new file mode 100644 index 0000000..81893df --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Align.java @@ -0,0 +1,47 @@ +/** + * Align.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + + +/** + * Used to specify the text alignment in paragraphs. + * See the Paragraph class for more details. + * + * + */ +public class Align { + public static final int LEFT = 0x00000000; + public static final int CENTER = 0x00100000; + public static final int RIGHT = 0x00200000; + public static final int JUSTIFY = 0x00300000; + + public static final int TOP = 0x00400000; + public static final int BOTTOM = 0x00500000; +} diff --git a/PDFJet/src/main/java/com/pdfjet/Annotation.java b/PDFJet/src/main/java/com/pdfjet/Annotation.java new file mode 100644 index 0000000..757104d --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Annotation.java @@ -0,0 +1,87 @@ +/** + * Annotation.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + + +/** + * Used to create PDF annotation objects. + * + * + */ +class Annotation { + + protected int objNumber; + protected String uri; + protected String key; + protected float x1; + protected float y1; + protected float x2; + protected float y2; + + protected String language = null; + protected String altDescription = null; + protected String actualText = null; + + protected FileAttachment fileAttachment = null; + + + /** + * This class is used to create annotation objects. + * + * @param uri the URI string. + * @param key the destination name. + * @param x1 the x coordinate of the top left corner. + * @param y1 the y coordinate of the top left corner. + * @param x2 the x coordinate of the bottom right corner. + * @param y2 the y coordinate of the bottom right corner. + * + */ + protected Annotation( + String uri, + String key, + float x1, + float y1, + float x2, + float y2, + String language, + String altDescription, + String actualText) { + this.uri = uri; + this.key = key; + this.x1 = x1; + this.y1 = y1; + this.x2 = x2; + this.y2 = y2; + this.language = language; + this.altDescription = (altDescription == null) ? uri : altDescription; + this.actualText = (actualText == null) ? uri : actualText; + } + +} diff --git a/PDFJet/src/main/java/com/pdfjet/B5.java b/PDFJet/src/main/java/com/pdfjet/B5.java new file mode 100644 index 0000000..785e6d2 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/B5.java @@ -0,0 +1,41 @@ +/** + * B5.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + + +/** + * Used to specify PDF page with size B5. + * For more information about the page size classes - A3, A4, A5, B5, Executive, Letter, Legal and Tabloid - see the Page class. + * + */ +public class B5 { + public static final float[] PORTRAIT = new float[] {516.0f, 729.0f}; + public static final float[] LANDSCAPE = new float[] {729.0f, 516.0f}; +} diff --git a/PDFJet/src/main/java/com/pdfjet/BMPImage.java b/PDFJet/src/main/java/com/pdfjet/BMPImage.java new file mode 100644 index 0000000..a23108d --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/BMPImage.java @@ -0,0 +1,282 @@ +/** + * + * Copyright (c) 2018, Jonas Krogsboll +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + + +import java.io.ByteArrayOutputStream; +import java.util.zip.Deflater; +import java.util.zip.DeflaterOutputStream; + + +class BMPImage { + + int w = 0; // Image width in pixels + int h = 0; // Image height in pixels + + byte[] image; // The reconstructed image data + byte[] deflated; // The deflated reconstructed image data + + private int bpp; + private byte palette[][]; + private boolean r5g6b5; // If 16 bit image two encodings can occur + + private static final int m10000000 = 0x80; + private static final int m01000000 = 0x40; + private static final int m00100000 = 0x20; + private static final int m00010000 = 0x10; + private static final int m00001000 = 0x08; + private static final int m00000100 = 0x04; + private static final int m00000010 = 0x02; + private static final int m00000001 = 0x01; + private static final int m11110000 = 0xF0; + private static final int m00001111 = 0x0F; + + /* Tested with images created from GIMP */ + public BMPImage( java.io.InputStream is ) throws Exception { + palette = null; + byte bm[] = getBytes(is, 2); + // From Wikipedia + if((bm[0] == 'B' && bm[1] == 'M')|| + (bm[0] == 'B' && bm[1] == 'A')|| + (bm[0] == 'C' && bm[1] == 'I')|| + (bm[0] == 'C' && bm[1] == 'P')|| + (bm[0] == 'I' && bm[1] == 'C')|| + (bm[0] == 'P' && bm[1] == 'T')) { + skipNBytes(is, 8); + int offset = readSignedInt(is); + int sizeOfHeader = readSignedInt(is); + w = readSignedInt(is); + h = readSignedInt(is); + skipNBytes(is, 2); + bpp = read2BytesLE(is); + int compression = readSignedInt(is); + if (bpp > 8) { + r5g6b5 = (compression == 3); + skipNBytes(is, 20); + if (offset > 54) { + skipNBytes(is, offset-54); + } + } + else { + skipNBytes(is, 12); + int numpalcol = readSignedInt(is); + if (numpalcol == 0) { + numpalcol = (int) Math.pow(2, bpp); + } + skipNBytes(is, 4); + parsePalette(is, numpalcol); + } + parseData(is); + } + else { + throw new Exception("BMP data could not be parsed!"); + } + + } + + private void parseData(java.io.InputStream is) throws Exception { + // rowsize is 4 * ceil (bpp*width/32.0) + image = new byte[w * h * 3]; + + int rowsize = 4 * (int)Math.ceil(bpp*w/32.0); // 4 byte alignment + byte row[]; + int index; + try { + for (int i = 0; i < h; i++) { + row = getBytes(is, rowsize); + switch (bpp) { + case 1: row = bit1to8(row, w); break; // opslag i palette + case 4: row = bit4to8(row, w); break; // opslag i palette + case 8: break; // opslag i palette + case 16: + if (r5g6b5) + row = bit16to24(row, w); // 5,6,5 bit + else + row = bit16to24b(row, w); + break; + case 24: break; // bytes are correct + case 32: row = bit32to24(row, w); break; + default: + throw new Exception( + "Can only parse 1 bit, 4bit, 8bit, 16bit, 24bit and 32bit images"); + } + + index = w*(h-i-1)*3; + if (palette != null) { // indexed + for (int j = 0; j < w; j++) { + image[index++] = palette[(row[j]<0)?row[j]+256:row[j]][2]; + image[index++] = palette[(row[j]<0)?row[j]+256:row[j]][1]; + image[index++] = palette[(row[j]<0)?row[j]+256:row[j]][0]; + } + } else { // not indexed + for (int j = 0; j < w*3; j+=3) { + image[index++] = row[j+2]; + image[index++] = row[j+1]; + image[index++] = row[j]; + } + } + } + } catch (ArrayIndexOutOfBoundsException aiobe) { + throw new Exception ("BMP parse error: imagedata not correct"); + } + + ByteArrayOutputStream data2 = new ByteArrayOutputStream(32768); + DeflaterOutputStream dos = new DeflaterOutputStream(data2, new Deflater()); + dos.write(image, 0, image.length); + dos.finish(); + deflated = data2.toByteArray(); + } + + // 5 + 6 + 5 in B G R format 2 bytes to 3 bytes + private static byte[] bit16to24(byte[] row, int width) { + byte[] ret = new byte[width * 3]; + int j = 0; + for (int i = 0; i < width*2; i+=2) { + ret[j++] = (byte)((row[i] & 0x1F)<<3); + ret[j++] = (byte)(((row[i+1] & 0x07)<<5)+((row[i] & 0xE0)>>3)); + ret[j++] = (byte)((row[i+1] & 0xF8)); + } + return ret; + } + + // 5 + 5 + 5 in B G R format 2 bytes to 3 bytes + private static byte[] bit16to24b(byte[] row, int width) { + byte[] ret = new byte[width * 3]; + int j = 0; + for (int i = 0; i < width*2; i+=2) { + ret[j++] = (byte)((row[i] & 0x1F)<<3); + ret[j++] = (byte)(((row[i+1] & 0x03)<<6)+((row[i] & 0xE0)>>2)); + ret[j++] = (byte)((row[i+1] & 0x7C)<<1); + } + return ret; + } + + /* alpha first? */ + private static byte[] bit32to24(byte[] row, int width) { + byte[] ret = new byte[width * 3]; + int j = 0; + for (int i = 0; i < width*4; i+=4) { + ret[j++] = row[i+1]; + ret[j++] = row[i+2]; + ret[j++] = row[i+3]; + } + return ret; + } + + private static byte[] bit4to8(byte[] row, int width) { + byte[] ret = new byte[width]; + for(int i = 0; i < width; i++) { + if (i % 2 == 0) { + ret[i] =(byte) ((row[i/2] & m11110000)>>4); + } + else { + ret[i] =(byte) ((row[i/2] & m00001111)); + } + } + return ret; + } + + private static byte[] bit1to8(byte[] row, int width) { + byte[] ret = new byte[width]; + for(int i = 0; i < width; i++) { + switch (i % 8) { + case 0: ret[i] = (byte) ((row[i/8] & m10000000)>>7); break; + case 1: ret[i] = (byte) ((row[i/8] & m01000000)>>6); break; + case 2: ret[i] = (byte) ((row[i/8] & m00100000)>>5); break; + case 3: ret[i] = (byte) ((row[i/8] & m00010000)>>4); break; + case 4: ret[i] = (byte) ((row[i/8] & m00001000)>>3); break; + case 5: ret[i] = (byte) ((row[i/8] & m00000100)>>2); break; + case 6: ret[i] = (byte) ((row[i/8] & m00000010)>>1); break; + case 7: ret[i] = (byte) ((row[i/8] & m00000001)); break; + } + } + return ret; + } + + private void parsePalette(java.io.InputStream is, int size) + throws Exception { + palette = new byte[size][]; + for (int i = 0; i < size; i++) { + palette[i] = getBytes(is, 4); + } + } + + private void skipNBytes(java.io.InputStream inputStream, int n) { + try { + getBytes(inputStream, n); + } + catch (Exception e) { + e.printStackTrace(); + } + } + + private byte[] getBytes(java.io.InputStream inputStream, int length) + throws Exception { + byte[] buf = new byte[length]; + inputStream.read(buf, 0, buf.length); + return buf; + } + + private int read2BytesLE(java.io.InputStream inputStream) + throws Exception { + byte[] buf = getBytes(inputStream, 2); + int val = 0; + val |= buf[ 1 ] & 0xff; + val <<= 8; + val |= buf[ 0 ] & 0xff; + return val; + } + + private int readSignedInt(java.io.InputStream inputStream) + throws Exception { + byte[] buf = getBytes(inputStream, 4); + long val = 0L; + val |= buf[ 3 ] & 0xff; + val <<= 8; + val |= buf[ 2 ] & 0xff; + val <<= 8; + val |= buf[ 1 ] & 0xff; + val <<= 8; + val |= buf[ 0 ] & 0xff; + return (int)val; + } + + public int getWidth() { + return this.w; + } + + public int getHeight() { + return this.h; + } + + public byte[] getData() { + return this.deflated; + } + +} diff --git a/PDFJet/src/main/java/com/pdfjet/Bidi.java b/PDFJet/src/main/java/com/pdfjet/Bidi.java new file mode 100644 index 0000000..b085bf7 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Bidi.java @@ -0,0 +1,235 @@ +/** + * Bidi.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + +import java.util.*; + + +/** + * Provides BIDI processing for Arabic and Hebrew. + * + * Please see Example_27. + */ +public class Bidi { + +/* +General,Isolated,End,Middle,Beginning +*/ +private static char[] forms = new char[] { +'\u0623','\uFE83','\uFE84','\u0623','\u0623', +'\u0628','\uFE8F','\uFE90','\uFE92','\uFE91', +'\u062A','\uFE95','\uFE96','\uFE98','\uFE97', +'\u062B','\uFE99','\uFE9A','\uFE9C','\uFE9B', +'\u062C','\uFE9D','\uFE9E','\uFEA0','\uFE9F', +'\u062D','\uFEA1','\uFEA2','\uFEA4','\uFEA3', +'\u062E','\uFEA5','\uFEA6','\uFEA8','\uFEA7', +'\u062F','\uFEA9','\uFEAA','\u062F','\u062F', +'\u0630','\uFEAB','\uFEAC','\u0630','\u0630', +'\u0631','\uFEAD','\uFEAE','\u0631','\u0631', +'\u0632','\uFEAF','\uFEB0','\u0632','\u0632', +'\u0633','\uFEB1','\uFEB2','\uFEB4','\uFEB3', +'\u0634','\uFEB5','\uFEB6','\uFEB8','\uFEB7', +'\u0635','\uFEB9','\uFEBA','\uFEBC','\uFEBB', +'\u0636','\uFEBD','\uFEBE','\uFEC0','\uFEBF', +'\u0637','\uFEC1','\uFEC2','\uFEC4','\uFEC3', +'\u0638','\uFEC5','\uFEC6','\uFEC8','\uFEC7', +'\u0639','\uFEC9','\uFECA','\uFECC','\uFECB', +'\u063A','\uFECD','\uFECE','\uFED0','\uFECF', +'\u0641','\uFED1','\uFED2','\uFED4','\uFED3', +'\u0642','\uFED5','\uFED6','\uFED8','\uFED7', +'\u0643','\uFED9','\uFEDA','\uFEDC','\uFEDB', +'\u0644','\uFEDD','\uFEDE','\uFEE0','\uFEDF', +'\u0645','\uFEE1','\uFEE2','\uFEE4','\uFEE3', +'\u0646','\uFEE5','\uFEE6','\uFEE8','\uFEE7', +'\u0647','\uFEE9','\uFEEA','\uFEEC','\uFEEB', +'\u0648','\uFEED','\uFEEE','\u0648','\u0648', +'\u064A','\uFEF1','\uFEF2','\uFEF4','\uFEF3', +'\u0622','\uFE81','\uFE82','\u0622','\u0622', +'\u0629','\uFE93','\uFE94','\u0629','\u0629', +'\u0649','\uFEEF','\uFEF0','\u0649','\u0649', +}; + + + private static boolean isArabicLetter(char ch) { + for (int i = 0; i < forms.length; i += 5) { + if (ch == forms[i]) { + return true; + } + } + return false; + } + + + /** + * Reorders the string so that Arabic and Hebrew text flows from right + * to left while numbers and Latin text flows from left to right. + * + * @param str the input string. + * @return the reordered string. + */ + public static String reorderVisually(String str) { + StringBuilder buf1 = new StringBuilder(); + StringBuilder buf2 = new StringBuilder(); + boolean right_to_left = true; + for (int i = 0; i < str.length(); i++) { + char ch = str.charAt(i); + if (ch == '\u200E') { + // LRM U+200E LEFT-TO-RIGHT MARK Left-to-right zero-width character + right_to_left = false; + continue; + } + if (ch == '\u200F' || ch == '\u061C') { + // RLM U+200F RIGHT-TO-LEFT MARK Right-to-left zero-width non-Arabic character + // ALM U+061C ARABIC LETTER MARK Right-to-left zero-width Arabic character + right_to_left = true; + continue; + } + if (isArabic(ch) || + isHebrew(ch) || + ch == '«' || ch == '»' || + ch == '(' || ch == ')' || + ch == '[' || ch == ']') { + right_to_left = true; + if (buf2.length() > 0) { + buf1.append(process(buf2)); + buf2.setLength(0); + } + if (ch == '«') { + buf1.append('»'); + } + else if (ch == '»') { + buf1.append('«'); + } + else if (ch == '(') { + buf1.append(')'); + } + else if (ch == ')') { + buf1.append('('); + } + else if (ch == '[') { + buf1.append(']'); + } + else if (ch == ']') { + buf1.append('['); + } + else { + buf1.append(ch); + } + } + else if (isAlphaNumeric(ch)) { + right_to_left = false; + buf2.append(ch); + } + else { + if (right_to_left) { + buf1.append(ch); + } + else { + buf2.append(ch); + } + } + } + if (buf2.length() > 0) { + buf1.append(process(buf2)); + } + + StringBuilder buf3 = new StringBuilder(); + for (int i = (buf1.length() - 1); i >= 0; i--) { + char ch = buf1.charAt(i); + if (isArabicLetter(ch)) { + char prev_ch = (i > 0) ? buf1.charAt(i - 1) : '\u0000'; + char next_ch = (i < (buf1.length() - 1)) ? buf1.charAt(i + 1) : '\u0000'; + for (int j = 0; j < forms.length; j += 5) { + if (ch == forms[j]) { + if (!isArabicLetter(prev_ch) && !isArabicLetter(next_ch)) { + buf3.append(forms[j + 1]); // Isolated + } + else if (isArabicLetter(prev_ch) && !isArabicLetter(next_ch)) { + buf3.append(forms[j + 2]); // End + } + else if (isArabicLetter(prev_ch) && isArabicLetter(next_ch)) { + buf3.append(forms[j + 3]); // Middle + } + else if (!isArabicLetter(prev_ch) && isArabicLetter(next_ch)) { + buf3.append(forms[j + 4]); // Beginning + } + } + } + } + else { + buf3.append(ch); + } + } + return buf3.toString(); + } + + + public static boolean isArabic(char ch) { + return (ch >= 0x600 && ch <= 0x6FF); + } + + + private static boolean isHebrew(char ch) { + return (ch >= 0x0591 && ch <= 0x05F4); + } + + + private static boolean isAlphaNumeric(char ch) { + if (ch >= '0' && ch <= '9') { + return true; + } + if (ch >= 'a' && ch <= 'z') { + return true; + } + if (ch >= 'A' && ch <= 'Z') { + return true; + } + return false; + } + + + private static StringBuilder process(StringBuilder buf) { + StringBuilder buf1 = buf.reverse(); + StringBuilder buf2 = new StringBuilder(); + StringBuilder buf3 = new StringBuilder(); + for (int i = 0; i < buf1.length(); i++) { + char ch = buf1.charAt(i); + if (ch == ' ' || ch == ',' || ch == '.' || ch == '-') { + buf2.append(ch); + continue; + } + buf3.append(buf1.substring(i)); + buf3.append(buf2.reverse()); + break; + } + return buf3; + } + +} diff --git a/PDFJet/src/main/java/com/pdfjet/BitBuffer.java b/PDFJet/src/main/java/com/pdfjet/BitBuffer.java new file mode 100644 index 0000000..f050e19 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/BitBuffer.java @@ -0,0 +1,62 @@ +/** + * +Copyright (c) 2009 Kazuhiko Arase + +URL: http://www.d-project.com/ + +Licensed under the MIT license: + http://www.opensource.org/licenses/mit-license.php + +The word "QR Code" is registered trademark of +DENSO WAVE INCORPORATED + http://www.denso-wave.com/qrcode/faqpatent-e.html +*/ + +package com.pdfjet; + + +/** + * BitBuffer + * @author Kazuhiko Arase + */ +class BitBuffer { + + private byte[] buffer; + private int length; + private int increments = 32; + + + public BitBuffer() { + buffer = new byte[increments]; + length = 0; + } + + public byte[] getBuffer() { + return buffer; + } + + public int getLengthInBits() { + return length; + } + + public void put(int num, int length) { + for (int i = 0; i < length; i++) { + put(((num >>> (length - i - 1)) & 1) == 1); + } + } + + public void put(boolean bit) { + if (length == buffer.length * 8) { + byte[] newBuffer = new byte[buffer.length + increments]; + System.arraycopy(buffer, 0, newBuffer, 0, buffer.length); + buffer = newBuffer; + } + + if (bit) { + buffer[length / 8] |= (0x80 >>> (length % 8)); + } + + length++; + } + +} diff --git a/PDFJet/src/main/java/com/pdfjet/Bookmark.java b/PDFJet/src/main/java/com/pdfjet/Bookmark.java new file mode 100644 index 0000000..e239c29 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Bookmark.java @@ -0,0 +1,200 @@ +/** + * Bookmark.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + +import java.lang.*; +import java.util.*; + +/** + * Please see Example_51 and Example_52 + * + */ +public class Bookmark { + + private int destNumber = 0; + private Page page = null; + private float y = 0f; + private String key = null; + private String title = null; + private Bookmark parent = null; + private Bookmark prev = null; + private Bookmark next = null; + private List children = null; + private Destination dest = null; + + protected int objNumber = 0; + protected String prefix = null; + + + public Bookmark(PDF pdf) { + pdf.toc = this; + } + + + private Bookmark(Page page, float y, String key, String title) { + this.page = page; + this.y = y; + this.key = key; + this.title = title; + } + + + public Bookmark addBookmark(Page page, Title title) { + return addBookmark(page, title.text.getY(), title.text.getText()); + } + + + public Bookmark addBookmark(Page page, float y, String title) { + Bookmark bm = this; + while (bm.parent != null) { + bm = bm.getParent(); + } + String key = bm.next(); + + Bookmark bookmark = new Bookmark(page, y, key, title.replaceAll("\\s+"," ")); + bookmark.parent = this; + bookmark.dest = page.addDestination(key, y); + if (children == null) { + children = new ArrayList(); + } + else { + bookmark.prev = children.get(children.size() - 1); + children.get(children.size() - 1).next = bookmark; + } + children.add(bookmark); + return bookmark; + } + + + public String getDestKey() { + return this.key; + } + + + public String getTitle() { + return this.title; + } + + + public Bookmark getParent() { + return this.parent; + } + + + public Bookmark autoNumber(TextLine text) { + Bookmark bm = getPrevBookmark(); + if (bm == null) { + bm = getParent(); + if (bm.prefix == null) { + prefix = "1"; + } + else { + prefix = bm.prefix + ".1"; + } + } + else { + if (bm.prefix == null) { + if (bm.getParent().prefix == null) { + prefix = "1"; + } + else { + prefix = bm.getParent().prefix + ".1"; + } + } + else { + int index = bm.prefix.lastIndexOf('.'); + if (index == -1) { + prefix = String.valueOf(Integer.valueOf(bm.prefix) + 1); + } + else { + prefix = bm.prefix.substring(0, index) + "."; + prefix += String.valueOf(Integer.valueOf(bm.prefix.substring(index + 1)) + 1); + } + } + } + text.setText(prefix); + title = prefix + " " + title; + return this; + } + + + protected List toArrayList() { + int objNumber = 0; + List list = new ArrayList(); + Queue queue = new LinkedList(); + queue.add(this); + while (!queue.isEmpty()) { + Bookmark bm = queue.poll(); + bm.objNumber = objNumber++; + list.add(bm); + if (bm.getChildren() != null) { + queue.addAll(bm.getChildren()); + } + } + return list; + } + + + protected List getChildren() { + return this.children; + } + + + protected Bookmark getPrevBookmark() { + return this.prev; + } + + + protected Bookmark getNextBookmark() { + return this.next; + } + + + protected Bookmark getFirstChild() { + return this.children.get(0); + } + + + protected Bookmark getLastChild() { + return children.get(children.size() - 1); + } + + + protected Destination getDestination() { + return this.dest; + } + + + private String next() { + ++destNumber; + return "dest#" + String.valueOf(destNumber); + } + +} // End of Bookmark.java diff --git a/PDFJet/src/main/java/com/pdfjet/Border.java b/PDFJet/src/main/java/com/pdfjet/Border.java new file mode 100644 index 0000000..7c14f35 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Border.java @@ -0,0 +1,43 @@ +/** + * Border.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + + +/** + * Used to control the visibility of cell borders. + * See the Cell class for more information. + * + */ +public class Border { + public static final int TOP = 0x00010000; + public static final int BOTTOM = 0x00020000; + public static final int LEFT = 0x00040000; + public static final int RIGHT = 0x00080000; +} diff --git a/PDFJet/src/main/java/com/pdfjet/Box.java b/PDFJet/src/main/java/com/pdfjet/Box.java new file mode 100644 index 0000000..71b6fee --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Box.java @@ -0,0 +1,369 @@ +/** + * Box.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + + +/** + * Used to create rectangular boxes on a page. + * Also used to for layout purposes. See the placeIn method in the Image and TextLine classes. + * + */ +public class Box implements Drawable { + + protected float x; + protected float y; + + private float w; + private float h; + + private int color = Color.black; + + private float width = 0.3f; + private String pattern = "[] 0"; + private boolean fill_shape = false; + + private String language = null; + private String altDescription = Single.space; + private String actualText = Single.space; + + protected String uri = null; + protected String key = null; + + + /** + * The default constructor. + * + */ + public Box() { + } + + + /** + * Creates a box object. + * + * @param x the x coordinate of the top left corner of this box when drawn on the page. + * @param y the y coordinate of the top left corner of this box when drawn on the page. + * @param w the width of this box. + * @param h the height of this box. + */ + public Box(double x, double y, double w, double h) { + this.x = (float) x; + this.y = (float) y; + this.w = (float) w; + this.h = (float) h; + } + + + /** + * Creates a box object. + * + * @param x the x coordinate of the top left corner of this box when drawn on the page. + * @param y the y coordinate of the top left corner of this box when drawn on the page. + * @param w the width of this box. + * @param h the height of this box. + */ + public Box(float x, float y, float w, float h) { + this.x = x; + this.y = y; + this.w = w; + this.h = h; + } + + + /** + * Sets the position of this box on the page. + * + * @param x the x coordinate of the top left corner of this box when drawn on the page. + * @param y the y coordinate of the top left corner of this box when drawn on the page. + */ + public Box setPosition(double x, double y) { + return setLocation((float) x, (float) y); + } + + + /** + * Sets the position of this box on the page. + * + * @param x the x coordinate of the top left corner of this box when drawn on the page. + * @param y the y coordinate of the top left corner of this box when drawn on the page. + */ + public Box setPosition(float x, float y) { + return setLocation(x, y); + } + + + /** + * Sets the location of this box on the page. + * + * @param x the x coordinate of the top left corner of this box when drawn on the page. + * @param y the y coordinate of the top left corner of this box when drawn on the page. + */ + public Box setLocation(float x, float y) { + this.x = x; + this.y = y; + return this; + } + + + /** + * Sets the size of this box. + * + * @param w the width of this box. + * @param h the height of this box. + */ + public void setSize(double w, double h) { + this.w = (float) w; + this.h = (float) h; + } + + + /** + * Sets the size of this box. + * + * @param w the width of this box. + * @param h the height of this box. + */ + public void setSize(float w, float h) { + this.w = w; + this.h = h; + } + + + /** + * Sets the color for this box. + * + * @param color the color specified as an integer. + */ + public void setColor(int color) { + this.color = color; + } + + + /** + * Sets the width of this line. + * + * @param width the width. + */ + public void setLineWidth(double width) { + this.width = (float) width; + } + + + /** + * Sets the width of this line. + * + * @param width the width. + */ + public void setLineWidth(float width) { + this.width = width; + } + + + /** + * Sets the URI for the "click box" action. + * + * @param uri the URI + */ + public void setURIAction(String uri) { + this.uri = uri; + } + + + /** + * Sets the destination key for the action. + * + * @param key the destination name. + */ + public void setGoToAction(String key) { + this.key = key; + } + + + /** + * Sets the alternate description of this box. + * + * @param altDescription the alternate description of the box. + * @return this Box. + */ + public Box setAltDescription(String altDescription) { + this.altDescription = altDescription; + return this; + } + + + /** + * Sets the actual text for this box. + * + * @param actualText the actual text for the box. + * @return this Box. + */ + public Box setActualText(String actualText) { + this.actualText = actualText; + return this; + } + + + /** + * The line dash pattern controls the pattern of dashes and gaps used to stroke paths. + * It is specified by a dash array and a dash phase. + * The elements of the dash array are positive numbers that specify the lengths of + * alternating dashes and gaps. + * The dash phase specifies the distance into the dash pattern at which to start the dash. + * The elements of both the dash array and the dash phase are expressed in user space units. + *
+     *  Examples of line dash patterns:
+     *
+     *      "[Array] Phase"     Appearance          Description
+     *      _______________     _________________   ____________________________________
+     *
+     *      "[] 0"              -----------------   Solid line
+     *      "[3] 0"             ---   ---   ---     3 units on, 3 units off, ...
+     *      "[2] 1"             -  --  --  --  --   1 on, 2 off, 2 on, 2 off, ...
+     *      "[2 1] 0"           -- -- -- -- -- --   2 on, 1 off, 2 on, 1 off, ...
+     *      "[3 5] 6"             ---     ---       2 off, 3 on, 5 off, 3 on, 5 off, ...
+     *      "[2 3] 11"          -   --   --   --    1 on, 3 off, 2 on, 3 off, 2 on, ...
+     *  
+ * + * @param pattern the line dash pattern. + */ + public void setPattern(String pattern) { + this.pattern = pattern; + } + + + /** + * Sets the private fill_shape variable. + * If the value of fill_shape is true - the box is filled with the current brush color. + * + * @param fill_shape the value used to set the private fill_shape variable. + */ + public void setFillShape(boolean fill_shape) { + this.fill_shape = fill_shape; + } + + + /** + * Places this box in the another box. + * + * @param box the other box. + * @param x_offset the x offset from the top left corner of the box. + * @param y_offset the y offset from the top left corner of the box. + */ + public void placeIn( + Box box, + double x_offset, + double y_offset) throws Exception { + placeIn(box, (float) x_offset, (float) y_offset); + } + + + /** + * Places this box in the another box. + * + * @param box the other box. + * @param x_offset the x offset from the top left corner of the box. + * @param y_offset the y offset from the top left corner of the box. + */ + public void placeIn( + Box box, + float x_offset, + float y_offset) throws Exception { + this.x = box.x + x_offset; + this.y = box.y + y_offset; + } + + + /** + * Scales this box by the spacified factor. + * + * @param factor the factor used to scale the box. + */ + public void scaleBy(double factor) throws Exception { + scaleBy((float) factor); + } + + + /** + * Scales this box by the spacified factor. + * + * @param factor the factor used to scale the box. + */ + public void scaleBy(float factor) throws Exception { + this.x *= factor; + this.y *= factor; + } + + + /** + * Draws this box on the specified page. + * + * @param page the page to draw this box on. + * @return x and y coordinates of the bottom right corner of this component. + * @throws Exception + */ + public float[] drawOn(Page page) throws Exception { + page.addBMC(StructElem.SPAN, language, altDescription, actualText); + page.setPenWidth(width); + page.setLinePattern(pattern); + if (fill_shape) { + page.setBrushColor(color); + } + else { + page.setPenColor(color); + } + page.moveTo(x, y); + page.lineTo(x + w, y); + page.lineTo(x + w, y + h); + page.lineTo(x, y + h); + if (fill_shape) { + page.fillPath(); + } + else { + page.closePath(); + } + page.addEMC(); + + if (uri != null || key != null) { + page.addAnnotation(new Annotation( + uri, + key, // The destination name + x, + page.height - y, + x + w, + page.height - (y + h), + language, + altDescription, + actualText)); + } + + return new float[] {x + w, y + h}; + } + +} // End of Box.java diff --git a/PDFJet/src/main/java/com/pdfjet/CalendarMonth.java b/PDFJet/src/main/java/com/pdfjet/CalendarMonth.java new file mode 100644 index 0000000..cb28fc5 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/CalendarMonth.java @@ -0,0 +1,142 @@ +/** + * CalendarMonth.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +package com.pdfjet; + + +import java.lang.*; +import java.io.*; +import java.util.*; + + +public class CalendarMonth { + + Font f1 = null; + Font f2 = null; + + float x1 = 75f; + float y1 = 75f; + float dx = 23f; + float dy = 20f; + + String[] days = {"Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"}; + // DAY_OF_WEEK 1 2 3 4 5 6 7 + + int days_in_month; + int day_of_week; + + + public CalendarMonth(Font f1, Font f2, int year, int month) { + this.f1 = f1; + this.f2 = f2; + days_in_month = getDaysInMonth(year, month - 1); + Calendar calendar = Calendar.getInstance(); + calendar.set(Calendar.YEAR, year); + calendar.set(Calendar.MONTH, month - 1); + calendar.set(Calendar.DAY_OF_MONTH, 1); + day_of_week = calendar.get(Calendar.DAY_OF_WEEK); + System.out.println(day_of_week); + } + + + public void setHeadFont(Font font) { + this.f1 = font; + } + + + public void setBodyFont(Font font) { + this.f2 = font; + } + + + public void setLocation(float x, float y) { + this.x1 = x; + this.y1 = y; + } + + + public void setCellWidth(float width) { + this.dx = width; + } + + + public void setCellHeight(float height) { + this.dy = height; + } + + + public void drawOn(Page page) throws Exception { + for (int row = 0; row < 7; row++) { + for (int col = 0; col < 7; col++) { + if (row == 0) { + float offset = (dx - f1.stringWidth(days[col])) / 2; + TextLine text = new TextLine(f1, days[col]); + text.setLocation(x1 + col*dx + offset, x1 + row*dy); + text.drawOn(page); + // Draw the line separating the title from the dates. + Line line = new Line( + x1, + y1 + dx/4, + x1 + 7*dx, + y1 + dx/4); + line.setWidth(0.5f); + line.drawOn(page); + } + else { + int day_of_month = ((7*row + col) - 6) - (day_of_week - 1); + if (day_of_month > 0 && day_of_month <= days_in_month) { + String s1 = String.valueOf(day_of_month); + float offset = (dx - f2.stringWidth(s1)) / 2; + TextLine text = new TextLine(f2, s1); + text.setLocation(x1 + col*dx + offset, y1 + row*dy); + text.drawOn(page); + + page.setPenWidth(1.5f); + page.setPenColor(Color.blue); + page.drawEllipse(x1 + col*dx + dx/2, y1 + row*dy - dy/5, 8f, 8f); + } + } + } + } + } + + + private boolean isLeapYear(int year) { + return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0; + } + + + private int getDaysInMonth( + int year, + int month) { + int daysInFebruary = isLeapYear(year) ? 29 : 28; + int[] daysInMonth = {31, daysInFebruary, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + return daysInMonth[month]; + } + +} diff --git a/PDFJet/src/main/java/com/pdfjet/Cap.java b/PDFJet/src/main/java/com/pdfjet/Cap.java new file mode 100644 index 0000000..866dbbe --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Cap.java @@ -0,0 +1,42 @@ +/** + * Cap.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + + +/** + * Used to specify the cap style of a line. + * See the Line class for more information. + * + */ +public class Cap { + public static final int BUTT = 0; + public static final int ROUND = 1; + public static final int PROJECTING_SQUARE = 2; +} diff --git a/PDFJet/src/main/java/com/pdfjet/Cell.java b/PDFJet/src/main/java/com/pdfjet/Cell.java new file mode 100644 index 0000000..17f9fa3 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Cell.java @@ -0,0 +1,900 @@ +/** + * Cell.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + +import java.util.*; + + +/** + * Used to create table cell objects. + * See the Table class for more information. + * + */ +public class Cell { + + protected Font font; + protected Font fallbackFont; + protected String text; + protected Image image; + protected Point point; + protected CompositeTextLine compositeTextLine; + protected boolean ignoreImageHeight = false; + + protected float width = 70f; + protected float top_padding = 2f; + protected float bottom_padding = 2f; + protected float left_padding = 2f; + protected float right_padding = 2f; + protected float lineWidth = 0.2f; + + private int background = -1; + private int pen = Color.black; + private int brush = Color.black; + + // Cell properties + // Colspan: + // bits 0 to 15 + // Border: + // bit 16 - top + // bit 17 - bottom + // bit 18 - left + // bit 19 - right + // Text Alignment: + // bit 20 + // bit 21 + // Text Decoration: + // bit 22 - underline + // bit 23 - strikeout + // Future use: + // bits 24 to 31 + private int properties = 0x000F0001; + private String uri; + + private int valign = Align.TOP; + + + /** + * Creates a cell object and sets the font. + * + * @param font the font. + */ + public Cell(Font font) { + this.font = font; + } + + + /** + * Creates a cell object and sets the font and the cell text. + * + * @param font the font. + * @param text the text. + */ + public Cell(Font font, String text) { + this.font = font; + this.text = text; + } + + + /** + * Creates a cell object and sets the font, fallback font and the cell text. + * + * @param font the font. + * @param fallbackFont the fallback font. + * @param text the text. + */ + public Cell(Font font, Font fallbackFont, String text) { + this.font = font; + this.fallbackFont = fallbackFont; + this.text = text; + } + + + /** + * Sets the font for this cell. + * + * @param font the font. + */ + public void setFont(Font font) { + this.font = font; + } + + + /** + * Sets the fallback font for this cell. + * + * @param fallbackFont the fallback font. + */ + public void setFallbackFont(Font fallbackFont) { + this.fallbackFont = fallbackFont; + } + + + /** + * Returns the font used by this cell. + * + * @return the font. + */ + public Font getFont() { + return this.font; + } + + + /** + * Returns the fallback font used by this cell. + * + * @return the fallback font. + */ + public Font getFallbackFont() { + return this.fallbackFont; + } + + + /** + * Sets the cell text. + * + * @param text the cell text. + */ + public void setText(String text) { + this.text = text; + } + + + /** + * Returns the cell text. + * + * @return the cell text. + */ + public String getText() { + return this.text; + } + + + /** + * Sets the image inside this cell. + * + * @param image the image. + */ + public void setImage(Image image) { + this.image = image; + } + + + /** + * Returns the cell image. + * + * @return the image. + */ + public Image getImage() { + return this.image; + } + + + /** + * Sets the point inside this cell. + * See the Point class and Example_09 for more information. + * + * @param point the point. + */ + public void setPoint(Point point) { + this.point = point; + } + + + /** + * Returns the cell point. + * + * @return the point. + */ + public Point getPoint() { + return this.point; + } + + + /** + * Sets the composite text object. + * + * @param compositeTextLine the composite text object. + */ + public void setCompositeTextLine(CompositeTextLine compositeTextLine) { + this.compositeTextLine = compositeTextLine; + } + + + /** + * Returns the composite text object. + * + * @return the composite text object. + */ + public CompositeTextLine getCompositeTextLine() { + return this.compositeTextLine; + } + + + /** + * Sets the width of this cell. + * + * @param width the specified width. + */ + public void setWidth(float width) { + this.width = width; + } + + + /** + * Returns the cell width. + * + * @return the cell width. + */ + public float getWidth() { + return this.width; + } + + + /** + * Sets the top padding of this cell. + * + * @param padding the top padding. + */ + public void setTopPadding(float padding) { + this.top_padding = padding; + } + + + /** + * Sets the bottom padding of this cell. + * + * @param padding the bottom padding. + */ + public void setBottomPadding(float padding) { + this.bottom_padding = padding; + } + + + /** + * Sets the left padding of this cell. + * + * @param padding the left padding. + */ + public void setLeftPadding(float padding) { + this.left_padding = padding; + } + + + /** + * Sets the right padding of this cell. + * + * @param padding the right padding. + */ + public void setRightPadding(float padding) { + this.right_padding = padding; + } + + + /** + * Sets the top, bottom, left and right paddings of this cell. + * + * @param padding the right padding. + */ + public void setPadding(float padding) { + this.top_padding = padding; + this.bottom_padding = padding; + this.left_padding = padding; + this.right_padding = padding; + } + + + /** + * Returns the cell height. + * + * @return the cell height. + */ + public float getHeight() { + if (image != null && !ignoreImageHeight) { + return image.getHeight() + top_padding + bottom_padding; + } + return font.body_height + top_padding + bottom_padding; + } + + + /** + * Sets the border line width. + * + * @param lineWidth the border line width. + */ + public void setLineWidth(float lineWidth) { + this.lineWidth = lineWidth; + } + + + /** + * Returns the border line width. + * + * @return the border line width. + */ + public float getLineWidth() { + return this.lineWidth; + } + + + /** + * Sets the background to the specified color. + * + * @param color the color specified as 0xRRGGBB integer. + */ + public void setBgColor(int color) { + this.background = color; + } + + + /** + * Returns the background color of this cell. + * + */ + public int getBgColor() { + return this.background; + } + + + /** + * Sets the pen color. + * + * @param color the color specified as 0xRRGGBB integer. + */ + public void setPenColor(int color) { + this.pen = color; + } + + + /** + * Returns the pen color. + * + */ + public int getPenColor() { + return pen; + } + + + /** + * Sets the brush color. + * + * @param color the color specified as 0xRRGGBB integer. + */ + public void setBrushColor(int color) { + this.brush = color; + } + + + /** + * Returns the brush color. + * + * @return the brush color. + */ + public int getBrushColor() { + return brush; + } + + + /** + * Sets the pen and brush colors to the specified color. + * + * @param color the color specified as 0xRRGGBB integer. + */ + public void setFgColor(int color) { + this.pen = color; + this.brush = color; + } + + + protected void setProperties(int properties) { + this.properties = properties; + } + + + protected int getProperties() { + return this.properties; + } + + + /** + * Sets the column span private variable. + * + * @param colspan the specified column span value. + */ + public void setColSpan(int colspan) { + this.properties &= 0x00FF0000; + this.properties |= (colspan & 0x0000FFFF); + } + + + /** + * Returns the column span private variable value. + * + * @return the column span value. + */ + public int getColSpan() { + return (this.properties & 0x0000FFFF); + } + + + /** + * Sets the cell border object. + * + * @param border the border object. + */ + public void setBorder(int border, boolean visible) { + if (visible) { + this.properties |= border; + } + else { + this.properties &= (~border & 0x00FFFFFF); + } + } + + + /** + * Returns the cell border object. + * + * @return the cell border object. + */ + public boolean getBorder(int border) { + return (this.properties & border) != 0; + } + + + /** + * Sets all border object parameters to false. + * This cell will have no borders when drawn on the page. + */ + public void setNoBorders() { + this.properties &= 0x00F0FFFF; + } + + + /** + * Sets the cell text alignment. + * + * @param alignment the alignment code. + * Supported values: Align.LEFT, Align.RIGHT and Align.CENTER. + */ + public void setTextAlignment(int alignment) { + this.properties &= 0x00CFFFFF; + this.properties |= (alignment & 0x00300000); + } + + + /** + * Returns the text alignment. + * + * @return the text horizontal alignment code. + */ + public int getTextAlignment() { + return (this.properties & 0x00300000); + } + + + /** + * Sets the cell text vertical alignment. + * + * @param alignment the alignment code. + * Supported values: Align.TOP, Align.CENTER and Align.BOTTOM. + */ + public void setVerTextAlignment(int alignment) { + this.valign = alignment; + } + + + /** + * Returns the cell text vertical alignment. + * + * @return the vertical alignment code. + */ + public int getVerTextAlignment() { + return this.valign; + } + + + /** + * Sets the underline text parameter. + * If the value of the underline variable is 'true' - the text is underlined. + * + * @param underline the underline text parameter. + */ + public void setUnderline(boolean underline) { + if (underline) { + this.properties |= 0x00400000; + } + else { + this.properties &= 0x00BFFFFF; + } + } + + + /** + * Returns the underline text parameter. + * + * @return the underline text parameter. + */ + public boolean getUnderline() { + return (properties & 0x00400000) != 0; + } + + + /** + * Sets the strikeout text parameter. + * + * @param strikeout the strikeout text parameter. + */ + public void setStrikeout(boolean strikeout) { + if (strikeout) { + this.properties |= 0x00800000; + } + else { + this.properties &= 0x007FFFFF; + } + } + + + /** + * Returns the strikeout text parameter. + * + * @return the strikeout text parameter. + */ + public boolean getStrikeout() { + return (properties & 0x00800000) != 0; + } + + + public void setURIAction(String uri) { + this.uri = uri; + } + + + /** + * Draws the point, text and borders of this cell. + * + */ + protected void paint( + Page page, + float x, + float y, + float w, + float h) throws Exception { + if (background != -1) { + drawBackground(page, x, y, w, h); + } + if (image != null) { + image.setLocation(x + left_padding, y + top_padding); + image.drawOn(page); + } + drawBorders(page, x, y, w, h); + if (text != null) { + drawText(page, x, y, w, h); + } + if (point != null) { + if (point.align == Align.LEFT) { + point.x = x + 2*point.r; + } + else if (point.align == Align.RIGHT) { + point.x = (x + w) - this.right_padding/2; + } + point.y = y + h/2; + page.setBrushColor(point.getColor()); + if (point.getURIAction() != null) { + page.addAnnotation(new Annotation( + point.getURIAction(), + null, + point.x - point.r, + page.height - (point.y - point.r), + point.x + point.r, + page.height - (point.y + point.r), + null, + null, + null)); + } + page.drawPoint(point); + } + } + + + private void drawBackground( + Page page, + float x, + float y, + float cell_w, + float cell_h) throws Exception { + page.setBrushColor(background); + page.fillRect(x, y + lineWidth / 2, cell_w, cell_h + lineWidth); + } + + + private void drawBorders( + Page page, + float x, + float y, + float cell_w, + float cell_h) throws Exception { + + page.setPenColor(pen); + page.setPenWidth(lineWidth); + + if (getBorder(Border.TOP) && + getBorder(Border.BOTTOM) && + getBorder(Border.LEFT) && + getBorder(Border.RIGHT)) { + page.addBMC(StructElem.SPAN, Single.space, Single.space); + page.drawRect(x, y, cell_w, cell_h); + page.addEMC(); + } + else { + float qWidth = lineWidth / 4; + if (getBorder(Border.TOP)) { + page.addBMC(StructElem.SPAN, Single.space, Single.space); + page.moveTo(x - qWidth, y); + page.lineTo(x + cell_w, y); + page.strokePath(); + page.addEMC(); + } + if (getBorder(Border.BOTTOM)) { + page.addBMC(StructElem.SPAN, Single.space, Single.space); + page.moveTo(x - qWidth, y + cell_h); + page.lineTo(x + cell_w, y + cell_h); + page.strokePath(); + page.addEMC(); + } + if (getBorder(Border.LEFT)) { + page.addBMC(StructElem.SPAN, Single.space, Single.space); + page.moveTo(x, y - qWidth); + page.lineTo(x, y + cell_h + qWidth); + page.strokePath(); + page.addEMC(); + } + if (getBorder(Border.RIGHT)) { + page.addBMC(StructElem.SPAN, Single.space, Single.space); + page.moveTo(x + cell_w, y - qWidth); + page.lineTo(x + cell_w, y + cell_h + qWidth); + page.strokePath(); + page.addEMC(); + } + } + + } + + + private void drawText( + Page page, + float x, + float y, + float cell_w, + float cell_h) throws Exception { + + float x_text; + float y_text; + if (valign == Align.TOP) { + y_text = y + font.ascent + this.top_padding; + } + else if (valign == Align.CENTER) { + y_text = y + cell_h/2 + font.ascent/2; + } + else if (valign == Align.BOTTOM) { + y_text = (y + cell_h) - this.bottom_padding; + } + else { + throw new Exception("Invalid vertical text alignment option."); + } + + page.setPenColor(pen); + page.setBrushColor(brush); + + if (getTextAlignment() == Align.RIGHT) { + if (compositeTextLine == null) { + x_text = (x + cell_w) - (font.stringWidth(text) + this.right_padding); + page.addBMC(StructElem.SPAN, text, text); + page.drawString(font, fallbackFont, text, x_text, y_text); + page.addEMC(); + if (getUnderline()) { + underlineText(page, font, text, x_text, y_text); + } + if (getStrikeout()) { + strikeoutText(page, font, text, x_text, y_text); + } + } + else { + x_text = (x + cell_w) - (compositeTextLine.getWidth() + this.right_padding); + compositeTextLine.setLocation(x_text, y_text); + page.addBMC(StructElem.SPAN, text, text); + compositeTextLine.drawOn(page); + page.addEMC(); + } + } + else if (getTextAlignment() == Align.CENTER) { + if (compositeTextLine == null) { + x_text = x + this.left_padding + + (((cell_w - (left_padding + right_padding)) - font.stringWidth(text)) / 2); + page.addBMC(StructElem.SPAN, text, text); + page.drawString(font, fallbackFont, text, x_text, y_text); + page.addEMC(); + if (getUnderline()) { + underlineText(page, font, text, x_text, y_text); + } + if (getStrikeout()) { + strikeoutText(page, font, text, x_text, y_text); + } + } + else { + x_text = x + this.left_padding + + (((cell_w - (left_padding + right_padding)) - compositeTextLine.getWidth()) / 2); + compositeTextLine.setLocation(x_text, y_text); + page.addBMC(StructElem.SPAN, text, text); + compositeTextLine.drawOn(page); + page.addEMC(); + } + } + else if (getTextAlignment() == Align.LEFT) { + x_text = x + this.left_padding; + if (compositeTextLine == null) { + page.addBMC(StructElem.SPAN, text, text); + page.drawString(font, fallbackFont, text, x_text, y_text); + page.addEMC(); + if (getUnderline()) { + underlineText(page, font, text, x_text, y_text); + } + if (getStrikeout()) { + strikeoutText(page, font, text, x_text, y_text); + } + } + else { + compositeTextLine.setLocation(x_text, y_text); + page.addBMC(StructElem.SPAN, text, text); + compositeTextLine.drawOn(page); + page.addEMC(); + } + } + else { + throw new Exception("Invalid Text Alignment!"); + } + + if (uri != null) { + float w = (compositeTextLine != null) ? + compositeTextLine.getWidth() : font.stringWidth(text); + // Please note: The font descent is a negative number. + page.addAnnotation(new Annotation( + uri, + null, + x_text, + (page.height - y_text) + font.descent, + x_text + w, + (page.height - y_text) + font.ascent, + null, + null, + null)); + } + } + + + private void underlineText( + Page page, Font font, String text, float x, float y) throws Exception { + page.addBMC(StructElem.SPAN, "underline", "underline"); + float descent = font.getDescent(); + page.setPenWidth(font.underlineThickness); + page.moveTo(x, y + descent); + page.lineTo(x + font.stringWidth(text), y + descent); + page.strokePath(); + page.addEMC(); + } + + + private void strikeoutText( + Page page, Font font, String text, float x, float y) throws Exception { + page.addBMC(StructElem.SPAN, "strike out", "strike out"); + page.setPenWidth(font.underlineThickness); + page.moveTo(x, y - font.getAscent()/3f); + page.lineTo(x + font.stringWidth(text), y - font.getAscent()/3f); + page.strokePath(); + page.addEMC(); + } + + + /** + * Use this method to find out how many vertically stacked cell are needed after call to wrapAroundCellText. + * + * @return the number of vertical cells needed to wrap around the cell text. + */ + public int getNumVerCells() { + int n = 1; + if (getText() == null) { + return n; + } + + String[] textLines = getText().split("\\r?\\n"); + if (textLines.length == 0) { + return n; + } + + n = 0; + for (String textLine : textLines) { + String[] tokens = textLine.split("\\s+"); + StringBuilder sb = new StringBuilder(); + if (tokens.length > 1) { + for (int i = 0; i < tokens.length; i++) { + String token = tokens[i]; + if (font.stringWidth(sb.toString() + " " + token) > + (getWidth() - (this.left_padding + this.right_padding))) { + sb = new StringBuilder(token); + n++; + } + else { + if (i > 0) { + sb.append(" "); + } + sb.append(token); + } + } + } + n++; + } + + return n; + } + + + /** + * Use this method to find out how many vertically stacked cell are needed after call to wrapAroundCellText2. + * + * @return the number of vertical cells needed to wrap around the cell text. + */ + public int getNumVerCells2() { + int n = 1; + if (getText() == null) { + return n; + } + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < this.text.length(); i++) { + String str = new String(new char[] { this.text.charAt(i) }); + if (font.stringWidth(sb.toString() + str) > + (getWidth() - (this.left_padding + this.right_padding))) { + n++; + sb.setLength(0); + } + sb.append(str); + } + return n; + } + + + public void setIgnoreImageHeight(boolean ignoreImageHeight) { + this.ignoreImageHeight = ignoreImageHeight; + } + + + public boolean getIgnoreImageHeight() { + return this.ignoreImageHeight; + } + +} // End of Cell.java diff --git a/PDFJet/src/main/java/com/pdfjet/CheckBox.java b/PDFJet/src/main/java/com/pdfjet/CheckBox.java new file mode 100644 index 0000000..4f95600 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/CheckBox.java @@ -0,0 +1,263 @@ +/** + * CheckBox.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Portions provided by Shirley C. Christenson +Shirley Christenson Consulting + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + + +/** + * Creates a CheckBox, which can be set checked or unchecked. + * By default the check box is unchecked. + */ +public class CheckBox implements Drawable { + + private float x; + private float y; + private float w; + private float h; + private int boxColor = Color.black; + private int checkColor = Color.black; + private float penWidth; + private float checkWidth; + private int mark = 0; + private Font font = null; + private String label = ""; + private String uri = null; + + private String language = null; + private String altDescription = Single.space; + private String actualText = Single.space; + + + /** + * Creates a CheckBox with black check mark. + * + */ + public CheckBox(Font font, String label) { + this.font = font; + this.label = label; + } + + + /** + * Sets the font size to use for this text line. + * + * @param fontSize the fontSize to use. + * @return this CheckBox. + */ + public CheckBox setFontSize(float fontSize) { + this.font.setSize(fontSize); + return this; + } + + + /** + * Sets the color of the check box. + * + * @param boxColor the check box color specified as an 0xRRGGBB integer. + * @return this CheckBox. + */ + public CheckBox setBoxColor(int boxColor) { + this.boxColor = boxColor; + return this; + } + + + /** + * Sets the color of the check mark. + * + * @param checkColor the check mark color specified as an 0xRRGGBB integer. + * @return this CheckBox. + */ + public CheckBox setCheckmark(int checkColor) { + this.checkColor = checkColor; + return this; + } + + + /** + * Set the x,y position on the Page. + * + * @param x the x coordinate on the Page. + * @param y the y coordinate on the Page. + * @return this CheckBox. + */ + public CheckBox setPosition(float x, float y) { + return setLocation(x, y); + } + + + /** + * Set the x,y location on the Page. + * + * @param x the x coordinate on the Page. + * @param y the y coordinate on the Page. + * @return this CheckBox. + */ + public CheckBox setLocation(float x, float y) { + this.x = x; + this.y = y; + return this; + } + + + /** + * Gets the height of the CheckBox. + * + */ + public float getHeight() { + return this.h; + } + + + /** + * Gets the width of the CheckBox. + * + */ + public float getWidth() { + return this.w; + } + + + /** + * Checks or unchecks this check box. See the Mark class for available options. + * + * @return this CheckBox. + */ + public CheckBox check(int mark) { + this.mark = mark; + return this; + } + + + /** + * Sets the URI for the "click text line" action. + * + * @param uri the URI. + * @return this CheckBox. + */ + public CheckBox setURIAction(String uri) { + this.uri = uri; + return this; + } + + + /** + * Sets the alternate description of this check box. + * + * @param altDescription the alternate description of the check box. + * @return this Checkbox. + */ + public CheckBox setAltDescription(String altDescription) { + this.altDescription = altDescription; + return this; + } + + + /** + * Sets the actual text for this check box. + * + * @param actualText the actual text for the check box. + * @return this CheckBox. + */ + public CheckBox setActualText(String actualText) { + this.actualText = actualText; + return this; + } + + + /** + * Draws this CheckBox on the specified Page. + * + * @param page the Page where the CheckBox is to be drawn. + */ + public float[] drawOn(Page page) throws Exception { + page.addBMC(StructElem.SPAN, language, altDescription, actualText); + + this.w = font.getAscent(); + this.h = this.w; + this.penWidth = this.w/15; + this.checkWidth = this.w/5; + + float y_box = y - font.getAscent(); + page.setPenWidth(penWidth); + page.setPenColor(boxColor); + page.setLinePattern("[] 0"); + page.drawRect(x, y_box, w, h); + + if (mark == Mark.CHECK || mark == Mark.X) { + page.setPenWidth(checkWidth); + page.setPenColor(checkColor); + if (mark == Mark.CHECK) { + // Draw check mark + page.moveTo(x + checkWidth, y_box + h/2); + page.lineTo(x + w/6 + checkWidth, (y_box + h) - 4f*checkWidth/3f); + page.lineTo((x + w) - checkWidth, y_box + checkWidth); + page.strokePath(); + } + else if (mark == Mark.X) { + // Draw 'X' mark + page.moveTo(x + checkWidth, y_box + checkWidth); + page.lineTo((x + w) - checkWidth, (y_box + h) - checkWidth); + page.moveTo((x + w) - checkWidth, y_box + checkWidth); + page.lineTo(x + checkWidth, (y_box + h) - checkWidth); + page.strokePath(); + } + } + + if (uri != null) { + page.setBrushColor(Color.blue); + } + page.drawString(font, label, x + 3f*w/2f, y); + page.setPenWidth(0f); + page.setPenColor(Color.black); + page.setBrushColor(Color.black); + + page.addEMC(); + + if (uri != null) { + // Please note: The font descent is a negative number. + page.addAnnotation(new Annotation( + uri, + null, + x + 3f*w/2f, + page.height - y, + x + 3f*w/2f + font.stringWidth(label), + page.height - (y - font.getAscent()), + language, + altDescription, + actualText)); + } + + return new float[] { x + 3f*w + font.stringWidth(label), y + font.getDescent() }; + } + +} // End of CheckBox.java diff --git a/PDFJet/src/main/java/com/pdfjet/Chunk.java b/PDFJet/src/main/java/com/pdfjet/Chunk.java new file mode 100644 index 0000000..a9a69b2 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Chunk.java @@ -0,0 +1,91 @@ +/** + * Chunk.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +package com.pdfjet; + +import java.util.zip.*; + + +class Chunk { + + protected byte[] type; + + private long chunkLength; + private byte[] data; + private long crc; + + + public Chunk() { + } + + + public long getLength() { + return this.chunkLength; + } + + + public void setLength( long chunkLength ) { + this.chunkLength = chunkLength; + } + + + public void setType( byte[] type ) { + this.type = type; + } + + + public byte[] getData() { + return this.data; + } + + + public void setData( byte[] data ) { + this.data = data; + } + + + public long getCrc() { + return this.crc; + } + + + public void setCrc( long crc ) { + this.crc = crc; + } + + + public boolean hasGoodCRC() { + CRC32 computedCRC = new CRC32(); + computedCRC.update( type, 0, 4 ); + computedCRC.update( data, 0, ( int ) chunkLength ); + return ( computedCRC.getValue() == this.crc ); + } + +} // End of Chunk.java diff --git a/PDFJet/src/main/java/com/pdfjet/ClockWise.java b/PDFJet/src/main/java/com/pdfjet/ClockWise.java new file mode 100644 index 0000000..08da3b1 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/ClockWise.java @@ -0,0 +1,47 @@ +/** + * ClockWise.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + + +/** + * Used to specify the check mark in CheckBox. + * + */ +public class ClockWise { + public static final int degrees_0 = 0; + public static final int degrees_90 = 90; + public static final int degrees_180 = 180; + public static final int degrees_270 = 270; + + public static final int _0_degrees = 0; + public static final int _90_degrees = 90; + public static final int _180_degrees = 180; + public static final int _270_degrees = 270; +} diff --git a/PDFJet/src/main/java/com/pdfjet/CodePage.java b/PDFJet/src/main/java/com/pdfjet/CodePage.java new file mode 100644 index 0000000..600ac79 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/CodePage.java @@ -0,0 +1,48 @@ +/** + * CodePage.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + + +/** + * Used to specify the character encoding - code page - for a font. + * See the Font class for more information. + * + * + */ +public class CodePage { + public static final int UNICODE = -1; + + public static final int CP1250 = 0; + public static final int CP1251 = 1; + public static final int CP1252 = 2; + public static final int CP1253 = 3; + public static final int CP1254 = 4; + public static final int CP1257 = 7; +} diff --git a/PDFJet/src/main/java/com/pdfjet/Color.java b/PDFJet/src/main/java/com/pdfjet/Color.java new file mode 100644 index 0000000..4ac6ea1 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Color.java @@ -0,0 +1,191 @@ +/** + * Color.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + + +/** + * Used to specify the pen and brush colors. + * @see http://www.w3.org/TR/css3-color/#svg-color + * + */ +public class Color { + public static final int aliceblue = 0xf0f8ff; + public static final int antiquewhite = 0xfaebd7; + public static final int aqua = 0x00ffff; + public static final int aquamarine = 0x7fffd4; + public static final int azure = 0xf0ffff; + public static final int beige = 0xf5f5dc; + public static final int bisque = 0xffe4c4; + public static final int black = 0x000000; + public static final int blanchedalmond = 0xffebcd; + public static final int blue = 0x0000ff; + public static final int blueviolet = 0x8a2be2; + public static final int brown = 0xa52a2a; + public static final int burlywood = 0xdeb887; + public static final int cadetblue = 0x5f9ea0; + public static final int chartreuse = 0x7fff00; + public static final int chocolate = 0xd2691e; + public static final int coral = 0xff7f50; + public static final int cornflowerblue = 0x6495ed; + public static final int cornsilk = 0xfff8dc; + public static final int crimson = 0xdc143c; + public static final int cyan = 0x00ffff; + public static final int darkblue = 0x00008b; + public static final int darkcyan = 0x008b8b; + public static final int darkgoldenrod = 0xb8860b; + public static final int darkgray = 0xa9a9a9; + public static final int darkgreen = 0x006400; + public static final int darkgrey = 0xa9a9a9; + public static final int darkkhaki = 0xbdb76b; + public static final int darkmagenta = 0x8b008b; + public static final int darkolivegreen = 0x556b2f; + public static final int darkorange = 0xff8c00; + public static final int darkorchid = 0x9932cc; + public static final int darkred = 0x8b0000; + public static final int darksalmon = 0xe9967a; + public static final int darkseagreen = 0x8fbc8f; + public static final int darkslateblue = 0x483d8b; + public static final int darkslategray = 0x2f4f4f; + public static final int darkslategrey = 0x2f4f4f; + public static final int darkturquoise = 0x00ced1; + public static final int darkviolet = 0x9400d3; + public static final int deeppink = 0xff1493; + public static final int deepskyblue = 0x00bfff; + public static final int dimgray = 0x696969; + public static final int dimgrey = 0x696969; + public static final int dodgerblue = 0x1e90ff; + public static final int firebrick = 0xb22222; + public static final int floralwhite = 0xfffaf0; + public static final int forestgreen = 0x228b22; + public static final int fuchsia = 0xff00ff; + public static final int gainsboro = 0xdcdcdc; + public static final int ghostwhite = 0xf8f8ff; + public static final int gold = 0xffd700; + public static final int goldenrod = 0xdaa520; + public static final int gray = 0x808080; + public static final int green = 0x008000; + public static final int greenyellow = 0xadff2f; + public static final int grey = 0x808080; + public static final int honeydew = 0xf0fff0; + public static final int hotpink = 0xff69b4; + public static final int indianred = 0xcd5c5c; + public static final int indigo = 0x4b0082; + public static final int ivory = 0xfffff0; + public static final int khaki = 0xf0e68c; + public static final int lavender = 0xe6e6fa; + public static final int lavenderblush = 0xfff0f5; + public static final int lawngreen = 0x7cfc00; + public static final int lemonchiffon = 0xfffacd; + public static final int lightblue = 0xadd8e6; + public static final int lightcoral = 0xf08080; + public static final int lightcyan = 0xe0ffff; + public static final int lightgoldenrodyellow = 0xfafad2; + public static final int lightgray = 0xd3d3d3; + public static final int lightgreen = 0x90ee90; + public static final int lightgrey = 0xd3d3d3; + public static final int lightpink = 0xffb6c1; + public static final int lightsalmon = 0xffa07a; + public static final int lightseagreen = 0x20b2aa; + public static final int lightskyblue = 0x87cefa; + public static final int lightslategray = 0x778899; + public static final int lightslategrey = 0x778899; + public static final int lightsteelblue = 0xb0c4de; + public static final int lightyellow = 0xffffe0; + public static final int lime = 0x00ff00; + public static final int limegreen = 0x32cd32; + public static final int linen = 0xfaf0e6; + public static final int magenta = 0xff00ff; + public static final int maroon = 0x800000; + public static final int mediumaquamarine = 0x66cdaa; + public static final int mediumblue = 0x0000cd; + public static final int mediumorchid = 0xba55d3; + public static final int mediumpurple = 0x9370db; + public static final int mediumseagreen = 0x3cb371; + public static final int mediumslateblue = 0x7b68ee; + public static final int mediumspringgreen = 0x00fa9a; + public static final int mediumturquoise = 0x48d1cc; + public static final int mediumvioletred = 0xc71585; + public static final int midnightblue = 0x191970; + public static final int mintcream = 0xf5fffa; + public static final int mistyrose = 0xffe4e1; + public static final int moccasin = 0xffe4b5; + public static final int navajowhite = 0xffdead; + public static final int navy = 0x000080; + public static final int oldlace = 0xfdf5e6; + public static final int olive = 0x808000; + public static final int olivedrab = 0x6b8e23; + public static final int orange = 0xffa500; + public static final int orangered = 0xff4500; + public static final int orchid = 0xda70d6; + public static final int palegoldenrod = 0xeee8aa; + public static final int palegreen = 0x98fb98; + public static final int paleturquoise = 0xafeeee; + public static final int palevioletred = 0xdb7093; + public static final int papayawhip = 0xffefd5; + public static final int peachpuff = 0xffdab9; + public static final int peru = 0xcd853f; + public static final int pink = 0xffc0cb; + public static final int plum = 0xdda0dd; + public static final int powderblue = 0xb0e0e6; + public static final int purple = 0x800080; + public static final int red = 0xff0000; + public static final int rosybrown = 0xbc8f8f; + public static final int royalblue = 0x4169e1; + public static final int saddlebrown = 0x8b4513; + public static final int salmon = 0xfa8072; + public static final int sandybrown = 0xf4a460; + public static final int seagreen = 0x2e8b57; + public static final int seashell = 0xfff5ee; + public static final int sienna = 0xa0522d; + public static final int silver = 0xc0c0c0; + public static final int skyblue = 0x87ceeb; + public static final int slateblue = 0x6a5acd; + public static final int slategray = 0x708090; + public static final int slategrey = 0x708090; + public static final int snow = 0xfffafa; + public static final int springgreen = 0x00ff7f; + public static final int steelblue = 0x4682b4; + public static final int tan = 0xd2b48c; + public static final int teal = 0x008080; + public static final int thistle = 0xd8bfd8; + public static final int tomato = 0xff6347; + public static final int turquoise = 0x40e0d0; + public static final int violet = 0xee82ee; + public static final int wheat = 0xf5deb3; + public static final int white = 0xffffff; + public static final int whitesmoke = 0xf5f5f5; + public static final int yellow = 0xffff00; + public static final int yellowgreen = 0x9acd32; + + public static final int oldgloryred = 0xb22234; + public static final int oldgloryblue = 0x3c3b6e; + + public static final int transparent = -1; +} diff --git a/PDFJet/src/main/java/com/pdfjet/Compliance.java b/PDFJet/src/main/java/com/pdfjet/Compliance.java new file mode 100644 index 0000000..8ffa3e0 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Compliance.java @@ -0,0 +1,12 @@ +package com.pdfjet; + + +/** + * Used to set PDF/A compliance. + * See the constructors in the PDF class. + * + */ +public class Compliance { + public static final int PDF_A_1B = 1; + public static final int PDF_UA = 2; +} diff --git a/PDFJet/src/main/java/com/pdfjet/CompositeTextLine.java b/PDFJet/src/main/java/com/pdfjet/CompositeTextLine.java new file mode 100644 index 0000000..1355690 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/CompositeTextLine.java @@ -0,0 +1,387 @@ +/** + * CompositeTextLine.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * This class was designed and implemented by Jon T. Swanson, Ph.D. + * + * Refactored and integrated into the project by Eugene Dragoev - 2nd June 2012. + */ + + +package com.pdfjet; + +import java.util.*; + + +/** + * Used to create composite text line objects. + * + * + */ +public class CompositeTextLine implements Drawable { + + private static final int X = 0; + private static final int Y = 1; + + private List textLines = new ArrayList(); + + private float[] position = new float[2]; + private float[] current = new float[2]; + + // Subscript and Superscript size factors + private float subscript_size_factor = 0.583f; + private float superscript_size_factor = 0.583f; + + // Subscript and Superscript positions in relation to the base font + private float superscript_position = 0.350f; + private float subscript_position = 0.141f; + + private float fontSize = 0f; + + + public CompositeTextLine(float x, float y) { + position[X] = x; + position[Y] = y; + current[X] = x; + current[Y] = y; + } + + + /** + * Sets the font size. + * + * @param fontSize the font size. + */ + public void setFontSize(float fontSize) { + this.fontSize = fontSize; + } + + + /** + * Gets the font size. + * + * @return fontSize the font size. + */ + public float getFontSize() { + return fontSize; + } + + + /** + * Sets the superscript factor for this composite text line. + * + * @param superscript the superscript size factor. + */ + public void setSuperscriptFactor(float superscript) { + this.superscript_size_factor = superscript; + } + + + /** + * Gets the superscript factor for this text line. + * + * @return superscript the superscript size factor. + */ + public float getSuperscriptFactor() { + return superscript_size_factor; + } + + + /** + * Sets the subscript factor for this composite text line. + * + * @param subscript the subscript size factor. + */ + public void setSubscriptFactor(float subscript) { + this.subscript_size_factor = subscript; + } + + + /** + * Gets the subscript factor for this text line. + * + * @return subscript the subscript size factor. + */ + public float getSubscriptFactor() { + return subscript_size_factor; + } + + + /** + * Sets the superscript position for this composite text line. + * + * @param superscript_position the superscript position. + */ + public void setSuperscriptPosition(float superscript_position) { + this.superscript_position = superscript_position; + } + + + /** + * Gets the superscript position for this text line. + * + * @return superscript_position the superscript position. + */ + public float getSuperscriptPosition() { + return superscript_position; + } + + + /** + * Sets the subscript position for this composite text line. + * + * @param subscript_position the subscript position. + */ + public void setSubscriptPosition(float subscript_position) { + this.subscript_position = subscript_position; + } + + + /** + * Gets the subscript position for this text line. + * + * @return subscript_position the subscript position. + */ + public float getSubscriptPosition() { + return subscript_position; + } + + + /** + * Add a new text line. + * + * Find the current font, current size and effects (normal, super or subscript) + * Set the position of the component to the starting stored as current position + * Set the size and offset based on effects + * Set the new current position + * + * @param component the component. + */ + public void addComponent(TextLine component) { + if (component.getTextEffect() == Effect.SUPERSCRIPT) { + if (fontSize > 0f) { + component.getFont().setSize(fontSize * superscript_size_factor); + } + component.setLocation( + current[X], + current[Y] - fontSize * superscript_position); + } + else if (component.getTextEffect() == Effect.SUBSCRIPT) { + if (fontSize > 0f) { + component.getFont().setSize(fontSize * subscript_size_factor); + } + component.setLocation( + current[X], + current[Y] + fontSize * subscript_position); + } + else { + if (fontSize > 0f) { + component.getFont().setSize(fontSize); + } + component.setLocation(current[X], current[Y]); + } + current[X] += component.getWidth(); + textLines.add(component); + } + + + /** + * Loop through all the text lines and reset their position based on + * the new position set here. + * + * @param x the x coordinate. + * @param y the y coordinate. + */ + public void setPosition(double x, double y) { + setPosition((float) x, (float) y); + } + + + /** + * Loop through all the text lines and reset their position based on + * the new position set here. + * + * @param x the x coordinate. + * @param y the y coordinate. + */ + public void setPosition(float x, float y) { + setLocation(x, y); + } + + + /** + * Loop through all the text lines and reset their location based on + * the new location set here. + * + * @param x the x coordinate. + * @param y the y coordinate. + */ + public void setLocation(float x, float y) { + position[X] = x; + position[Y] = y; + current[X] = x; + current[Y] = y; + + if (textLines == null || textLines.size() == 0) { + return; + } + + for (TextLine component : textLines) { + if (component.getTextEffect() == Effect.SUPERSCRIPT) { + component.setLocation( + current[X], + current[Y] - fontSize * superscript_position); + } + else if (component.getTextEffect() == Effect.SUBSCRIPT) { + component.setLocation( + current[X], + current[Y] + fontSize * subscript_position); + } + else { + component.setLocation(current[X], current[Y]); + } + current[X] += component.getWidth(); + } + } + + + /** + * Return the position of this composite text line. + * + * @return the position of this composite text line. + */ + public float[] getPosition() { + return position; + } + + + /** + * Return the nth entry in the TextLine array. + * + * @param index the index of the nth element. + * @return the text line at the specified index. + */ + public TextLine getTextLine(int index) { + if (textLines == null || textLines.size() == 0) { + return null; + } + if (index < 0 || index > textLines.size() - 1) { + return null; + } + return textLines.get(index); + } + + + /** + * Returns the number of text lines. + * + * @return the number of text lines. + */ + public int getNumberOfTextLines() { + return textLines.size(); + } + + + /** + * Returns the vertical coordinates of the top left and bottom right corners + * of the bounding box of this composite text line. + * + * @return the an array containing the vertical coordinates. + */ + public float[] getMinMax() { + float min = position[Y]; + float max = position[Y]; + float cur; + + for (TextLine component : textLines) { + if (component.getTextEffect() == Effect.SUPERSCRIPT) { + cur = (position[Y] - component.getFont().ascent) - fontSize * superscript_position; + if (cur < min) + min = cur; + } + else if (component.getTextEffect() == Effect.SUBSCRIPT) { + cur = (position[Y] - component.getFont().descent) + fontSize * subscript_position; + if (cur > max) + max = cur; + } + else { + cur = position[Y] - component.getFont().ascent; + if (cur < min) + min = cur; + cur = position[Y] - component.getFont().descent; + if (cur > max) + max = cur; + } + } + + return new float[] {min, max}; + } + + + /** + * Returns the height of this CompositeTextLine. + * + * @return the height. + */ + public float getHeight() { + float[] yy = getMinMax(); + return yy[1] - yy[0]; + } + + + /** + * Returns the width of this CompositeTextLine. + * + * @return the width. + */ + public float getWidth() { + return (current[X] - position[X]); + } + + + /** + * Draws this line on the specified page. + * + * @param page the page to draw this line on. + * @return x and y coordinates of the bottom right corner of this component. + * @throws Exception + */ + public float[] drawOn(Page page) throws Exception { + float x_max = 0f; + float y_max = 0f; + // Loop through all the text lines and draw them on the page + for (TextLine textLine : textLines) { + float[] xy = textLine.drawOn(page); + x_max = Math.max(x_max, xy[0]); + y_max = Math.max(y_max, xy[1]); + } + return new float[] {x_max, y_max}; + } + +} diff --git a/PDFJet/src/main/java/com/pdfjet/Compressor.java b/PDFJet/src/main/java/com/pdfjet/Compressor.java new file mode 100644 index 0000000..ab375e9 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Compressor.java @@ -0,0 +1,63 @@ +/** + * Compressor.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + +import java.io.*; +import java.util.zip.*; + + +class Compressor extends Deflater { + + ByteArrayOutputStream bos = null; + + + public Compressor(byte[] image) { + + // setLevel(Deflater.BEST_SPEED); + // setLevel(Deflater.NO_COMPRESSION); + setInput(image); + finish(); + + bos = new ByteArrayOutputStream(image.length); + + byte[] buf = new byte[2048]; + while (!finished()) { + int count = deflate(buf); + bos.write(buf, 0, count); + } + + } + + + public byte[] getCompressedData() { + return bos.toByteArray(); + } + +} diff --git a/PDFJet/src/main/java/com/pdfjet/CoreFont.java b/PDFJet/src/main/java/com/pdfjet/CoreFont.java new file mode 100644 index 0000000..b1cd780 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/CoreFont.java @@ -0,0 +1,53 @@ +/** + * CoreFont.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + + +/** + * Used to select one of the 14 core fonts. + * See the Font class for more details. + * + */ +public enum CoreFont { + COURIER, + COURIER_BOLD, + COURIER_OBLIQUE, + COURIER_BOLD_OBLIQUE, + HELVETICA, + HELVETICA_BOLD, + HELVETICA_OBLIQUE, + HELVETICA_BOLD_OBLIQUE, + TIMES_ROMAN, + TIMES_BOLD, + TIMES_ITALIC, + TIMES_BOLD_ITALIC, + SYMBOL, + ZAPF_DINGBATS, +} diff --git a/PDFJet/src/main/java/com/pdfjet/Courier.java b/PDFJet/src/main/java/com/pdfjet/Courier.java new file mode 100644 index 0000000..21ff113 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Courier.java @@ -0,0 +1,238 @@ +package com.pdfjet; + +class Courier { + protected static final String name = "Courier"; + protected static final int bBoxLLx = -23; + protected static final int bBoxLLy = -250; + protected static final int bBoxURx = 715; + protected static final int bBoxURy = 805; + protected static final int underlinePosition = -100; + protected static final int underlineThickness = 50; + protected static final String notice = "Copyright (c) 1989, 1990, 1991, 1992, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved."; + protected static final int[][] metrics = { + {32,600,}, + {33,600,}, + {34,600,}, + {35,600,}, + {36,600,}, + {37,600,}, + {38,600,}, + {39,600,}, + {40,600,}, + {41,600,}, + {42,600,}, + {43,600,}, + {44,600,}, + {45,600,}, + {46,600,}, + {47,600,}, + {48,600,}, + {49,600,}, + {50,600,}, + {51,600,}, + {52,600,}, + {53,600,}, + {54,600,}, + {55,600,}, + {56,600,}, + {57,600,}, + {58,600,}, + {59,600,}, + {60,600,}, + {61,600,}, + {62,600,}, + {63,600,}, + {64,600,}, + {65,600,}, + {66,600,}, + {67,600,}, + {68,600,}, + {69,600,}, + {70,600,}, + {71,600,}, + {72,600,}, + {73,600,}, + {74,600,}, + {75,600,}, + {76,600,}, + {77,600,}, + {78,600,}, + {79,600,}, + {80,600,}, + {81,600,}, + {82,600,}, + {83,600,}, + {84,600,}, + {85,600,}, + {86,600,}, + {87,600,}, + {88,600,}, + {89,600,}, + {90,600,}, + {91,600,}, + {92,600,}, + {93,600,}, + {94,600,}, + {95,600,}, + {96,600,}, + {97,600,}, + {98,600,}, + {99,600,}, + {100,600,}, + {101,600,}, + {102,600,}, + {103,600,}, + {104,600,}, + {105,600,}, + {106,600,}, + {107,600,}, + {108,600,}, + {109,600,}, + {110,600,}, + {111,600,}, + {112,600,}, + {113,600,}, + {114,600,}, + {115,600,}, + {116,600,}, + {117,600,}, + {118,600,}, + {119,600,}, + {120,600,}, + {121,600,}, + {122,600,}, + {123,600,}, + {124,600,}, + {125,600,}, + {126,600,}, + {127,600,}, + {128,600,}, + {129,600,}, + {130,600,}, + {131,600,}, + {132,600,}, + {133,600,}, + {134,600,}, + {135,600,}, + {136,600,}, + {137,600,}, + {138,600,}, + {139,600,}, + {140,600,}, + {141,600,}, + {142,600,}, + {143,600,}, + {144,600,}, + {145,600,}, + {146,600,}, + {147,600,}, + {148,600,}, + {149,600,}, + {150,600,}, + {151,600,}, + {152,600,}, + {153,600,}, + {154,600,}, + {155,600,}, + {156,600,}, + {157,600,}, + {158,600,}, + {159,600,}, + {160,600,}, + {161,600,}, + {162,600,}, + {163,600,}, + {164,600,}, + {165,600,}, + {166,600,}, + {167,600,}, + {168,600,}, + {169,600,}, + {170,600,}, + {171,600,}, + {172,600,}, + {173,600,}, + {174,600,}, + {175,600,}, + {176,600,}, + {177,600,}, + {178,600,}, + {179,600,}, + {180,600,}, + {181,600,}, + {182,600,}, + {183,600,}, + {184,600,}, + {185,600,}, + {186,600,}, + {187,600,}, + {188,600,}, + {189,600,}, + {190,600,}, + {191,600,}, + {192,600,}, + {193,600,}, + {194,600,}, + {195,600,}, + {196,600,}, + {197,600,}, + {198,600,}, + {199,600,}, + {200,600,}, + {201,600,}, + {202,600,}, + {203,600,}, + {204,600,}, + {205,600,}, + {206,600,}, + {207,600,}, + {208,600,}, + {209,600,}, + {210,600,}, + {211,600,}, + {212,600,}, + {213,600,}, + {214,600,}, + {215,600,}, + {216,600,}, + {217,600,}, + {218,600,}, + {219,600,}, + {220,600,}, + {221,600,}, + {222,600,}, + {223,600,}, + {224,600,}, + {225,600,}, + {226,600,}, + {227,600,}, + {228,600,}, + {229,600,}, + {230,600,}, + {231,600,}, + {232,600,}, + {233,600,}, + {234,600,}, + {235,600,}, + {236,600,}, + {237,600,}, + {238,600,}, + {239,600,}, + {240,600,}, + {241,600,}, + {242,600,}, + {243,600,}, + {244,600,}, + {245,600,}, + {246,600,}, + {247,600,}, + {248,600,}, + {249,600,}, + {250,600,}, + {251,600,}, + {252,600,}, + {253,600,}, + {254,600,}, + {255,600,}, + }; +} diff --git a/PDFJet/src/main/java/com/pdfjet/Courier_Bold.java b/PDFJet/src/main/java/com/pdfjet/Courier_Bold.java new file mode 100644 index 0000000..3e18146 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Courier_Bold.java @@ -0,0 +1,238 @@ +package com.pdfjet; + +class Courier_Bold { + protected static final String name = "Courier-Bold"; + protected static final int bBoxLLx = -113; + protected static final int bBoxLLy = -250; + protected static final int bBoxURx = 749; + protected static final int bBoxURy = 801; + protected static final int underlinePosition = -100; + protected static final int underlineThickness = 50; + protected static final String notice = "Copyright (c) 1989, 1990, 1991, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved."; + protected static final int[][] metrics = { + {32,600,}, + {33,600,}, + {34,600,}, + {35,600,}, + {36,600,}, + {37,600,}, + {38,600,}, + {39,600,}, + {40,600,}, + {41,600,}, + {42,600,}, + {43,600,}, + {44,600,}, + {45,600,}, + {46,600,}, + {47,600,}, + {48,600,}, + {49,600,}, + {50,600,}, + {51,600,}, + {52,600,}, + {53,600,}, + {54,600,}, + {55,600,}, + {56,600,}, + {57,600,}, + {58,600,}, + {59,600,}, + {60,600,}, + {61,600,}, + {62,600,}, + {63,600,}, + {64,600,}, + {65,600,}, + {66,600,}, + {67,600,}, + {68,600,}, + {69,600,}, + {70,600,}, + {71,600,}, + {72,600,}, + {73,600,}, + {74,600,}, + {75,600,}, + {76,600,}, + {77,600,}, + {78,600,}, + {79,600,}, + {80,600,}, + {81,600,}, + {82,600,}, + {83,600,}, + {84,600,}, + {85,600,}, + {86,600,}, + {87,600,}, + {88,600,}, + {89,600,}, + {90,600,}, + {91,600,}, + {92,600,}, + {93,600,}, + {94,600,}, + {95,600,}, + {96,600,}, + {97,600,}, + {98,600,}, + {99,600,}, + {100,600,}, + {101,600,}, + {102,600,}, + {103,600,}, + {104,600,}, + {105,600,}, + {106,600,}, + {107,600,}, + {108,600,}, + {109,600,}, + {110,600,}, + {111,600,}, + {112,600,}, + {113,600,}, + {114,600,}, + {115,600,}, + {116,600,}, + {117,600,}, + {118,600,}, + {119,600,}, + {120,600,}, + {121,600,}, + {122,600,}, + {123,600,}, + {124,600,}, + {125,600,}, + {126,600,}, + {127,600,}, + {128,600,}, + {129,600,}, + {130,600,}, + {131,600,}, + {132,600,}, + {133,600,}, + {134,600,}, + {135,600,}, + {136,600,}, + {137,600,}, + {138,600,}, + {139,600,}, + {140,600,}, + {141,600,}, + {142,600,}, + {143,600,}, + {144,600,}, + {145,600,}, + {146,600,}, + {147,600,}, + {148,600,}, + {149,600,}, + {150,600,}, + {151,600,}, + {152,600,}, + {153,600,}, + {154,600,}, + {155,600,}, + {156,600,}, + {157,600,}, + {158,600,}, + {159,600,}, + {160,600,}, + {161,600,}, + {162,600,}, + {163,600,}, + {164,600,}, + {165,600,}, + {166,600,}, + {167,600,}, + {168,600,}, + {169,600,}, + {170,600,}, + {171,600,}, + {172,600,}, + {173,600,}, + {174,600,}, + {175,600,}, + {176,600,}, + {177,600,}, + {178,600,}, + {179,600,}, + {180,600,}, + {181,600,}, + {182,600,}, + {183,600,}, + {184,600,}, + {185,600,}, + {186,600,}, + {187,600,}, + {188,600,}, + {189,600,}, + {190,600,}, + {191,600,}, + {192,600,}, + {193,600,}, + {194,600,}, + {195,600,}, + {196,600,}, + {197,600,}, + {198,600,}, + {199,600,}, + {200,600,}, + {201,600,}, + {202,600,}, + {203,600,}, + {204,600,}, + {205,600,}, + {206,600,}, + {207,600,}, + {208,600,}, + {209,600,}, + {210,600,}, + {211,600,}, + {212,600,}, + {213,600,}, + {214,600,}, + {215,600,}, + {216,600,}, + {217,600,}, + {218,600,}, + {219,600,}, + {220,600,}, + {221,600,}, + {222,600,}, + {223,600,}, + {224,600,}, + {225,600,}, + {226,600,}, + {227,600,}, + {228,600,}, + {229,600,}, + {230,600,}, + {231,600,}, + {232,600,}, + {233,600,}, + {234,600,}, + {235,600,}, + {236,600,}, + {237,600,}, + {238,600,}, + {239,600,}, + {240,600,}, + {241,600,}, + {242,600,}, + {243,600,}, + {244,600,}, + {245,600,}, + {246,600,}, + {247,600,}, + {248,600,}, + {249,600,}, + {250,600,}, + {251,600,}, + {252,600,}, + {253,600,}, + {254,600,}, + {255,600,}, + }; +} diff --git a/PDFJet/src/main/java/com/pdfjet/Courier_BoldOblique.java b/PDFJet/src/main/java/com/pdfjet/Courier_BoldOblique.java new file mode 100644 index 0000000..c222e2f --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Courier_BoldOblique.java @@ -0,0 +1,238 @@ +package com.pdfjet; + +class Courier_BoldOblique { + protected static final String name = "Courier-BoldOblique"; + protected static final int bBoxLLx = -57; + protected static final int bBoxLLy = -250; + protected static final int bBoxURx = 869; + protected static final int bBoxURy = 801; + protected static final int underlinePosition = -100; + protected static final int underlineThickness = 50; + protected static final String notice = "Copyright (c) 1989, 1990, 1991, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved."; + protected static final int[][] metrics = { + {32,600,}, + {33,600,}, + {34,600,}, + {35,600,}, + {36,600,}, + {37,600,}, + {38,600,}, + {39,600,}, + {40,600,}, + {41,600,}, + {42,600,}, + {43,600,}, + {44,600,}, + {45,600,}, + {46,600,}, + {47,600,}, + {48,600,}, + {49,600,}, + {50,600,}, + {51,600,}, + {52,600,}, + {53,600,}, + {54,600,}, + {55,600,}, + {56,600,}, + {57,600,}, + {58,600,}, + {59,600,}, + {60,600,}, + {61,600,}, + {62,600,}, + {63,600,}, + {64,600,}, + {65,600,}, + {66,600,}, + {67,600,}, + {68,600,}, + {69,600,}, + {70,600,}, + {71,600,}, + {72,600,}, + {73,600,}, + {74,600,}, + {75,600,}, + {76,600,}, + {77,600,}, + {78,600,}, + {79,600,}, + {80,600,}, + {81,600,}, + {82,600,}, + {83,600,}, + {84,600,}, + {85,600,}, + {86,600,}, + {87,600,}, + {88,600,}, + {89,600,}, + {90,600,}, + {91,600,}, + {92,600,}, + {93,600,}, + {94,600,}, + {95,600,}, + {96,600,}, + {97,600,}, + {98,600,}, + {99,600,}, + {100,600,}, + {101,600,}, + {102,600,}, + {103,600,}, + {104,600,}, + {105,600,}, + {106,600,}, + {107,600,}, + {108,600,}, + {109,600,}, + {110,600,}, + {111,600,}, + {112,600,}, + {113,600,}, + {114,600,}, + {115,600,}, + {116,600,}, + {117,600,}, + {118,600,}, + {119,600,}, + {120,600,}, + {121,600,}, + {122,600,}, + {123,600,}, + {124,600,}, + {125,600,}, + {126,600,}, + {127,600,}, + {128,600,}, + {129,600,}, + {130,600,}, + {131,600,}, + {132,600,}, + {133,600,}, + {134,600,}, + {135,600,}, + {136,600,}, + {137,600,}, + {138,600,}, + {139,600,}, + {140,600,}, + {141,600,}, + {142,600,}, + {143,600,}, + {144,600,}, + {145,600,}, + {146,600,}, + {147,600,}, + {148,600,}, + {149,600,}, + {150,600,}, + {151,600,}, + {152,600,}, + {153,600,}, + {154,600,}, + {155,600,}, + {156,600,}, + {157,600,}, + {158,600,}, + {159,600,}, + {160,600,}, + {161,600,}, + {162,600,}, + {163,600,}, + {164,600,}, + {165,600,}, + {166,600,}, + {167,600,}, + {168,600,}, + {169,600,}, + {170,600,}, + {171,600,}, + {172,600,}, + {173,600,}, + {174,600,}, + {175,600,}, + {176,600,}, + {177,600,}, + {178,600,}, + {179,600,}, + {180,600,}, + {181,600,}, + {182,600,}, + {183,600,}, + {184,600,}, + {185,600,}, + {186,600,}, + {187,600,}, + {188,600,}, + {189,600,}, + {190,600,}, + {191,600,}, + {192,600,}, + {193,600,}, + {194,600,}, + {195,600,}, + {196,600,}, + {197,600,}, + {198,600,}, + {199,600,}, + {200,600,}, + {201,600,}, + {202,600,}, + {203,600,}, + {204,600,}, + {205,600,}, + {206,600,}, + {207,600,}, + {208,600,}, + {209,600,}, + {210,600,}, + {211,600,}, + {212,600,}, + {213,600,}, + {214,600,}, + {215,600,}, + {216,600,}, + {217,600,}, + {218,600,}, + {219,600,}, + {220,600,}, + {221,600,}, + {222,600,}, + {223,600,}, + {224,600,}, + {225,600,}, + {226,600,}, + {227,600,}, + {228,600,}, + {229,600,}, + {230,600,}, + {231,600,}, + {232,600,}, + {233,600,}, + {234,600,}, + {235,600,}, + {236,600,}, + {237,600,}, + {238,600,}, + {239,600,}, + {240,600,}, + {241,600,}, + {242,600,}, + {243,600,}, + {244,600,}, + {245,600,}, + {246,600,}, + {247,600,}, + {248,600,}, + {249,600,}, + {250,600,}, + {251,600,}, + {252,600,}, + {253,600,}, + {254,600,}, + {255,600,}, + }; +} diff --git a/PDFJet/src/main/java/com/pdfjet/Courier_Oblique.java b/PDFJet/src/main/java/com/pdfjet/Courier_Oblique.java new file mode 100644 index 0000000..badcb80 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Courier_Oblique.java @@ -0,0 +1,238 @@ +package com.pdfjet; + +class Courier_Oblique { + protected static final String name = "Courier-Oblique"; + protected static final int bBoxLLx = -27; + protected static final int bBoxLLy = -250; + protected static final int bBoxURx = 849; + protected static final int bBoxURy = 805; + protected static final int underlinePosition = -100; + protected static final int underlineThickness = 50; + protected static final String notice = "Copyright (c) 1989, 1990, 1991, 1992, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved."; + protected static final int[][] metrics = { + {32,600,}, + {33,600,}, + {34,600,}, + {35,600,}, + {36,600,}, + {37,600,}, + {38,600,}, + {39,600,}, + {40,600,}, + {41,600,}, + {42,600,}, + {43,600,}, + {44,600,}, + {45,600,}, + {46,600,}, + {47,600,}, + {48,600,}, + {49,600,}, + {50,600,}, + {51,600,}, + {52,600,}, + {53,600,}, + {54,600,}, + {55,600,}, + {56,600,}, + {57,600,}, + {58,600,}, + {59,600,}, + {60,600,}, + {61,600,}, + {62,600,}, + {63,600,}, + {64,600,}, + {65,600,}, + {66,600,}, + {67,600,}, + {68,600,}, + {69,600,}, + {70,600,}, + {71,600,}, + {72,600,}, + {73,600,}, + {74,600,}, + {75,600,}, + {76,600,}, + {77,600,}, + {78,600,}, + {79,600,}, + {80,600,}, + {81,600,}, + {82,600,}, + {83,600,}, + {84,600,}, + {85,600,}, + {86,600,}, + {87,600,}, + {88,600,}, + {89,600,}, + {90,600,}, + {91,600,}, + {92,600,}, + {93,600,}, + {94,600,}, + {95,600,}, + {96,600,}, + {97,600,}, + {98,600,}, + {99,600,}, + {100,600,}, + {101,600,}, + {102,600,}, + {103,600,}, + {104,600,}, + {105,600,}, + {106,600,}, + {107,600,}, + {108,600,}, + {109,600,}, + {110,600,}, + {111,600,}, + {112,600,}, + {113,600,}, + {114,600,}, + {115,600,}, + {116,600,}, + {117,600,}, + {118,600,}, + {119,600,}, + {120,600,}, + {121,600,}, + {122,600,}, + {123,600,}, + {124,600,}, + {125,600,}, + {126,600,}, + {127,600,}, + {128,600,}, + {129,600,}, + {130,600,}, + {131,600,}, + {132,600,}, + {133,600,}, + {134,600,}, + {135,600,}, + {136,600,}, + {137,600,}, + {138,600,}, + {139,600,}, + {140,600,}, + {141,600,}, + {142,600,}, + {143,600,}, + {144,600,}, + {145,600,}, + {146,600,}, + {147,600,}, + {148,600,}, + {149,600,}, + {150,600,}, + {151,600,}, + {152,600,}, + {153,600,}, + {154,600,}, + {155,600,}, + {156,600,}, + {157,600,}, + {158,600,}, + {159,600,}, + {160,600,}, + {161,600,}, + {162,600,}, + {163,600,}, + {164,600,}, + {165,600,}, + {166,600,}, + {167,600,}, + {168,600,}, + {169,600,}, + {170,600,}, + {171,600,}, + {172,600,}, + {173,600,}, + {174,600,}, + {175,600,}, + {176,600,}, + {177,600,}, + {178,600,}, + {179,600,}, + {180,600,}, + {181,600,}, + {182,600,}, + {183,600,}, + {184,600,}, + {185,600,}, + {186,600,}, + {187,600,}, + {188,600,}, + {189,600,}, + {190,600,}, + {191,600,}, + {192,600,}, + {193,600,}, + {194,600,}, + {195,600,}, + {196,600,}, + {197,600,}, + {198,600,}, + {199,600,}, + {200,600,}, + {201,600,}, + {202,600,}, + {203,600,}, + {204,600,}, + {205,600,}, + {206,600,}, + {207,600,}, + {208,600,}, + {209,600,}, + {210,600,}, + {211,600,}, + {212,600,}, + {213,600,}, + {214,600,}, + {215,600,}, + {216,600,}, + {217,600,}, + {218,600,}, + {219,600,}, + {220,600,}, + {221,600,}, + {222,600,}, + {223,600,}, + {224,600,}, + {225,600,}, + {226,600,}, + {227,600,}, + {228,600,}, + {229,600,}, + {230,600,}, + {231,600,}, + {232,600,}, + {233,600,}, + {234,600,}, + {235,600,}, + {236,600,}, + {237,600,}, + {238,600,}, + {239,600,}, + {240,600,}, + {241,600,}, + {242,600,}, + {243,600,}, + {244,600,}, + {245,600,}, + {246,600,}, + {247,600,}, + {248,600,}, + {249,600,}, + {250,600,}, + {251,600,}, + {252,600,}, + {253,600,}, + {254,600,}, + {255,600,}, + }; +} diff --git a/PDFJet/src/main/java/com/pdfjet/Decompressor.java b/PDFJet/src/main/java/com/pdfjet/Decompressor.java new file mode 100644 index 0000000..74e3786 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Decompressor.java @@ -0,0 +1,57 @@ +/** + * Decompressor.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + +import java.io.*; +import java.util.zip.*; + + +class Decompressor extends Inflater { + + private ByteArrayOutputStream bos = null; + + + public Decompressor(byte[] data) throws Exception { + super.setInput(data); + bos = new ByteArrayOutputStream(data.length); + + byte[] buf = new byte[2048]; + while (!super.finished()) { + int count = super.inflate(buf); + bos.write(buf, 0, count); + } + } + + + public byte[] getDecompressedData() { + return bos.toByteArray(); + } + +} diff --git a/PDFJet/src/main/java/com/pdfjet/Destination.java b/PDFJet/src/main/java/com/pdfjet/Destination.java new file mode 100644 index 0000000..dcaefb9 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Destination.java @@ -0,0 +1,74 @@ +/** + * Destination.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + + +/** + * Used to create PDF destination objects. + * + * + */ +public class Destination { + + String name; + int pageObjNumber; + float yPosition; + + + /** + * This class is used to create destination objects. + * + * @param name the name of this destination object. + * @param yPosition the y coordinate of the top left corner. + * + */ + public Destination(String name, double yPosition) { + this(name, (float) yPosition); + } + + + /** + * This class is used to create destination objects. + * + * @param name the name of this destination object. + * @param yPosition the y coordinate of the top left corner. + * + */ + public Destination(String name, float yPosition) { + this.name = name; + this.yPosition = yPosition; + } + + + protected void setPageObjNumber(int pageObjNumber) { + this.pageObjNumber = pageObjNumber; + } + +} diff --git a/PDFJet/src/main/java/com/pdfjet/Dimension.java b/PDFJet/src/main/java/com/pdfjet/Dimension.java new file mode 100644 index 0000000..a414328 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Dimension.java @@ -0,0 +1,61 @@ +/** + * Dimension.java + * + Copyright (c) 2018, Innovatics Inc. + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.pdfjet; + +/** + * Encapsulates the width and height of a component. + */ +public class Dimension { + + protected float w; + protected float h; + + /** + * Constructor for creating dimension objects. + * + * @param width the width. + * @param height the height. + */ + public Dimension(float width, float height) { + this.w = width; + this.h = height; + } + + + public float getWidth() { + return w; + } + + + public float getHeight() { + return h; + } + +} // End of Dimension.java + diff --git a/PDFJet/src/main/java/com/pdfjet/Drawable.java b/PDFJet/src/main/java/com/pdfjet/Drawable.java new file mode 100644 index 0000000..43d693e --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Drawable.java @@ -0,0 +1,47 @@ +/** + * Drawable.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +package com.pdfjet; + +/** + * Interface that is required for components that can be drawn on a PDF page as part of Optional Content Group. + * + * @author Mark Paxton + */ +public interface Drawable { + + /** + * Draw the component implementing this interface on the PDF page. + * + * @param page the page to draw on. + * @return x and y coordinates of the bottom right corner of this component. + * @throws Exception + */ + public float[] drawOn(Page page) throws Exception; + +} diff --git a/PDFJet/src/main/java/com/pdfjet/Effect.java b/PDFJet/src/main/java/com/pdfjet/Effect.java new file mode 100644 index 0000000..f4f92f4 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Effect.java @@ -0,0 +1,41 @@ +/** + * Effect.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + + +/** + * Used to specify the text effects. + * + */ +public class Effect { + public static final int NORMAL = 0; + public static final int SUBSCRIPT = 1; + public static final int SUPERSCRIPT = 2; +} diff --git a/PDFJet/src/main/java/com/pdfjet/Embed.java b/PDFJet/src/main/java/com/pdfjet/Embed.java new file mode 100644 index 0000000..f241460 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Embed.java @@ -0,0 +1,41 @@ +/** + * Embed.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + + +/** + * Used to specify if TrueType or OpenType font should be embedded in the PDF document. + * See the Font class for more details. + * + */ +public class Embed { + public static final boolean YES = true; + public static final boolean NO = false; +} diff --git a/PDFJet/src/main/java/com/pdfjet/EmbeddedFile.java b/PDFJet/src/main/java/com/pdfjet/EmbeddedFile.java new file mode 100644 index 0000000..38f8ee0 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/EmbeddedFile.java @@ -0,0 +1,105 @@ +/** + * EmbeddedFile.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.util.zip.Deflater; +import java.util.zip.DeflaterOutputStream; + + +/** + * Used to embed file objects. + * The file objects must added to the PDF before drawing on the first page. + * + */ +public class EmbeddedFile { + + protected int objNumber = -1; + protected String fileName = null; + + + public EmbeddedFile(PDF pdf, String fileName, InputStream stream, boolean compress) throws Exception { + this.fileName = fileName; + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte[] buf = new byte[2048]; + int number; + while ((number = stream.read(buf, 0, buf.length)) > 0) { + baos.write(buf, 0, number); + } + stream.close(); + + if (compress) { + buf = baos.toByteArray(); + baos = new ByteArrayOutputStream(); + DeflaterOutputStream dos = new DeflaterOutputStream(baos, new Deflater()); + dos.write(buf, 0, buf.length); + dos.finish(); + } + + pdf.newobj(); + pdf.append("<<\n"); + pdf.append("/Type /EmbeddedFile\n"); + if (compress) { + pdf.append("/Filter /FlateDecode\n"); + } + pdf.append("/Length "); + pdf.append(baos.size()); + pdf.append("\n"); + pdf.append(">>\n"); + pdf.append("stream\n"); + pdf.append(baos); + pdf.append("\nendstream\n"); + pdf.endobj(); + + pdf.newobj(); + pdf.append("<<\n"); + pdf.append("/Type /Filespec\n"); + pdf.append("/F ("); + pdf.append(fileName); + pdf.append(")\n"); + pdf.append("/EF <>\n"); + pdf.append(">>\n"); + pdf.endobj(); + + this.objNumber = pdf.objNumber; + + pdf.embeddedFiles.add(this); + } + + + public String getFileName() { + return fileName; + } + +} // End of EmbeddedFile.java diff --git a/PDFJet/src/main/java/com/pdfjet/ErrorCorrectLevel.java b/PDFJet/src/main/java/com/pdfjet/ErrorCorrectLevel.java new file mode 100644 index 0000000..1f9681a --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/ErrorCorrectLevel.java @@ -0,0 +1,28 @@ +/** + * +Copyright (c) 2009 Kazuhiko Arase + +URL: http://www.d-project.com/ + +Licensed under the MIT license: + http://www.opensource.org/licenses/mit-license.php + +The word "QR Code" is registered trademark of +DENSO WAVE INCORPORATED + http://www.denso-wave.com/qrcode/faqpatent-e.html +*/ + +package com.pdfjet; + +/** + * Used to specify the error correction level for QR Codes. + * + * @author Kazuhiko Arase + */ +public class ErrorCorrectLevel { + public static final int L = 1; + public static final int M = 0; + public static final int Q = 3; + public static final int H = 2; +} + diff --git a/PDFJet/src/main/java/com/pdfjet/Executive.java b/PDFJet/src/main/java/com/pdfjet/Executive.java new file mode 100644 index 0000000..55ad124 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Executive.java @@ -0,0 +1,41 @@ +/** + * Executive.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + + +/** + * Used to specify PDF page with size Executive. + * For more information about the page size classes - A3, A4, A5, B5, Executive, Letter, Legal and Tabloid - see the Page class. + * + */ +public class Executive { + public static final float[] PORTRAIT = new float[] {522.0f, 756.0f}; + public static final float[] LANDSCAPE = new float[] {756.0f, 522.0f}; +} diff --git a/PDFJet/src/main/java/com/pdfjet/FastFont.java b/PDFJet/src/main/java/com/pdfjet/FastFont.java new file mode 100644 index 0000000..e985548 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/FastFont.java @@ -0,0 +1,378 @@ +/** + * FastFont.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + +import java.io.*; +import java.util.*; +import java.util.zip.*; + + +class FastFont { + + protected static void register( + PDF pdf, + Font font, + InputStream inputStream) throws Exception { + + int len = inputStream.read(); + byte[] fontName = new byte[len]; + inputStream.read(fontName, 0, len); + font.name = new String(fontName, "UTF8"); + // System.out.println(font.name); + + len = getInt24(inputStream); + byte[] fontInfo = new byte[len]; + inputStream.read(fontInfo, 0, len); + font.info = new String(fontInfo, "UTF8"); + // System.out.println(font.info); + + byte[] buf = new byte[getInt32(inputStream)]; + inputStream.read(buf, 0, buf.length); + Decompressor decompressor = new Decompressor(buf); + ByteArrayInputStream stream = + new ByteArrayInputStream(decompressor.getDecompressedData()); + + font.unitsPerEm = getInt32(stream); + font.bBoxLLx = getInt32(stream); + font.bBoxLLy = getInt32(stream); + font.bBoxURx = getInt32(stream); + font.bBoxURy = getInt32(stream); + font.ascent = getInt32(stream); + font.descent = getInt32(stream); + font.firstChar = getInt32(stream); + font.lastChar = getInt32(stream); + font.capHeight = getInt32(stream); + font.underlinePosition = getInt32(stream); + font.underlineThickness = getInt32(stream); + + len = getInt32(stream); + font.advanceWidth = new int[len]; + for (int i = 0; i < len; i++) { + font.advanceWidth[i] = getInt16(stream); + } + + len = getInt32(stream); + font.glyphWidth = new int[len]; + for (int i = 0; i < len; i++) { + font.glyphWidth[i] = getInt16(stream); + } + + len = getInt32(stream); + font.unicodeToGID = new int[len]; + for (int i = 0; i < len; i++) { + font.unicodeToGID[i] = getInt16(stream); + } + + font.cff = (inputStream.read() == 'Y') ? true : false; + font.uncompressed_size = getInt32(inputStream); + font.compressed_size = getInt32(inputStream); + + embedFontFile(pdf, font, inputStream); + addFontDescriptorObject(pdf, font); + addCIDFontDictionaryObject(pdf, font); + addToUnicodeCMapObject(pdf, font); + + // Type0 Font Dictionary + pdf.newobj(); + pdf.append("<<\n"); + pdf.append("/Type /Font\n"); + pdf.append("/Subtype /Type0\n"); + pdf.append("/BaseFont /"); + pdf.append(font.name); + pdf.append('\n'); + pdf.append("/Encoding /Identity-H\n"); + pdf.append("/DescendantFonts ["); + pdf.append(font.getCidFontDictObjNumber()); + pdf.append(" 0 R]\n"); + pdf.append("/ToUnicode "); + pdf.append(font.getToUnicodeCMapObjNumber()); + pdf.append(" 0 R\n"); + pdf.append(">>\n"); + pdf.endobj(); + + font.objNumber = pdf.objNumber; + } + + + private static void embedFontFile( + PDF pdf, Font font, InputStream inputStream) throws Exception { + + // Check if the font file is already embedded + for (int i = 0; i < pdf.fonts.size(); i++) { + Font f = pdf.fonts.get(i); + if (f.name.equals(font.name) && f.fileObjNumber != -1) { + font.fileObjNumber = f.fileObjNumber; + return; + } + } + + int metadataObjNumber = pdf.addMetadataObject(font.info, true); + + pdf.newobj(); + pdf.append("<<\n"); + + pdf.append("/Metadata "); + pdf.append(metadataObjNumber); + pdf.append(" 0 R\n"); + + if (font.cff) { + pdf.append("/Subtype /CIDFontType0C\n"); + } + pdf.append("/Filter /FlateDecode\n"); + pdf.append("/Length "); + pdf.append(font.compressed_size); + pdf.append("\n"); + + if (!font.cff) { + pdf.append("/Length1 "); + pdf.append(font.uncompressed_size); + pdf.append('\n'); + } + + pdf.append(">>\n"); + pdf.append("stream\n"); + // byte[] buf = new byte[2048]; + byte[] buf = new byte[16384]; + int len; + while ((len = inputStream.read(buf, 0, buf.length)) > 0) { + pdf.append(buf, 0, len); + } + inputStream.close(); + pdf.append("\nendstream\n"); + pdf.endobj(); + + font.fileObjNumber = pdf.objNumber; + } + + + private static void addFontDescriptorObject(PDF pdf, Font font) throws Exception { + float factor = 1000f / font.unitsPerEm; + + for (int i = 0; i < pdf.fonts.size(); i++) { + Font f = pdf.fonts.get(i); + if (f.name.equals(font.name) && f.getFontDescriptorObjNumber() != -1) { + font.setFontDescriptorObjNumber(f.getFontDescriptorObjNumber()); + return; + } + } + + pdf.newobj(); + pdf.append("<<\n"); + pdf.append("/Type /FontDescriptor\n"); + pdf.append("/FontName /"); + pdf.append(font.name); + pdf.append('\n'); + if (font.cff) { + pdf.append("/FontFile3 "); + } + else { + pdf.append("/FontFile2 "); + } + pdf.append(font.fileObjNumber); + pdf.append(" 0 R\n"); + pdf.append("/Flags 32\n"); + pdf.append("/FontBBox ["); + pdf.append((int) (font.bBoxLLx * factor)); + pdf.append(' '); + pdf.append((int) (font.bBoxLLy * factor)); + pdf.append(' '); + pdf.append((int) (font.bBoxURx * factor)); + pdf.append(' '); + pdf.append((int) (font.bBoxURy * factor)); + pdf.append("]\n"); + pdf.append("/Ascent "); + pdf.append((int) (font.ascent * factor)); + pdf.append('\n'); + pdf.append("/Descent "); + pdf.append((int) (font.descent * factor)); + pdf.append('\n'); + pdf.append("/ItalicAngle 0\n"); + pdf.append("/CapHeight "); + pdf.append((int) (font.capHeight * factor)); + pdf.append('\n'); + pdf.append("/StemV 79\n"); + pdf.append(">>\n"); + pdf.endobj(); + + font.setFontDescriptorObjNumber(pdf.objNumber); + } + + + private static void addToUnicodeCMapObject(PDF pdf, Font font) throws Exception { + + for (int i = 0; i < pdf.fonts.size(); i++) { + Font f = pdf.fonts.get(i); + if (f.name.equals(font.name) && f.getToUnicodeCMapObjNumber() != -1) { + font.setToUnicodeCMapObjNumber(f.getToUnicodeCMapObjNumber()); + return; + } + } + + StringBuilder sb = new StringBuilder(); + + sb.append("/CIDInit /ProcSet findresource begin\n"); + sb.append("12 dict begin\n"); + sb.append("begincmap\n"); + sb.append("/CIDSystemInfo <> def\n"); + sb.append("/CMapName /Adobe-Identity def\n"); + sb.append("/CMapType 2 def\n"); + + sb.append("1 begincodespacerange\n"); + sb.append("<0000> \n"); + sb.append("endcodespacerange\n"); + + List list = new ArrayList(); + StringBuilder buf = new StringBuilder(); + for (int cid = 0; cid <= 0xffff; cid++) { + int gid = font.unicodeToGID[cid]; + if (gid > 0) { + buf.append('<'); + buf.append(toHexString(gid)); + buf.append("> <"); + buf.append(toHexString(cid)); + buf.append(">\n"); + list.add(buf.toString()); + buf.setLength(0); + if (list.size() == 100) { + writeListToBuffer(list, sb); + } + } + } + if (list.size() > 0) { + writeListToBuffer(list, sb); + } + + sb.append("endcmap\n"); + sb.append("CMapName currentdict /CMap defineresource pop\n"); + sb.append("end\nend"); + + pdf.newobj(); + pdf.append("<<\n"); + pdf.append("/Length "); + pdf.append(sb.length()); + pdf.append("\n"); + pdf.append(">>\n"); + pdf.append("stream\n"); + pdf.append(sb.toString()); + pdf.append("\nendstream\n"); + pdf.endobj(); + + font.setToUnicodeCMapObjNumber(pdf.objNumber); + } + + + private static void addCIDFontDictionaryObject(PDF pdf, Font font) throws Exception { + + for (int i = 0; i < pdf.fonts.size(); i++) { + Font f = pdf.fonts.get(i); + if (f.name.equals(font.name) && f.getCidFontDictObjNumber() != -1) { + font.setCidFontDictObjNumber(f.getCidFontDictObjNumber()); + return; + } + } + + pdf.newobj(); + pdf.append("<<\n"); + pdf.append("/Type /Font\n"); + if (font.cff) { + pdf.append("/Subtype /CIDFontType0\n"); + } + else { + pdf.append("/Subtype /CIDFontType2\n"); + } + pdf.append("/BaseFont /"); + pdf.append(font.name); + pdf.append('\n'); + pdf.append("/CIDSystemInfo <>\n"); + pdf.append("/FontDescriptor "); + pdf.append(font.getFontDescriptorObjNumber()); + pdf.append(" 0 R\n"); + pdf.append("/DW "); + pdf.append((int) + ((1000f / font.unitsPerEm) * font.advanceWidth[0])); + pdf.append('\n'); + pdf.append("/W [0[\n"); + for (int i = 0; i < font.advanceWidth.length; i++) { + pdf.append((int) + ((1000f / font.unitsPerEm) * font.advanceWidth[i])); + pdf.append(' '); + } + pdf.append("]]\n"); + pdf.append("/CIDToGIDMap /Identity\n"); + pdf.append(">>\n"); + pdf.endobj(); + + font.setCidFontDictObjNumber(pdf.objNumber); + } + + + private static String toHexString(int code) { + String str = Integer.toHexString(code); + if (str.length() == 1) { + return "000" + str; + } + else if (str.length() == 2) { + return "00" + str; + } + else if (str.length() == 3) { + return "0" + str; + } + return str; + } + + + private static void writeListToBuffer(List list, StringBuilder sb) { + sb.append(list.size()); + sb.append(" beginbfchar\n"); + for (String str : list) { + sb.append(str); + } + sb.append("endbfchar\n"); + list.clear(); + } + + + private static int getInt16(InputStream stream) throws Exception { + return stream.read() << 8 | stream.read(); + } + + + private static int getInt24(InputStream stream) throws Exception { + return stream.read() << 16 | + stream.read() << 8 | stream.read(); + } + + + private static int getInt32(InputStream stream) throws Exception { + return stream.read() << 24 | stream.read() << 16 | + stream.read() << 8 | stream.read(); + } + +} // End of FastFont.java diff --git a/PDFJet/src/main/java/com/pdfjet/FastFont2.java b/PDFJet/src/main/java/com/pdfjet/FastFont2.java new file mode 100644 index 0000000..2d016d4 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/FastFont2.java @@ -0,0 +1,397 @@ +/** + * FastFont2.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + +import java.io.*; +import java.util.*; +import java.util.zip.*; + + +class FastFont2 { + + protected static void register( + Map objects, + Font font, + InputStream inputStream) throws Exception { + + int len = inputStream.read(); + byte[] fontName = new byte[len]; + inputStream.read(fontName, 0, len); + font.name = new String(fontName, "UTF8"); + // System.out.println(font.name); + + len = getInt24(inputStream); + byte[] fontInfo = new byte[len]; + inputStream.read(fontInfo, 0, len); + font.info = new String(fontInfo, "UTF8"); + // System.out.println(font.info); + + byte[] buf = new byte[getInt32(inputStream)]; + inputStream.read(buf, 0, buf.length); + Decompressor decompressor = new Decompressor(buf); + ByteArrayInputStream stream = + new ByteArrayInputStream(decompressor.getDecompressedData()); + + font.unitsPerEm = getInt32(stream); + font.bBoxLLx = getInt32(stream); + font.bBoxLLy = getInt32(stream); + font.bBoxURx = getInt32(stream); + font.bBoxURy = getInt32(stream); + font.ascent = getInt32(stream); + font.descent = getInt32(stream); + font.firstChar = getInt32(stream); + font.lastChar = getInt32(stream); + font.capHeight = getInt32(stream); + font.underlinePosition = getInt32(stream); + font.underlineThickness = getInt32(stream); + + len = getInt32(stream); + font.advanceWidth = new int[len]; + for (int i = 0; i < len; i++) { + font.advanceWidth[i] = getInt16(stream); + } + + len = getInt32(stream); + font.glyphWidth = new int[len]; + for (int i = 0; i < len; i++) { + font.glyphWidth[i] = getInt16(stream); + } + + len = getInt32(stream); + font.unicodeToGID = new int[len]; + for (int i = 0; i < len; i++) { + font.unicodeToGID[i] = getInt16(stream); + } + + font.cff = (inputStream.read() == 'Y') ? true : false; + font.uncompressed_size = getInt32(inputStream); + font.compressed_size = getInt32(inputStream); + + embedFontFile(objects, font, inputStream); + addFontDescriptorObject(objects, font); + addCIDFontDictionaryObject(objects, font); + addToUnicodeCMapObject(objects, font); + + // Type0 Font Dictionary + PDFobj obj = new PDFobj(); + List dict = obj.getDict(); + dict.add("<<"); + dict.add("/Type"); + dict.add("/Font"); + dict.add("/Subtype"); + dict.add("/Type0"); + dict.add("/BaseFont"); + dict.add("/" + font.name); + dict.add("/Encoding"); + dict.add("/Identity-H"); + dict.add("/DescendantFonts"); + dict.add("["); + dict.add(String.valueOf(font.getCidFontDictObjNumber())); + dict.add("0"); + dict.add("R"); + dict.add("]"); + dict.add("/ToUnicode"); + dict.add(String.valueOf(font.getToUnicodeCMapObjNumber())); + dict.add("0"); + dict.add("R"); + dict.add(">>"); + obj.number = Collections.max(objects.keySet()) + 1; + objects.put(obj.number, obj); + font.objNumber = obj.number; + } + + + private static int addMetadataObject( + Map objects, Font font) throws Exception { + + StringBuilder sb = new StringBuilder(); + sb.append("\n"); + sb.append("\n"); + sb.append("\n"); + sb.append("\n"); + sb.append("\n"); + sb.append("\n"); + sb.append("\n"); + sb.append(font.info); + sb.append("\n"); + sb.append("\n"); + sb.append("\n"); + sb.append("\n"); + sb.append("\n"); + sb.append("\n"); + sb.append(""); + + byte[] xml = sb.toString().getBytes("UTF-8"); + + // This is the metadata object + PDFobj obj = new PDFobj(); + List dict = obj.getDict(); + dict.add("<<"); + dict.add("/Type"); + dict.add("/Metadata"); + dict.add("/Subtype"); + dict.add("/XML"); + dict.add("/Length"); + dict.add(String.valueOf(xml.length)); + dict.add(">>"); + obj.setStream(xml); + obj.number = Collections.max(objects.keySet()) + 1; + objects.put(obj.number, obj); + + return obj.number; + } + + + private static void embedFontFile( + Map objects, + Font font, + InputStream inputStream) throws Exception { + + int metadataObjNumber = addMetadataObject(objects, font); + + PDFobj obj = new PDFobj(); + List dict = obj.getDict(); + dict.add("<<"); + dict.add("/Metadata"); + dict.add(String.valueOf(metadataObjNumber)); + dict.add("0"); + dict.add("R"); + dict.add("/Filter"); + dict.add("/FlateDecode"); + dict.add("/Length"); + dict.add(String.valueOf(font.compressed_size)); + if (font.cff) { + dict.add("/Subtype"); + dict.add("/CIDFontType0C"); + } + else { + dict.add("/Length1"); + dict.add(String.valueOf(font.uncompressed_size)); + } + dict.add(">>"); + ByteArrayOutputStream buf2 = new ByteArrayOutputStream(); + byte[] buf = new byte[16384]; + int len; + while ((len = inputStream.read(buf, 0, buf.length)) > 0) { + buf2.write(buf, 0, len); + } + inputStream.close(); + obj.setStream(buf2.toByteArray()); + obj.number = Collections.max(objects.keySet()) + 1; + objects.put(obj.number, obj); + font.fileObjNumber = obj.number; + } + + + private static void addFontDescriptorObject( + Map objects, Font font) throws Exception { + + float factor = 1000f / font.unitsPerEm; + + PDFobj obj = new PDFobj(); + List dict = obj.getDict(); + dict.add("<<"); + dict.add("/Type"); + dict.add("/FontDescriptor"); + dict.add("/FontName"); + dict.add("/" + font.name); + dict.add("/FontFile" + (font.cff ? "3" : "2")); + dict.add(String.valueOf(font.fileObjNumber)); + dict.add("0"); + dict.add("R"); + dict.add("/Flags"); + dict.add("32"); + dict.add("/FontBBox"); + dict.add("["); + dict.add(String.valueOf((int) (font.bBoxLLx * factor))); + dict.add(String.valueOf((int) (font.bBoxLLy * factor))); + dict.add(String.valueOf((int) (font.bBoxURx * factor))); + dict.add(String.valueOf((int) (font.bBoxURy * factor))); + dict.add("]"); + dict.add("/Ascent"); + dict.add(String.valueOf((int) (font.ascent * factor))); + dict.add("/Descent"); + dict.add(String.valueOf((int) (font.descent * factor))); + dict.add("/ItalicAngle"); + dict.add("0"); + dict.add("/CapHeight"); + dict.add(String.valueOf((int) (font.capHeight * factor))); + dict.add("/StemV"); + dict.add("79"); + dict.add(">>"); + obj.number = Collections.max(objects.keySet()) + 1; + objects.put(obj.number, obj); + font.setFontDescriptorObjNumber(obj.number); + } + + + private static void addToUnicodeCMapObject( + Map objects, Font font) throws Exception { + + StringBuilder sb = new StringBuilder(); + + sb.append("/CIDInit /ProcSet findresource begin\n"); + sb.append("12 dict begin\n"); + sb.append("begincmap\n"); + sb.append("/CIDSystemInfo <> def\n"); + sb.append("/CMapName /Adobe-Identity def\n"); + sb.append("/CMapType 2 def\n"); + + sb.append("1 begincodespacerange\n"); + sb.append("<0000> \n"); + sb.append("endcodespacerange\n"); + + List list = new ArrayList(); + StringBuilder buf = new StringBuilder(); + for (int cid = 0; cid <= 0xffff; cid++) { + int gid = font.unicodeToGID[cid]; + if (gid > 0) { + buf.append('<'); + buf.append(toHexString(gid)); + buf.append("> <"); + buf.append(toHexString(cid)); + buf.append(">\n"); + list.add(buf.toString()); + buf.setLength(0); + if (list.size() == 100) { + writeListToBuffer(list, sb); + } + } + } + if (list.size() > 0) { + writeListToBuffer(list, sb); + } + sb.append("endcmap\n"); + sb.append("CMapName currentdict /CMap defineresource pop\n"); + sb.append("end\nend"); + + PDFobj obj = new PDFobj(); + List dict = obj.getDict(); + dict.add("<<"); + dict.add("/Length"); + dict.add(String.valueOf(sb.length())); + dict.add(">>"); + obj.setStream(sb.toString().getBytes("UTF-8")); + obj.number = Collections.max(objects.keySet()) + 1; + objects.put(obj.number, obj); + font.setToUnicodeCMapObjNumber(obj.number); + } + + + private static void addCIDFontDictionaryObject( + Map objects, Font font) throws Exception { + + PDFobj obj = new PDFobj(); + List dict = obj.getDict(); + dict.add("<<"); + dict.add("/Type"); + dict.add("/Font"); + dict.add("/Subtype"); + dict.add("/CIDFontType" + (font.cff ? "0" : "2")); + dict.add("/BaseFont"); + dict.add("/" + font.name); + dict.add("/CIDSystemInfo"); + dict.add("<<"); + dict.add("/Registry"); + dict.add("(Adobe)"); + dict.add("/Ordering"); + dict.add("(Identity)"); + dict.add("/Supplement"); + dict.add("0"); + dict.add(">>"); + dict.add("/FontDescriptor"); + dict.add(String.valueOf(font.getFontDescriptorObjNumber())); + dict.add("0"); + dict.add("R"); + dict.add("/DW"); + dict.add(String.valueOf((int) + ((1000f / font.unitsPerEm) * font.advanceWidth[0]))); + dict.add("/W"); + dict.add("["); + dict.add("0"); + dict.add("["); + for (int i = 0; i < font.advanceWidth.length; i++) { + dict.add(String.valueOf((int) + ((1000f / font.unitsPerEm) * font.advanceWidth[i]))); + } + dict.add("]"); + dict.add("]"); + dict.add("/CIDToGIDMap"); + dict.add("/Identity"); + dict.add(">>"); + obj.number = Collections.max(objects.keySet()) + 1; + objects.put(obj.number, obj); + font.setCidFontDictObjNumber(obj.number); + } + + + private static String toHexString(int code) { + String str = Integer.toHexString(code); + if (str.length() == 1) { + return "000" + str; + } + else if (str.length() == 2) { + return "00" + str; + } + else if (str.length() == 3) { + return "0" + str; + } + return str; + } + + + private static void writeListToBuffer(List list, StringBuilder sb) { + sb.append(list.size()); + sb.append(" beginbfchar\n"); + for (String str : list) { + sb.append(str); + } + sb.append("endbfchar\n"); + list.clear(); + } + + + private static int getInt16(InputStream stream) throws Exception { + return stream.read() << 8 | stream.read(); + } + + + private static int getInt24(InputStream stream) throws Exception { + return stream.read() << 16 | + stream.read() << 8 | stream.read(); + } + + + private static int getInt32(InputStream stream) throws Exception { + return stream.read() << 24 | stream.read() << 16 | + stream.read() << 8 | stream.read(); + } + +} // End of FastFont2.java diff --git a/PDFJet/src/main/java/com/pdfjet/Field.java b/PDFJet/src/main/java/com/pdfjet/Field.java new file mode 100644 index 0000000..bd1754d --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Field.java @@ -0,0 +1,75 @@ +/** + * Field.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + + +/** + * Please see Example_45 + */ +public class Field { + + float x; + String[] values; + String[] altDescription; + String[] actualText; + boolean format = false; + + + public Field(float x, String[] values) { + this(x, values, false); + } + + public Field(float x, String[] values, boolean format) { + this.x = x; + this.values = values; + this.format = format; + if (values != null) { + this.altDescription = new String[values.length]; + this.actualText = new String[values.length]; + for (int i = 0; i < values.length; i++) { + this.altDescription[i] = values[i]; + this.actualText[i] = values[i]; + } + } + } + + + public Field setAltDescription(String altDescription) { + this.altDescription[0] = altDescription; + return this; + } + + + public Field setActualText(String actualText) { + this.actualText[0] = actualText; + return this; + } + +} diff --git a/PDFJet/src/main/java/com/pdfjet/FileAttachment.java b/PDFJet/src/main/java/com/pdfjet/FileAttachment.java new file mode 100644 index 0000000..915a4d0 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/FileAttachment.java @@ -0,0 +1,102 @@ +/** + * FileAttachment.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + + +/** + * Used to attach file objects. + * + */ +public class FileAttachment { + + protected int objNumber = -1; + protected PDF pdf = null; + protected EmbeddedFile embeddedFile = null; + protected String icon = "PushPin"; + protected String title = ""; + protected String contents = "Right mouse click or double click on the icon to save the attached file."; + protected float x = 0f; + protected float y = 0f; + protected float h = 24f; + + + public FileAttachment(PDF pdf, EmbeddedFile file) { + this.pdf = pdf; + this.embeddedFile = file; + } + + + public void setLocation(float x, float y) { + this.x = x; + this.y = y; + } + + + public void setIconPushPin() { + this.icon = "PushPin"; + } + + + public void setIconPaperclip() { + this.icon = "Paperclip"; + } + + + public void setIconSize(float height) { + this.h = height; + } + + + public void setTitle(String title) { + this.title = title; + } + + + public void setDescription(String description) { + this.contents = description; + } + + + public void drawOn(Page page) throws Exception { + Annotation annotation = new Annotation( + null, + null, + x, + page.height - y, + x + h, + page.height - (y + h), + null, + null, + null); + annotation.fileAttachment = this; + page.annots.add(annotation); + } + +} // End of FileAttachment.java diff --git a/PDFJet/src/main/java/com/pdfjet/Font.java b/PDFJet/src/main/java/com/pdfjet/Font.java new file mode 100644 index 0000000..91c1048 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Font.java @@ -0,0 +1,677 @@ +/** + * Font.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + +import java.io.InputStream; +import java.util.Collections; +import java.util.HashSet; +import java.util.Map; + + +/** + * Used to create font objects. + * The font objects must added to the PDF before they can be used to draw text. + * + */ +public class Font { + + // Chinese (Traditional) font + public static final String AdobeMingStd_Light = "AdobeMingStd-Light"; + + // Chinese (Simplified) font + public static final String STHeitiSC_Light = "STHeitiSC-Light"; + + // Japanese font + public static final String KozMinProVI_Regular = "KozMinProVI-Regular"; + + // Korean font + public static final String AdobeMyungjoStd_Medium = "AdobeMyungjoStd-Medium"; + + public static final boolean STREAM = true; + + protected String name; + protected String info; + protected int objNumber; + + // The object number of the embedded font file + protected int fileObjNumber = -1; + + // Font attributes + protected int unitsPerEm = 1000; + protected float size = 12.0f; + protected float ascent; + protected float descent; + protected float capHeight; + protected float body_height; + + // Font metrics + protected int[][] metrics = null; + + // Don't change the following default values! + protected boolean isCoreFont = false; + protected boolean isCJK = false; + protected int firstChar = 32; + protected int lastChar = 255; + protected boolean skew15 = false; + protected boolean kernPairs = false; + + // Font bounding box + protected float bBoxLLx; + protected float bBoxLLy; + protected float bBoxURx; + protected float bBoxURy; + protected float underlinePosition; + protected float underlineThickness; + + protected int compressed_size; + protected int uncompressed_size; + + protected int[] advanceWidth = null; + protected int[] glyphWidth = null; + protected int[] unicodeToGID; + protected boolean cff; + + protected String fontID; + + private int fontDescriptorObjNumber = -1; + private int cMapObjNumber = -1; + private int cidFontDictObjNumber = -1; + private int toUnicodeCMapObjNumber = -1; + private int widthsArrayObjNumber = -1; + private int encodingObjNumber = -1; + private int codePage = CodePage.UNICODE; + private int fontUnderlinePosition = 0; + private int fontUnderlineThickness = 0; + + + /** + * Constructor for the 14 standard fonts. + * Creates a font object and adds it to the PDF. + * + *
+     *  Examples:
+     *      Font font1 = new Font(pdf, CoreFont.HELVETICA);
+     *      Font font2 = new Font(pdf, CoreFont.TIMES_ITALIC);
+     *      Font font3 = new Font(pdf, CoreFont.ZAPF_DINGBATS);
+     *      ...
+     *  
+ * + * @param pdf the PDF to add this font to. + * @param coreFont the core font. Must be one the names defined in the CoreFont class. + */ + public Font(PDF pdf, CoreFont coreFont) throws Exception { + this.isCoreFont = true; + StandardFont font = StandardFont.getInstance(coreFont); + this.name = font.name; + this.bBoxLLx = font.bBoxLLx; + this.bBoxLLy = font.bBoxLLy; + this.bBoxURx = font.bBoxURx; + this.bBoxURy = font.bBoxURy; + this.metrics = font.metrics; + this.ascent = bBoxURy * size / unitsPerEm; + this.descent = bBoxLLy * size / unitsPerEm; + this.body_height = ascent - descent; + this.fontUnderlinePosition = font.underlinePosition; + this.fontUnderlineThickness = font.underlineThickness; + this.underlineThickness = fontUnderlineThickness * size / unitsPerEm; + this.underlinePosition = fontUnderlinePosition * size / -unitsPerEm + underlineThickness / 2.0f; + + pdf.newobj(); + pdf.append("<<\n"); + pdf.append("/Type /Font\n"); + pdf.append("/Subtype /Type1\n"); + pdf.append("/BaseFont /"); + pdf.append(this.name); + pdf.append('\n'); + if (!this.name.equals("Symbol") && !this.name.equals("ZapfDingbats")) { + pdf.append("/Encoding /WinAnsiEncoding\n"); + } + pdf.append(">>\n"); + pdf.endobj(); + objNumber = pdf.objNumber; + + pdf.fonts.add(this); + } + + + // Used by PDFobj + protected Font(CoreFont coreFont) { + this.isCoreFont = true; + StandardFont font = StandardFont.getInstance(coreFont); + this.name = font.name; + this.bBoxLLx = font.bBoxLLx; + this.bBoxLLy = font.bBoxLLy; + this.bBoxURx = font.bBoxURx; + this.bBoxURy = font.bBoxURy; + this.metrics = font.metrics; + this.ascent = bBoxURy * size / unitsPerEm; + this.descent = bBoxLLy * size / unitsPerEm; + this.body_height = ascent - descent; + this.fontUnderlinePosition = font.underlinePosition; + this.fontUnderlineThickness = font.underlineThickness; + this.underlineThickness = fontUnderlineThickness * size / unitsPerEm; + this.underlinePosition = fontUnderlinePosition * size / -unitsPerEm + underlineThickness / 2.0f; + } + + + public Font(PDF pdf, String fontName) throws Exception { + this(pdf, fontName, CodePage.UNICODE); + } + + + /** + * Constructor for CJK - Chinese, Japanese and Korean fonts. + * Please see Example_04. + * + * @param pdf the PDF to add this font to. + * @param fontName the font name. Please see Example_04. + * @param codePage the code page. Must be: CodePage.UNICODE + */ + public Font(PDF pdf, String fontName, int codePage) throws Exception { + this.name = fontName; + isCJK = true; + + firstChar = 0x0020; + lastChar = 0xFFEE; + + // Font Descriptor + pdf.newobj(); + pdf.append("<<\n"); + pdf.append("/Type /FontDescriptor\n"); + pdf.append("/FontName /"); + pdf.append(fontName); + pdf.append('\n'); + pdf.append("/Flags 4\n"); + pdf.append("/FontBBox [0 0 0 0]\n"); + pdf.append(">>\n"); + pdf.endobj(); + + // CIDFont Dictionary + pdf.newobj(); + pdf.append("<<\n"); + pdf.append("/Type /Font\n"); + pdf.append("/Subtype /CIDFontType0\n"); + pdf.append("/BaseFont /"); + pdf.append(fontName); + pdf.append('\n'); + pdf.append("/FontDescriptor "); + pdf.append(pdf.objNumber - 1); + pdf.append(" 0 R\n"); + pdf.append("/CIDSystemInfo <<\n"); + pdf.append("/Registry (Adobe)\n"); + if (fontName.startsWith("AdobeMingStd")) { + pdf.append("/Ordering (CNS1)\n"); + pdf.append("/Supplement 4\n"); + } else if (fontName.startsWith("AdobeSongStd") + || fontName.startsWith("STHeitiSC")) { + pdf.append("/Ordering (GB1)\n"); + pdf.append("/Supplement 4\n"); + } else if (fontName.startsWith("KozMinPro")) { + pdf.append("/Ordering (Japan1)\n"); + pdf.append("/Supplement 4\n"); + } else if (fontName.startsWith("AdobeMyungjoStd")) { + pdf.append("/Ordering (Korea1)\n"); + pdf.append("/Supplement 1\n"); + } else { + throw new Exception("Unsupported font: " + fontName); + } + pdf.append(">>\n"); + pdf.append(">>\n"); + pdf.endobj(); + + // Type0 Font Dictionary + pdf.newobj(); + pdf.append("<<\n"); + pdf.append("/Type /Font\n"); + pdf.append("/Subtype /Type0\n"); + pdf.append("/BaseFont /"); + if (fontName.startsWith("AdobeMingStd")) { + pdf.append(fontName + "-UniCNS-UTF16-H\n"); + pdf.append("/Encoding /UniCNS-UTF16-H\n"); + } else if (fontName.startsWith("AdobeSongStd") + || fontName.startsWith("STHeitiSC")) { + pdf.append(fontName + "-UniGB-UTF16-H\n"); + pdf.append("/Encoding /UniGB-UTF16-H\n"); + } else if (fontName.startsWith("KozMinPro")) { + pdf.append(fontName + "-UniJIS-UCS2-H\n"); + pdf.append("/Encoding /UniJIS-UCS2-H\n"); + } else if (fontName.startsWith("AdobeMyungjoStd")) { + pdf.append(fontName + "-UniKS-UCS2-H\n"); + pdf.append("/Encoding /UniKS-UCS2-H\n"); + } else { + throw new Exception("Unsupported font: " + fontName); + } + pdf.append("/DescendantFonts ["); + pdf.append(pdf.objNumber - 1); + pdf.append(" 0 R]\n"); + pdf.append(">>\n"); + pdf.endobj(); + objNumber = pdf.objNumber; + + ascent = size; + descent = -ascent/4; + body_height = ascent - descent; + + pdf.fonts.add(this); + } + + + // Constructor for .ttf.stream fonts: + public Font(PDF pdf, InputStream inputStream, boolean flag) throws Exception { + FastFont.register(pdf, this, inputStream); + + this.ascent = bBoxURy * size / unitsPerEm; + this.descent = bBoxLLy * size / unitsPerEm; + this.body_height = ascent - descent; + this.underlineThickness = fontUnderlineThickness * size / unitsPerEm; + this.underlinePosition = fontUnderlinePosition * size / -unitsPerEm + underlineThickness / 2f; + + pdf.fonts.add(this); + } + + + // Constructor for .ttf.stream fonts: + public Font(Map objects, InputStream inputStream, boolean flag) throws Exception { + FastFont2.register(objects, this, inputStream); + + this.ascent = bBoxURy * size / unitsPerEm; + this.descent = bBoxLLy * size / unitsPerEm; + this.body_height = ascent - descent; + this.underlineThickness = fontUnderlineThickness * size / unitsPerEm; + this.underlinePosition = fontUnderlinePosition * size / -unitsPerEm + underlineThickness / 2f; + } + + + protected int getFontDescriptorObjNumber() { + return fontDescriptorObjNumber; + } + + + protected int getCMapObjNumber() { + return cMapObjNumber; + } + + + protected int getCidFontDictObjNumber() { + return cidFontDictObjNumber; + } + + + protected int getToUnicodeCMapObjNumber() { + return toUnicodeCMapObjNumber; + } + + + protected int getWidthsArrayObjNumber() { + return widthsArrayObjNumber; + } + + + protected int getEncodingObjNumber() { + return encodingObjNumber; + } + + + public float getUnderlinePosition() { + return underlinePosition; + } + + + public float getUnderlineThickness() { + return underlineThickness; + } + + + protected void setFontDescriptorObjNumber(int fontDescriptorObjNumber) { + this.fontDescriptorObjNumber = fontDescriptorObjNumber; + } + + + protected void setCMapObjNumber(int cMapObjNumber) { + this.cMapObjNumber = cMapObjNumber; + } + + + protected void setCidFontDictObjNumber(int cidFontDictObjNumber) { + this.cidFontDictObjNumber = cidFontDictObjNumber; + } + + + protected void setToUnicodeCMapObjNumber(int toUnicodeCMapObjNumber) { + this.toUnicodeCMapObjNumber = toUnicodeCMapObjNumber; + } + + + protected void setWidthsArrayObjNumber(int widthsArrayObjNumber) { + this.widthsArrayObjNumber = widthsArrayObjNumber; + } + + + protected void setEncodingObjNumber(int encodingObjNumber) { + this.encodingObjNumber = encodingObjNumber; + } + + + /** + * Sets the size of this font. + * + * @param fontSize specifies the size of this font. + * @return the font. + */ + public Font setSize(double fontSize) { + return setSize((float) fontSize); + } + + + /** + * Sets the size of this font. + * + * @param fontSize specifies the size of this font. + * @return the font. + */ + public Font setSize(float fontSize) { + size = fontSize; + if (isCJK) { + ascent = size; + descent = -ascent/4; + return this; + } + this.ascent = bBoxURy * size / unitsPerEm; + this.descent = bBoxLLy * size / unitsPerEm; + this.body_height = ascent - descent; + this.underlineThickness = fontUnderlineThickness * size / unitsPerEm; + this.underlinePosition = fontUnderlinePosition * size / -unitsPerEm + underlineThickness / 2.0f; + return this; + } + + + /** + * Returns the current font size. + * + * @return the current size of the font. + */ + public float getSize() { + return size; + } + + + /** + * Sets the kerning for the selected font to 'true' or 'false' depending on the passed value of kernPairs parameter. + * The kerning is implemented only for the 14 standard fonts. + * + * @param kernPairs if 'true' the kerning for this font is enabled. + */ + public void setKernPairs(boolean kernPairs) { + this.kernPairs = kernPairs; + } + + + /** + * Returns the width of the specified string when drawn on the page with this font using the current font size. + * + * @param str the specified string. + * + * @return the width of the string when draw on the page with this font using the current selected size. + */ + public float stringWidth(String str) { + if (str == null) { + return 0f; + } + + if (isCJK) { + return str.length() * ascent; + } + + int width = 0; + for (int i = 0; i < str.length(); i++) { + int c1 = str.charAt(i); + if (isCoreFont) { + if (c1 < firstChar || c1 > lastChar) { + c1 = 0x20; + } + c1 -= 32; + + width += metrics[c1][1]; + + if (kernPairs && i < (str.length() - 1)) { + int c2 = str.charAt(i + 1); + if (c2 < firstChar || c2 > lastChar) { + c2 = 32; + } + for (int j = 2; j < metrics[c1].length; j += 2) { + if (metrics[c1][j] == c2) { + width += metrics[c1][j + 1]; + break; + } + } + } + } + else { + if (c1 < firstChar || c1 > lastChar) { + width += advanceWidth[0]; + } else { + width += glyphWidth[c1]; + } + } + } + + return width * size / unitsPerEm; + } + + + /** + * Returns the ascent of this font. + * + * @return the ascent of the font. + */ + public float getAscent() { + return ascent; + } + + + /** + * Returns the descent of this font. + * + * @return the descent of the font. + */ + public float getDescent() { + return -descent; + } + + + /** + * Returns the height of this font. + * + * @return the height of the font. + */ + public float getHeight() { + return ascent - descent; + } + + + /** + * Returns the height of the body of the font. + * + * @return float the height of the body of the font. + */ + public float getBodyHeight() { + return body_height; + } + + + /** + * Returns the number of characters from the specified string that will fit within the specified width. + * + * @param str the specified string. + * @param width the specified width. + * + * @return the number of characters that will fit. + */ + public int getFitChars(String str, double width) { + return getFitChars(str, (float) width); + } + + + /** + * Returns the number of characters from the specified string that will fit within the specified width. + * + * @param str the specified string. + * @param width the specified width. + * + * @return the number of characters that will fit. + */ + public int getFitChars(String str, float width) { + + float w = width * unitsPerEm / size; + + if (isCJK) { + return (int) (w / ascent); + } + + if (isCoreFont) { + return getStandardFontFitChars(str, w); + } + + int i; + for (i = 0; i < str.length(); i++) { + int c1 = str.charAt(i); + + if (c1 < firstChar || c1 > lastChar) { + w -= advanceWidth[0]; + } + else { + w -= glyphWidth[c1]; + } + + if (w < 0) break; + } + + return i; + } + + + private int getStandardFontFitChars(String str, float width) { + float w = width; + + int i = 0; + while (i < str.length()) { + + int c1 = str.charAt(i); + + if (c1 < firstChar || c1 > lastChar) { + c1 = 32; + } + + c1 -= 32; + w -= metrics[c1][1]; + + if (w < 0) { + return i; + } + + if (kernPairs && i < (str.length() - 1)) { + int c2 = str.charAt(i + 1); + if (c2 < firstChar || c2 > lastChar) { + c2 = 32; + } + + for (int j = 2; j < metrics[c1].length; j += 2) { + if (metrics[c1][j] == c2) { + w -= metrics[c1][j + 1]; + if (w < 0) { + return i; + } + break; + } + } + } + + i += 1; + } + + return i; + } + + + /** + * Sets the skew15 private variable. + * When the variable is set to 'true' all glyphs in the font are skewed on 15 degrees. + * This makes a regular font look like an italic type font. + * Use this method when you don't have real italic font in the font family, + * or when you want to generate smaller PDF files. + * For example you could embed only the Regular and Bold fonts and synthesize the RegularItalic and BoldItalic. + * + * @param skew15 the skew flag. + */ + public void setItalic(boolean skew15) { + this.skew15 = skew15; + } + + + /** + * Returns the width of a string drawn using two fonts. + * + * @param font2 the fallback font. + * @param str the string. + * @return the width. + */ + public float stringWidth(Font font2, String str) { + if (font2 == null) { + return stringWidth(str); + } + float width = 0f; + + Font activeFont = this; + StringBuilder buf = new StringBuilder(); + for (int i = 0; i < str.length(); i++) { + int ch = str.charAt(i); + if ((isCJK && ch >= 0x4E00 && ch <= 0x9FCC) + || (!isCJK && unicodeToGID[ch] != 0)) { + if (this != activeFont) { + width += activeFont.stringWidth(buf.toString()); + buf.setLength(0); + activeFont = this; + } + } + else { + if (font2 != activeFont) { + width += activeFont.stringWidth(buf.toString()); + buf.setLength(0); + activeFont = font2; + } + } + buf.append((char) ch); + } + width += activeFont.stringWidth(buf.toString()); + + return width; + } + +} // End of Font.java diff --git a/PDFJet/src/main/java/com/pdfjet/FontTable.java b/PDFJet/src/main/java/com/pdfjet/FontTable.java new file mode 100644 index 0000000..fcf56f4 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/FontTable.java @@ -0,0 +1,38 @@ +/** + * FontTable.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + + +class FontTable { + protected String name; + protected long checkSum; + protected int offset; + protected int length; +} diff --git a/PDFJet/src/main/java/com/pdfjet/Form.java b/PDFJet/src/main/java/com/pdfjet/Form.java new file mode 100644 index 0000000..955d93b --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Form.java @@ -0,0 +1,240 @@ +/** + * Form.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +package com.pdfjet; + +import java.util.*; + + +/** + * Please see Example_45 + */ +public class Form implements Drawable { + + private List fields; + private float x; + private float y; + private Font f1; + private float labelFontSize = 8f; + private Font f2; + private float valueFontSize = 10f; + private int numberOfRows; + private float rowLength = 500f; + private float rowHeight = 12f; + private int labelColor = Color.black; + private int valueColor = Color.blue; + private List endOfLinePoints; + + + public Form(List fields) { + this.fields = fields; + this.endOfLinePoints = new ArrayList(); + } + + + public Form setLocation(float x, float y) { + this.x = x; + this.y = y; + return this; + } + + + public Form setRowLength(float rowLength) { + this.rowLength = rowLength; + return this; + } + + + public Form setRowHeight(float rowHeight) { + this.rowHeight = rowHeight; + return this; + } + + + public Form setLabelFont(Font f1) { + this.f1 = f1; + return this; + } + + + public Form setLabelFontSize(float labelFontSize) { + this.labelFontSize = labelFontSize; + return this; + } + + + public Form setValueFont(Font f2) { + this.f2 = f2; + return this; + } + + + public Form setValueFontSize(float valueFontSize) { + this.valueFontSize = valueFontSize; + return this; + } + + + public Form setLabelColor(int labelColor) { + this.labelColor = labelColor; + return this; + } + + + public Form setValueColor(int valueColor) { + this.valueColor = valueColor; + return this; + } + + + public List getEndOfLinePoints() { + return endOfLinePoints; + } + + + /** + * Draws this Form on the specified page. + * + * @param page the page to draw this form on. + * @return x and y coordinates of the bottom right corner of this component. + * @throws Exception + */ + public float[] drawOn(Page page) throws Exception { + for (Field field : fields) { + if (field.format) { + field.values = format(field.values[0], field.values[1], this.f2, this.rowLength); + field.altDescription = new String[field.values.length]; + field.actualText = new String[field.values.length]; + for (int i = 0; i < field.values.length; i++) { + field.altDescription[i] = field.values[i]; + field.actualText[i] = field.values[i]; + } + } + if (field.x == 0f) { + numberOfRows += field.values.length; + } + } + + if (numberOfRows == 0) { + return new float[] { x, y }; + } + + float boxHeight = rowHeight*numberOfRows; + Box box = new Box(); + box.setLocation(x, y); + box.setSize(rowLength, boxHeight); + box.drawOn(page); + + float field_y = 0f; + int row_span = 1; + float row_y = 0; + for (Field field : fields) { + if (field.x == 0f) { + row_y += row_span*rowHeight; + row_span = field.values.length; + } + field_y = row_y; + for (int i = 0; i < field.values.length; i++) { + Font font = (i == 0) ? f1 : f2; + float fontSize = (i == 0) ? labelFontSize : valueFontSize; + int color = (i == 0) ? labelColor : valueColor; + new TextLine(font, field.values[i]) + .setFontSize(fontSize) + .setColor(color) + .placeIn(box, field.x + f1.getDescent(), field_y - font.getDescent()) + .setAltDescription((i == 0) ? field.altDescription[i] : (field.altDescription[i] + ",")) + .setActualText((i == 0) ? field.actualText[i] : (field.actualText[i] + ",")) + .drawOn(page); + endOfLinePoints.add(new float[] { + field.x + f1.getDescent() + font.stringWidth(field.values[i]), + field_y - font.getDescent(), + }); + if (i == (field.values.length - 1)) { + new Line(0f, 0f, rowLength, 0f) + .placeIn(box, 0f, field_y) + .drawOn(page); + if (field.x != 0f) { + new Line(0f, -(field.values.length-1)*rowHeight, 0f, 0f) + .placeIn(box, field.x, field_y) + .drawOn(page); + } + } + field_y += rowHeight; + } + } + + return new float[] { x + rowLength, y + boxHeight }; + } + + + public static String[] format(String title, String text, Font font, float width) { + + String[] original = text.split("\\r?\\n"); + List lines = new ArrayList(); + StringBuilder buf = new StringBuilder(); + for (int i = 0; i < original.length; i++) { + String line = original[i]; + if (font.stringWidth(line) < width) { + lines.add(line); + continue; + } + + buf.setLength(0); + for (int j = 0; j < line.length(); j++) { + buf.append(line.charAt(j)); + if (font.stringWidth(buf.toString()) > (width - font.stringWidth(" "))) { + while (j > 0 && line.charAt(j) != ' ') { + j -= 1; + } + String str = line.substring(0, j).replaceAll("\\s+$", ""); + lines.add(str); + buf.setLength(0); + while (j < line.length() && line.charAt(j) == ' ') { + j += 1; + } + line = line.substring(j); + j = 0; + } + } + + if (!line.equals("")) { + lines.add(line); + } + } + + int count = lines.size(); + String[] data = new String[1 + count]; + data[0] = title; + for (int i = 0; i < count; i++) { + data[i + 1] = lines.get(i); + } + + return data; + } + +} // End of Form.java diff --git a/PDFJet/src/main/java/com/pdfjet/Glyph.java b/PDFJet/src/main/java/com/pdfjet/Glyph.java new file mode 100644 index 0000000..5922880 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Glyph.java @@ -0,0 +1,265 @@ +/** + * Glyph.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + + +/** + * Should not be used by third party applications. + * It's public only because the AfmCompiler is using it. + * + */ +class Glyph { +static String[] names = { +"space", +"exclam", +"quotedbl", +"numbersign", +"dollar", +"percent", +"ampersand", +"quotesingle", +"parenleft", +"parenright", +"asterisk", +"plus", +"comma", +"hyphen", +"period", +"slash", +"zero", +"one", +"two", +"three", +"four", +"five", +"six", +"seven", +"eight", +"nine", +"colon", +"semicolon", +"less", +"equal", +"greater", +"question", +"at", +"A", +"B", +"C", +"D", +"E", +"F", +"G", +"H", +"I", +"J", +"K", +"L", +"M", +"N", +"O", +"P", +"Q", +"R", +"S", +"T", +"U", +"V", +"W", +"X", +"Y", +"Z", +"bracketleft", +"backslash", +"bracketright", +"asciicircum", +"underscore", +"grave", +"a", +"b", +"c", +"d", +"e", +"f", +"g", +"h", +"i", +"j", +"k", +"l", +"m", +"n", +"o", +"p", +"q", +"r", +"s", +"t", +"u", +"v", +"w", +"x", +"y", +"z", +"braceleft", +"bar", +"braceright", +"asciitilde", +"space", +"Euro", +"space", +"quotesinglbase", +"florin", +"quotedblbase", +"ellipsis", +"dagger", +"daggerdbl", +"circumflex", +"perthousand", +"Scaron", +"guilsinglleft", +"OE", +"space", +"Zcaron", +"space", +"space", +"quoteleft", +"quoteright", +"quotedblleft", +"quotedblright", +"bullet", +"endash", +"emdash", +"tilde", +"trademark", +"scaron", +"guilsinglright", +"oe", +"space", +"zcaron", +"Ydieresis", +"space", +"exclamdown", +"cent", +"sterling", +"currency", +"yen", +"brokenbar", +"section", +"dieresis", +"copyright", +"ordfeminine", +"guillemotleft", +"logicalnot", +"hyphen", +"registered", +"macron", +"degree", +"plusminus", +"twosuperior", +"threesuperior", +"acute", +"mu", +"paragraph", +"periodcentered", +"cedilla", +"onesuperior", +"ordmasculine", +"guillemotright", +"onequarter", +"onehalf", +"threequarters", +"questiondown", +"Agrave", +"Aacute", +"Acircumflex", +"Atilde", +"Adieresis", +"Aring", +"AE", +"Ccedilla", +"Egrave", +"Eacute", +"Ecircumflex", +"Edieresis", +"Igrave", +"Iacute", +"Icircumflex", +"Idieresis", +"Eth", +"Ntilde", +"Ograve", +"Oacute", +"Ocircumflex", +"Otilde", +"Odieresis", +"multiply", +"Oslash", +"Ugrave", +"Uacute", +"Ucircumflex", +"Udieresis", +"Yacute", +"Thorn", +"germandbls", +"agrave", +"aacute", +"acircumflex", +"atilde", +"adieresis", +"aring", +"ae", +"ccedilla", +"egrave", +"eacute", +"ecircumflex", +"edieresis", +"igrave", +"iacute", +"icircumflex", +"idieresis", +"eth", +"ntilde", +"ograve", +"oacute", +"ocircumflex", +"otilde", +"odieresis", +"divide", +"oslash", +"ugrave", +"uacute", +"ucircumflex", +"udieresis", +"yacute", +"thorn", +"ydieresis", +}; +} diff --git a/PDFJet/src/main/java/com/pdfjet/GraphicsState.java b/PDFJet/src/main/java/com/pdfjet/GraphicsState.java new file mode 100644 index 0000000..f58e30a --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/GraphicsState.java @@ -0,0 +1,30 @@ +package com.pdfjet; + + +public class GraphicsState { + + // Default values + private float CA = 1f; + private float ca = 1f; + + public void set_CA(float CA) { + if (CA >= 0f && CA <= 1f) { + this.CA = CA; + } + } + + public float get_CA() { + return this.CA; + } + + public void set_ca(float ca) { + if (ca >= 0f && ca <= 1f) { + this.ca = ca; + } + } + + public float get_ca() { + return this.ca; + } + +} diff --git a/PDFJet/src/main/java/com/pdfjet/Helvetica.java b/PDFJet/src/main/java/com/pdfjet/Helvetica.java new file mode 100644 index 0000000..a6fc832 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Helvetica.java @@ -0,0 +1,238 @@ +package com.pdfjet; + +class Helvetica { + protected static final String name = "Helvetica"; + protected static final int bBoxLLx = -166; + protected static final int bBoxLLy = -225; + protected static final int bBoxURx = 1000; + protected static final int bBoxURy = 931; + protected static final int underlinePosition = -100; + protected static final int underlineThickness = 50; + protected static final String notice = "Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated. All Rights Reserved. Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries."; + protected static final int[][] metrics = { + {32,278,84,-50,86,-50,87,-40,89,-90,221,-90,159,-90,147,-30,145,-60,}, + {33,278,}, + {34,355,}, + {35,556,}, + {36,556,}, + {37,889,}, + {38,667,}, + {39,191,}, + {40,333,}, + {41,333,}, + {42,389,}, + {43,584,}, + {44,278,148,-100,146,-100,}, + {45,333,}, + {46,278,148,-100,146,-100,32,-60,}, + {47,278,}, + {48,556,}, + {49,556,}, + {50,556,}, + {51,556,}, + {52,556,}, + {53,556,}, + {54,556,}, + {55,556,}, + {56,556,}, + {57,556,}, + {58,278,32,-50,}, + {59,278,32,-50,}, + {60,584,}, + {61,584,}, + {62,584,}, + {63,556,}, + {64,1015,}, + {65,667,67,-30,199,-30,71,-30,79,-30,211,-30,212,-30,214,-30,210,-30,216,-30,213,-30,81,-30,84,-120,85,-50,218,-50,219,-50,220,-50,217,-50,86,-70,87,-50,89,-100,221,-100,159,-100,117,-30,250,-30,251,-30,252,-30,249,-30,118,-40,119,-40,121,-40,253,-40,255,-40,}, + {66,667,85,-10,218,-10,219,-10,220,-10,217,-10,44,-20,46,-20,}, + {67,722,44,-30,46,-30,}, + {68,722,65,-40,193,-40,194,-40,196,-40,192,-40,197,-40,195,-40,86,-70,87,-40,89,-90,221,-90,159,-90,44,-70,46,-70,}, + {69,667,}, + {70,611,65,-80,193,-80,194,-80,196,-80,192,-80,197,-80,195,-80,97,-50,225,-50,226,-50,228,-50,224,-50,229,-50,227,-50,44,-150,101,-30,233,-30,234,-30,235,-30,232,-30,111,-30,243,-30,244,-30,246,-30,242,-30,248,-30,245,-30,46,-150,114,-45,}, + {71,778,}, + {72,722,}, + {73,278,}, + {74,500,65,-20,193,-20,194,-20,196,-20,192,-20,197,-20,195,-20,97,-20,225,-20,226,-20,228,-20,224,-20,229,-20,227,-20,44,-30,46,-30,117,-20,250,-20,251,-20,252,-20,249,-20,}, + {75,667,79,-50,211,-50,212,-50,214,-50,210,-50,216,-50,213,-50,101,-40,233,-40,234,-40,235,-40,232,-40,111,-40,243,-40,244,-40,246,-40,242,-40,248,-40,245,-40,117,-30,250,-30,251,-30,252,-30,249,-30,121,-50,253,-50,255,-50,}, + {76,556,84,-110,86,-110,87,-70,89,-140,221,-140,159,-140,148,-140,146,-160,121,-30,253,-30,255,-30,}, + {77,833,}, + {78,722,}, + {79,778,65,-20,193,-20,194,-20,196,-20,192,-20,197,-20,195,-20,84,-40,86,-50,87,-30,88,-60,89,-70,221,-70,159,-70,44,-40,46,-40,}, + {80,667,65,-120,193,-120,194,-120,196,-120,192,-120,197,-120,195,-120,97,-40,225,-40,226,-40,228,-40,224,-40,229,-40,227,-40,44,-180,101,-50,233,-50,234,-50,235,-50,232,-50,111,-50,243,-50,244,-50,246,-50,242,-50,248,-50,245,-50,46,-180,}, + {81,778,85,-10,218,-10,219,-10,220,-10,217,-10,}, + {82,722,79,-20,211,-20,212,-20,214,-20,210,-20,216,-20,213,-20,84,-30,85,-40,218,-40,219,-40,220,-40,217,-40,86,-50,87,-30,89,-50,221,-50,159,-50,}, + {83,667,44,-20,46,-20,}, + {84,611,65,-120,193,-120,194,-120,196,-120,192,-120,197,-120,195,-120,79,-40,211,-40,212,-40,214,-40,210,-40,216,-40,213,-40,97,-120,225,-120,226,-120,228,-120,224,-120,229,-120,227,-60,58,-20,44,-120,101,-120,233,-120,234,-120,235,-120,232,-60,45,-140,111,-120,243,-120,244,-120,246,-120,242,-120,248,-120,245,-60,46,-120,114,-120,59,-20,117,-120,250,-120,251,-120,252,-120,249,-120,119,-120,121,-120,253,-120,255,-60,}, + {85,722,65,-40,193,-40,194,-40,196,-40,192,-40,197,-40,195,-40,44,-40,46,-40,}, + {86,667,65,-80,193,-80,194,-80,196,-80,192,-80,197,-80,195,-80,71,-40,79,-40,211,-40,212,-40,214,-40,210,-40,216,-40,213,-40,97,-70,225,-70,226,-70,228,-70,224,-70,229,-70,227,-70,58,-40,44,-125,101,-80,233,-80,234,-80,235,-80,232,-80,45,-80,111,-80,243,-80,244,-80,246,-80,242,-80,248,-80,245,-80,46,-125,59,-40,117,-70,250,-70,251,-70,252,-70,249,-70,}, + {87,944,65,-50,193,-50,194,-50,196,-50,192,-50,197,-50,195,-50,79,-20,211,-20,212,-20,214,-20,210,-20,216,-20,213,-20,97,-40,225,-40,226,-40,228,-40,224,-40,229,-40,227,-40,44,-80,101,-30,233,-30,234,-30,235,-30,232,-30,45,-40,111,-30,243,-30,244,-30,246,-30,242,-30,248,-30,245,-30,46,-80,117,-30,250,-30,251,-30,252,-30,249,-30,121,-20,253,-20,255,-20,}, + {88,667,}, + {89,667,65,-110,193,-110,194,-110,196,-110,192,-110,197,-110,195,-110,79,-85,211,-85,212,-85,214,-85,210,-85,216,-85,213,-85,97,-140,225,-140,226,-140,228,-140,224,-140,229,-140,227,-140,58,-60,44,-140,101,-140,233,-140,234,-140,235,-140,232,-140,45,-140,105,-20,237,-20,111,-140,243,-140,244,-140,246,-140,242,-140,248,-140,245,-140,46,-140,59,-60,117,-110,250,-110,251,-110,252,-110,249,-110,}, + {90,611,}, + {91,278,}, + {92,278,}, + {93,278,}, + {94,469,}, + {95,556,}, + {96,333,}, + {97,556,118,-20,119,-20,121,-30,253,-30,255,-30,}, + {98,556,98,-10,44,-40,108,-20,46,-40,117,-20,250,-20,251,-20,252,-20,249,-20,118,-20,121,-20,253,-20,255,-20,}, + {99,500,44,-15,107,-20,}, + {100,556,}, + {101,556,44,-15,46,-15,118,-30,119,-20,120,-30,121,-20,253,-20,255,-20,}, + {102,278,97,-30,225,-30,226,-30,228,-30,224,-30,229,-30,227,-30,44,-30,101,-30,233,-30,234,-30,235,-30,232,-30,111,-30,243,-30,244,-30,246,-30,242,-30,248,-30,245,-30,46,-30,148,60,146,50,}, + {103,556,114,-10,}, + {104,556,121,-30,253,-30,255,-30,}, + {105,222,}, + {106,222,}, + {107,500,101,-20,233,-20,234,-20,235,-20,232,-20,111,-20,243,-20,244,-20,246,-20,242,-20,248,-20,245,-20,}, + {108,222,}, + {109,833,117,-10,250,-10,251,-10,252,-10,249,-10,121,-15,253,-15,255,-15,}, + {110,556,117,-10,250,-10,251,-10,252,-10,249,-10,118,-20,121,-15,253,-15,255,-15,}, + {111,556,44,-40,46,-40,118,-15,119,-15,120,-30,121,-30,253,-30,255,-30,}, + {112,556,44,-35,46,-35,121,-30,253,-30,255,-30,}, + {113,556,}, + {114,333,97,-10,225,-10,226,-10,228,-10,224,-10,229,-10,227,-10,58,30,44,-50,105,15,237,15,238,15,239,15,236,15,107,15,108,15,109,25,110,25,241,25,112,30,46,-50,59,30,116,40,117,15,250,15,251,15,252,15,249,15,118,30,121,30,253,30,255,30,}, + {115,500,44,-15,46,-15,119,-30,}, + {116,278,}, + {117,556,}, + {118,500,97,-25,225,-25,226,-25,228,-25,224,-25,229,-25,227,-25,44,-80,101,-25,233,-25,234,-25,235,-25,232,-25,111,-25,243,-25,244,-25,246,-25,242,-25,248,-25,245,-25,46,-80,}, + {119,722,97,-15,225,-15,226,-15,228,-15,224,-15,229,-15,227,-15,44,-60,101,-10,233,-10,234,-10,235,-10,232,-10,111,-10,243,-10,244,-10,246,-10,242,-10,248,-10,245,-10,46,-60,}, + {120,500,101,-30,233,-30,234,-30,235,-30,232,-30,}, + {121,500,97,-20,225,-20,226,-20,228,-20,224,-20,229,-20,227,-20,44,-100,101,-20,233,-20,234,-20,235,-20,232,-20,111,-20,243,-20,244,-20,246,-20,242,-20,248,-20,245,-20,46,-100,}, + {122,500,101,-15,233,-15,234,-15,235,-15,232,-15,111,-15,243,-15,244,-15,246,-15,242,-15,248,-15,245,-15,}, + {123,334,}, + {124,260,}, + {125,334,}, + {126,584,}, + {127,278,}, + {128,556,}, + {129,278,}, + {130,222,}, + {131,556,}, + {132,333,}, + {133,1000,}, + {134,556,}, + {135,556,}, + {136,333,}, + {137,1000,}, + {138,667,44,-20,46,-20,}, + {139,333,}, + {140,1000,}, + {141,278,}, + {142,611,}, + {143,278,}, + {144,278,}, + {145,222,145,-57,}, + {146,222,100,-50,146,-57,114,-50,115,-50,154,-50,32,-70,}, + {147,333,}, + {148,333,32,-40,}, + {149,350,}, + {150,556,}, + {151,1000,}, + {152,333,}, + {153,1000,}, + {154,500,44,-15,46,-15,119,-30,}, + {155,333,}, + {156,944,}, + {157,278,}, + {158,500,101,-15,233,-15,234,-15,235,-15,232,-15,111,-15,243,-15,244,-15,246,-15,242,-15,248,-15,245,-15,}, + {159,667,65,-110,193,-110,194,-110,196,-110,192,-110,197,-110,195,-110,79,-85,211,-85,212,-85,214,-85,210,-85,216,-85,213,-85,97,-140,225,-140,226,-140,228,-140,224,-140,229,-140,227,-70,58,-60,44,-140,101,-140,233,-140,234,-140,235,-140,232,-140,45,-140,105,-20,237,-20,111,-140,243,-140,244,-140,246,-140,242,-140,248,-140,245,-140,46,-140,59,-60,117,-110,250,-110,251,-110,252,-110,249,-110,}, + {160,278,}, + {161,333,}, + {162,556,}, + {163,556,}, + {164,556,}, + {165,556,}, + {166,260,}, + {167,556,}, + {168,333,}, + {169,737,}, + {170,370,}, + {171,556,}, + {172,584,}, + {173,278,}, + {174,737,}, + {175,333,}, + {176,400,}, + {177,584,}, + {178,333,}, + {179,333,}, + {180,333,}, + {181,556,}, + {182,537,}, + {183,278,}, + {184,333,}, + {185,333,}, + {186,365,}, + {187,556,}, + {188,834,}, + {189,834,}, + {190,834,}, + {191,611,}, + {192,667,67,-30,199,-30,71,-30,79,-30,211,-30,212,-30,214,-30,210,-30,216,-30,213,-30,81,-30,84,-120,85,-50,218,-50,219,-50,220,-50,217,-50,86,-70,87,-50,89,-100,221,-100,159,-100,117,-30,250,-30,251,-30,252,-30,249,-30,118,-40,119,-40,121,-40,253,-40,255,-40,}, + {193,667,67,-30,199,-30,71,-30,79,-30,211,-30,212,-30,214,-30,210,-30,216,-30,213,-30,81,-30,84,-120,85,-50,218,-50,219,-50,220,-50,217,-50,86,-70,87,-50,89,-100,221,-100,159,-100,117,-30,250,-30,251,-30,252,-30,249,-30,118,-40,119,-40,121,-40,253,-40,255,-40,}, + {194,667,67,-30,199,-30,71,-30,79,-30,211,-30,212,-30,214,-30,210,-30,216,-30,213,-30,81,-30,84,-120,85,-50,218,-50,219,-50,220,-50,217,-50,86,-70,87,-50,89,-100,221,-100,159,-100,117,-30,250,-30,251,-30,252,-30,249,-30,118,-40,119,-40,121,-40,253,-40,255,-40,}, + {195,667,67,-30,199,-30,71,-30,79,-30,211,-30,212,-30,214,-30,210,-30,216,-30,213,-30,81,-30,84,-120,85,-50,218,-50,219,-50,220,-50,217,-50,86,-70,87,-50,89,-100,221,-100,159,-100,117,-30,250,-30,251,-30,252,-30,249,-30,118,-40,119,-40,121,-40,253,-40,255,-40,}, + {196,667,67,-30,199,-30,71,-30,79,-30,211,-30,212,-30,214,-30,210,-30,216,-30,213,-30,81,-30,84,-120,85,-50,218,-50,219,-50,220,-50,217,-50,86,-70,87,-50,89,-100,221,-100,159,-100,117,-30,250,-30,251,-30,252,-30,249,-30,118,-40,119,-40,121,-40,253,-40,255,-40,}, + {197,667,67,-30,199,-30,71,-30,79,-30,211,-30,212,-30,214,-30,210,-30,216,-30,213,-30,81,-30,84,-120,85,-50,218,-50,219,-50,220,-50,217,-50,86,-70,87,-50,89,-100,221,-100,159,-100,117,-30,250,-30,251,-30,252,-30,249,-30,118,-40,119,-40,121,-40,253,-40,255,-40,}, + {198,1000,}, + {199,722,44,-30,46,-30,}, + {200,667,}, + {201,667,}, + {202,667,}, + {203,667,}, + {204,278,}, + {205,278,}, + {206,278,}, + {207,278,}, + {208,722,}, + {209,722,}, + {210,778,65,-20,193,-20,194,-20,196,-20,192,-20,197,-20,195,-20,84,-40,86,-50,87,-30,88,-60,89,-70,221,-70,159,-70,44,-40,46,-40,}, + {211,778,65,-20,193,-20,194,-20,196,-20,192,-20,197,-20,195,-20,84,-40,86,-50,87,-30,88,-60,89,-70,221,-70,159,-70,44,-40,46,-40,}, + {212,778,65,-20,193,-20,194,-20,196,-20,192,-20,197,-20,195,-20,84,-40,86,-50,87,-30,88,-60,89,-70,221,-70,159,-70,44,-40,46,-40,}, + {213,778,65,-20,193,-20,194,-20,196,-20,192,-20,197,-20,195,-20,84,-40,86,-50,87,-30,88,-60,89,-70,221,-70,159,-70,44,-40,46,-40,}, + {214,778,65,-20,193,-20,194,-20,196,-20,192,-20,197,-20,195,-20,84,-40,86,-50,87,-30,88,-60,89,-70,221,-70,159,-70,44,-40,46,-40,}, + {215,584,}, + {216,778,65,-20,193,-20,194,-20,196,-20,192,-20,197,-20,195,-20,84,-40,86,-50,87,-30,88,-60,89,-70,221,-70,159,-70,44,-40,46,-40,}, + {217,722,65,-40,193,-40,194,-40,196,-40,192,-40,197,-40,195,-40,44,-40,46,-40,}, + {218,722,65,-40,193,-40,194,-40,196,-40,192,-40,197,-40,195,-40,44,-40,46,-40,}, + {219,722,65,-40,193,-40,194,-40,196,-40,192,-40,197,-40,195,-40,44,-40,46,-40,}, + {220,722,65,-40,193,-40,194,-40,196,-40,192,-40,197,-40,195,-40,44,-40,46,-40,}, + {221,667,65,-110,193,-110,194,-110,196,-110,192,-110,197,-110,195,-110,79,-85,211,-85,212,-85,214,-85,210,-85,216,-85,213,-85,97,-140,225,-140,226,-140,228,-140,224,-140,229,-140,227,-70,58,-60,44,-140,101,-140,233,-140,234,-140,235,-140,232,-140,45,-140,105,-20,237,-20,111,-140,243,-140,244,-140,246,-140,242,-140,248,-140,245,-140,46,-140,59,-60,117,-110,250,-110,251,-110,252,-110,249,-110,}, + {222,667,}, + {223,611,}, + {224,556,118,-20,119,-20,121,-30,253,-30,255,-30,}, + {225,556,118,-20,119,-20,121,-30,253,-30,255,-30,}, + {226,556,118,-20,119,-20,121,-30,253,-30,255,-30,}, + {227,556,118,-20,119,-20,121,-30,253,-30,255,-30,}, + {228,556,118,-20,119,-20,121,-30,253,-30,255,-30,}, + {229,556,118,-20,119,-20,121,-30,253,-30,255,-30,}, + {230,889,}, + {231,500,44,-15,107,-20,}, + {232,556,44,-15,46,-15,118,-30,119,-20,120,-30,121,-20,253,-20,255,-20,}, + {233,556,44,-15,46,-15,118,-30,119,-20,120,-30,121,-20,253,-20,255,-20,}, + {234,556,44,-15,46,-15,118,-30,119,-20,120,-30,121,-20,253,-20,255,-20,}, + {235,556,44,-15,46,-15,118,-30,119,-20,120,-30,121,-20,253,-20,255,-20,}, + {236,278,}, + {237,278,}, + {238,278,}, + {239,278,}, + {240,556,}, + {241,556,117,-10,250,-10,251,-10,252,-10,249,-10,118,-20,121,-15,253,-15,255,-15,}, + {242,556,44,-40,46,-40,118,-15,119,-15,120,-30,121,-30,253,-30,255,-30,}, + {243,556,44,-40,46,-40,118,-15,119,-15,120,-30,121,-30,253,-30,255,-30,}, + {244,556,44,-40,46,-40,118,-15,119,-15,120,-30,121,-30,253,-30,255,-30,}, + {245,556,44,-40,46,-40,118,-15,119,-15,120,-30,121,-30,253,-30,255,-30,}, + {246,556,44,-40,46,-40,118,-15,119,-15,120,-30,121,-30,253,-30,255,-30,}, + {247,584,}, + {248,611,97,-55,225,-55,226,-55,228,-55,224,-55,229,-55,227,-55,98,-55,99,-55,231,-55,44,-95,100,-55,101,-55,233,-55,234,-55,235,-55,232,-55,102,-55,103,-55,104,-55,105,-55,237,-55,238,-55,239,-55,236,-55,106,-55,107,-55,108,-55,109,-55,110,-55,241,-55,111,-55,243,-55,244,-55,246,-55,242,-55,248,-55,245,-55,112,-55,46,-95,113,-55,114,-55,115,-55,154,-55,116,-55,117,-55,250,-55,251,-55,252,-55,249,-55,118,-70,119,-70,120,-85,121,-70,253,-70,255,-70,122,-55,158,-55,}, + {249,556,}, + {250,556,}, + {251,556,}, + {252,556,}, + {253,500,97,-20,225,-20,226,-20,228,-20,224,-20,229,-20,227,-20,44,-100,101,-20,233,-20,234,-20,235,-20,232,-20,111,-20,243,-20,244,-20,246,-20,242,-20,248,-20,245,-20,46,-100,}, + {254,556,}, + {255,500,97,-20,225,-20,226,-20,228,-20,224,-20,229,-20,227,-20,44,-100,101,-20,233,-20,234,-20,235,-20,232,-20,111,-20,243,-20,244,-20,246,-20,242,-20,248,-20,245,-20,46,-100,}, + }; +} diff --git a/PDFJet/src/main/java/com/pdfjet/Helvetica_Bold.java b/PDFJet/src/main/java/com/pdfjet/Helvetica_Bold.java new file mode 100644 index 0000000..6d914ce --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Helvetica_Bold.java @@ -0,0 +1,238 @@ +package com.pdfjet; + +class Helvetica_Bold { + protected static final String name = "Helvetica-Bold"; + protected static final int bBoxLLx = -170; + protected static final int bBoxLLy = -228; + protected static final int bBoxURx = 1003; + protected static final int bBoxURy = 962; + protected static final int underlinePosition = -100; + protected static final int underlineThickness = 50; + protected static final String notice = "Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated. All Rights Reserved. Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries."; + protected static final int[][] metrics = { + {32,278,84,-100,86,-80,87,-80,89,-120,221,-120,159,-120,147,-80,145,-60,}, + {33,333,}, + {34,474,}, + {35,556,}, + {36,556,}, + {37,889,}, + {38,722,}, + {39,238,}, + {40,333,}, + {41,333,}, + {42,389,}, + {43,584,}, + {44,278,148,-120,146,-120,32,-40,}, + {45,333,}, + {46,278,148,-120,146,-120,32,-40,}, + {47,278,}, + {48,556,}, + {49,556,}, + {50,556,}, + {51,556,}, + {52,556,}, + {53,556,}, + {54,556,}, + {55,556,}, + {56,556,}, + {57,556,}, + {58,333,32,-40,}, + {59,333,32,-40,}, + {60,584,}, + {61,584,}, + {62,584,}, + {63,611,}, + {64,975,}, + {65,722,67,-40,199,-40,71,-50,79,-40,211,-40,212,-40,214,-40,210,-40,216,-40,213,-40,81,-40,84,-90,85,-50,218,-50,219,-50,220,-50,217,-50,86,-80,87,-60,89,-110,221,-110,159,-110,117,-30,250,-30,251,-30,252,-30,249,-30,118,-40,119,-30,121,-30,253,-30,255,-30,}, + {66,722,65,-30,193,-30,194,-30,196,-30,192,-30,197,-30,195,-30,85,-10,218,-10,219,-10,220,-10,217,-10,}, + {67,722,}, + {68,722,65,-40,193,-40,194,-40,196,-40,192,-40,197,-40,195,-40,86,-40,87,-40,89,-70,221,-70,159,-70,44,-30,46,-30,}, + {69,667,}, + {70,611,65,-80,193,-80,194,-80,196,-80,192,-80,197,-80,195,-80,97,-20,225,-20,226,-20,228,-20,224,-20,229,-20,227,-20,44,-100,46,-100,}, + {71,778,}, + {72,722,}, + {73,278,}, + {74,556,65,-20,193,-20,194,-20,196,-20,192,-20,197,-20,195,-20,44,-20,46,-20,117,-20,250,-20,251,-20,252,-20,249,-20,}, + {75,722,79,-30,211,-30,212,-30,214,-30,210,-30,216,-30,213,-30,101,-15,233,-15,234,-15,235,-15,232,-15,111,-35,243,-35,244,-35,246,-35,242,-35,248,-35,245,-35,117,-30,250,-30,251,-30,252,-30,249,-30,121,-40,253,-40,255,-40,}, + {76,611,84,-90,86,-110,87,-80,89,-120,221,-120,159,-120,148,-140,146,-140,121,-30,253,-30,255,-30,}, + {77,833,}, + {78,722,}, + {79,778,65,-50,193,-50,194,-50,196,-50,192,-50,197,-50,195,-50,84,-40,86,-50,87,-50,88,-50,89,-70,221,-70,159,-70,44,-40,46,-40,}, + {80,667,65,-100,193,-100,194,-100,196,-100,192,-100,197,-100,195,-100,97,-30,225,-30,226,-30,228,-30,224,-30,229,-30,227,-30,44,-120,101,-30,233,-30,234,-30,235,-30,232,-30,111,-40,243,-40,244,-40,246,-40,242,-40,248,-40,245,-40,46,-120,}, + {81,778,85,-10,218,-10,219,-10,220,-10,217,-10,44,20,46,20,}, + {82,722,79,-20,211,-20,212,-20,214,-20,210,-20,216,-20,213,-20,84,-20,85,-20,218,-20,219,-20,220,-20,217,-20,86,-50,87,-40,89,-50,221,-50,159,-50,}, + {83,667,}, + {84,611,65,-90,193,-90,194,-90,196,-90,192,-90,197,-90,195,-90,79,-40,211,-40,212,-40,214,-40,210,-40,216,-40,213,-40,97,-80,225,-80,226,-80,228,-80,224,-80,229,-80,227,-80,58,-40,44,-80,101,-60,233,-60,234,-60,235,-60,232,-60,45,-120,111,-80,243,-80,244,-80,246,-80,242,-80,248,-80,245,-80,46,-80,114,-80,59,-40,117,-90,250,-90,251,-90,252,-90,249,-90,119,-60,121,-60,253,-60,255,-60,}, + {85,722,65,-50,193,-50,194,-50,196,-50,192,-50,197,-50,195,-50,44,-30,46,-30,}, + {86,667,65,-80,193,-80,194,-80,196,-80,192,-80,197,-80,195,-80,71,-50,79,-50,211,-50,212,-50,214,-50,210,-50,216,-50,213,-50,97,-60,225,-60,226,-60,228,-60,224,-60,229,-60,227,-60,58,-40,44,-120,101,-50,233,-50,234,-50,235,-50,232,-50,45,-80,111,-90,243,-90,244,-90,246,-90,242,-90,248,-90,245,-90,46,-120,59,-40,117,-60,250,-60,251,-60,252,-60,249,-60,}, + {87,944,65,-60,193,-60,194,-60,196,-60,192,-60,197,-60,195,-60,79,-20,211,-20,212,-20,214,-20,210,-20,216,-20,213,-20,97,-40,225,-40,226,-40,228,-40,224,-40,229,-40,227,-40,58,-10,44,-80,101,-35,233,-35,234,-35,235,-35,232,-35,45,-40,111,-60,243,-60,244,-60,246,-60,242,-60,248,-60,245,-60,46,-80,59,-10,117,-45,250,-45,251,-45,252,-45,249,-45,121,-20,253,-20,255,-20,}, + {88,667,}, + {89,667,65,-110,193,-110,194,-110,196,-110,192,-110,197,-110,195,-110,79,-70,211,-70,212,-70,214,-70,210,-70,216,-70,213,-70,97,-90,225,-90,226,-90,228,-90,224,-90,229,-90,227,-90,58,-50,44,-100,101,-80,233,-80,234,-80,235,-80,232,-80,111,-100,243,-100,244,-100,246,-100,242,-100,248,-100,245,-100,46,-100,59,-50,117,-100,250,-100,251,-100,252,-100,249,-100,}, + {90,611,}, + {91,333,}, + {92,278,}, + {93,333,}, + {94,584,}, + {95,556,}, + {96,333,}, + {97,556,103,-10,118,-15,119,-15,121,-20,253,-20,255,-20,}, + {98,611,108,-10,117,-20,250,-20,251,-20,252,-20,249,-20,118,-20,121,-20,253,-20,255,-20,}, + {99,556,104,-10,107,-20,108,-20,121,-10,253,-10,255,-10,}, + {100,611,100,-10,118,-15,119,-15,121,-15,253,-15,255,-15,}, + {101,556,44,10,46,20,118,-15,119,-15,120,-15,121,-15,253,-15,255,-15,}, + {102,333,44,-10,101,-10,233,-10,234,-10,235,-10,232,-10,111,-20,243,-20,244,-20,246,-20,242,-20,248,-20,245,-20,46,-10,148,30,146,30,}, + {103,611,101,10,233,10,234,10,235,10,232,10,103,-10,}, + {104,611,121,-20,253,-20,255,-20,}, + {105,278,}, + {106,278,}, + {107,556,111,-15,243,-15,244,-15,246,-15,242,-15,248,-15,245,-15,}, + {108,278,119,-15,121,-15,253,-15,255,-15,}, + {109,889,117,-20,250,-20,251,-20,252,-20,249,-20,121,-30,253,-30,255,-30,}, + {110,611,117,-10,250,-10,251,-10,252,-10,249,-10,118,-40,121,-20,253,-20,255,-20,}, + {111,611,118,-20,119,-15,120,-30,121,-20,253,-20,255,-20,}, + {112,611,121,-15,253,-15,255,-15,}, + {113,611,}, + {114,389,99,-20,231,-20,44,-60,100,-20,103,-15,45,-20,111,-20,243,-20,244,-20,246,-20,242,-20,248,-20,245,-20,46,-60,113,-20,115,-15,154,-15,116,20,118,10,121,10,253,10,255,10,}, + {115,556,119,-15,}, + {116,333,}, + {117,611,}, + {118,556,97,-20,225,-20,226,-20,228,-20,224,-20,229,-20,227,-20,44,-80,111,-30,243,-30,244,-30,246,-30,242,-30,248,-30,245,-30,46,-80,}, + {119,778,44,-40,111,-20,243,-20,244,-20,246,-20,242,-20,248,-20,245,-20,46,-40,}, + {120,556,101,-10,233,-10,234,-10,235,-10,232,-10,}, + {121,556,97,-30,225,-30,226,-30,228,-30,224,-30,229,-30,227,-30,44,-80,101,-10,233,-10,234,-10,235,-10,232,-10,111,-25,243,-25,244,-25,246,-25,242,-25,248,-25,245,-25,46,-80,}, + {122,500,101,10,233,10,234,10,235,10,232,10,}, + {123,389,}, + {124,280,}, + {125,389,}, + {126,584,}, + {127,278,}, + {128,556,}, + {129,278,}, + {130,278,}, + {131,556,}, + {132,500,}, + {133,1000,}, + {134,556,}, + {135,556,}, + {136,333,}, + {137,1000,}, + {138,667,}, + {139,333,}, + {140,1000,}, + {141,278,}, + {142,611,}, + {143,278,}, + {144,278,}, + {145,278,145,-46,}, + {146,278,100,-80,108,-20,146,-46,114,-40,115,-60,154,-60,32,-80,118,-20,}, + {147,500,}, + {148,500,32,-80,}, + {149,350,}, + {150,556,}, + {151,1000,}, + {152,333,}, + {153,1000,}, + {154,556,119,-15,}, + {155,333,}, + {156,944,}, + {157,278,}, + {158,500,101,10,233,10,234,10,235,10,232,10,}, + {159,667,65,-110,193,-110,194,-110,196,-110,192,-110,197,-110,195,-110,79,-70,211,-70,212,-70,214,-70,210,-70,216,-70,213,-70,97,-90,225,-90,226,-90,228,-90,224,-90,229,-90,227,-90,58,-50,44,-100,101,-80,233,-80,234,-80,235,-80,232,-80,111,-100,243,-100,244,-100,246,-100,242,-100,248,-100,245,-100,46,-100,59,-50,117,-100,250,-100,251,-100,252,-100,249,-100,}, + {160,278,}, + {161,333,}, + {162,556,}, + {163,556,}, + {164,556,}, + {165,556,}, + {166,280,}, + {167,556,}, + {168,333,}, + {169,737,}, + {170,370,}, + {171,556,}, + {172,584,}, + {173,278,}, + {174,737,}, + {175,333,}, + {176,400,}, + {177,584,}, + {178,333,}, + {179,333,}, + {180,333,}, + {181,611,}, + {182,556,}, + {183,278,}, + {184,333,}, + {185,333,}, + {186,365,}, + {187,556,}, + {188,834,}, + {189,834,}, + {190,834,}, + {191,611,}, + {192,722,67,-40,199,-40,71,-50,79,-40,211,-40,212,-40,214,-40,210,-40,216,-40,213,-40,81,-40,84,-90,85,-50,218,-50,219,-50,220,-50,217,-50,86,-80,87,-60,89,-110,221,-110,159,-110,117,-30,250,-30,251,-30,252,-30,249,-30,118,-40,119,-30,121,-30,253,-30,255,-30,}, + {193,722,67,-40,199,-40,71,-50,79,-40,211,-40,212,-40,214,-40,210,-40,216,-40,213,-40,81,-40,84,-90,85,-50,218,-50,219,-50,220,-50,217,-50,86,-80,87,-60,89,-110,221,-110,159,-110,117,-30,250,-30,251,-30,252,-30,249,-30,118,-40,119,-30,121,-30,253,-30,255,-30,}, + {194,722,67,-40,199,-40,71,-50,79,-40,211,-40,212,-40,214,-40,210,-40,216,-40,213,-40,81,-40,84,-90,85,-50,218,-50,219,-50,220,-50,217,-50,86,-80,87,-60,89,-110,221,-110,159,-110,117,-30,250,-30,251,-30,252,-30,249,-30,118,-40,119,-30,121,-30,253,-30,255,-30,}, + {195,722,67,-40,199,-40,71,-50,79,-40,211,-40,212,-40,214,-40,210,-40,216,-40,213,-40,81,-40,84,-90,85,-50,218,-50,219,-50,220,-50,217,-50,86,-80,87,-60,89,-110,221,-110,159,-110,117,-30,250,-30,251,-30,252,-30,249,-30,118,-40,119,-30,121,-30,253,-30,255,-30,}, + {196,722,67,-40,199,-40,71,-50,79,-40,211,-40,212,-40,214,-40,210,-40,216,-40,213,-40,81,-40,84,-90,85,-50,218,-50,219,-50,220,-50,217,-50,86,-80,87,-60,89,-110,221,-110,159,-110,117,-30,250,-30,251,-30,252,-30,249,-30,118,-40,119,-30,121,-30,253,-30,255,-30,}, + {197,722,67,-40,199,-40,71,-50,79,-40,211,-40,212,-40,214,-40,210,-40,216,-40,213,-40,81,-40,84,-90,85,-50,218,-50,219,-50,220,-50,217,-50,86,-80,87,-60,89,-110,221,-110,159,-110,117,-30,250,-30,251,-30,252,-30,249,-30,118,-40,119,-30,121,-30,253,-30,255,-30,}, + {198,1000,}, + {199,722,}, + {200,667,}, + {201,667,}, + {202,667,}, + {203,667,}, + {204,278,}, + {205,278,}, + {206,278,}, + {207,278,}, + {208,722,}, + {209,722,}, + {210,778,65,-50,193,-50,194,-50,196,-50,192,-50,197,-50,195,-50,84,-40,86,-50,87,-50,88,-50,89,-70,221,-70,159,-70,44,-40,46,-40,}, + {211,778,65,-50,193,-50,194,-50,196,-50,192,-50,197,-50,195,-50,84,-40,86,-50,87,-50,88,-50,89,-70,221,-70,159,-70,44,-40,46,-40,}, + {212,778,65,-50,193,-50,194,-50,196,-50,192,-50,197,-50,195,-50,84,-40,86,-50,87,-50,88,-50,89,-70,221,-70,159,-70,44,-40,46,-40,}, + {213,778,65,-50,193,-50,194,-50,196,-50,192,-50,197,-50,195,-50,84,-40,86,-50,87,-50,88,-50,89,-70,221,-70,159,-70,44,-40,46,-40,}, + {214,778,65,-50,193,-50,194,-50,196,-50,192,-50,197,-50,195,-50,84,-40,86,-50,87,-50,88,-50,89,-70,221,-70,159,-70,44,-40,46,-40,}, + {215,584,}, + {216,778,65,-50,193,-50,194,-50,196,-50,192,-50,197,-50,195,-50,84,-40,86,-50,87,-50,88,-50,89,-70,221,-70,159,-70,44,-40,46,-40,}, + {217,722,65,-50,193,-50,194,-50,196,-50,192,-50,197,-50,195,-50,44,-30,46,-30,}, + {218,722,65,-50,193,-50,194,-50,196,-50,192,-50,197,-50,195,-50,44,-30,46,-30,}, + {219,722,65,-50,193,-50,194,-50,196,-50,192,-50,197,-50,195,-50,44,-30,46,-30,}, + {220,722,65,-50,193,-50,194,-50,196,-50,192,-50,197,-50,195,-50,44,-30,46,-30,}, + {221,667,65,-110,193,-110,194,-110,196,-110,192,-110,197,-110,195,-110,79,-70,211,-70,212,-70,214,-70,210,-70,216,-70,213,-70,97,-90,225,-90,226,-90,228,-90,224,-90,229,-90,227,-90,58,-50,44,-100,101,-80,233,-80,234,-80,235,-80,232,-80,111,-100,243,-100,244,-100,246,-100,242,-100,248,-100,245,-100,46,-100,59,-50,117,-100,250,-100,251,-100,252,-100,249,-100,}, + {222,667,}, + {223,611,}, + {224,556,103,-10,118,-15,119,-15,121,-20,253,-20,255,-20,}, + {225,556,103,-10,118,-15,119,-15,121,-20,253,-20,255,-20,}, + {226,556,103,-10,118,-15,119,-15,121,-20,253,-20,255,-20,}, + {227,556,103,-10,118,-15,119,-15,121,-20,253,-20,255,-20,}, + {228,556,103,-10,118,-15,119,-15,121,-20,253,-20,255,-20,}, + {229,556,103,-10,118,-15,119,-15,121,-20,253,-20,255,-20,}, + {230,889,}, + {231,556,104,-10,107,-20,108,-20,121,-10,253,-10,255,-10,}, + {232,556,44,10,46,20,118,-15,119,-15,120,-15,121,-15,253,-15,255,-15,}, + {233,556,44,10,46,20,118,-15,119,-15,120,-15,121,-15,253,-15,255,-15,}, + {234,556,44,10,46,20,118,-15,119,-15,120,-15,121,-15,253,-15,255,-15,}, + {235,556,44,10,46,20,118,-15,119,-15,120,-15,121,-15,253,-15,255,-15,}, + {236,278,}, + {237,278,}, + {238,278,}, + {239,278,}, + {240,611,}, + {241,611,117,-10,250,-10,251,-10,252,-10,249,-10,118,-40,121,-20,253,-20,255,-20,}, + {242,611,118,-20,119,-15,120,-30,121,-20,253,-20,255,-20,}, + {243,611,118,-20,119,-15,120,-30,121,-20,253,-20,255,-20,}, + {244,611,118,-20,119,-15,120,-30,121,-20,253,-20,255,-20,}, + {245,611,118,-20,119,-15,120,-30,121,-20,253,-20,255,-20,}, + {246,611,118,-20,119,-15,120,-30,121,-20,253,-20,255,-20,}, + {247,584,}, + {248,611,118,-20,119,-15,120,-30,121,-20,253,-20,255,-20,}, + {249,611,}, + {250,611,}, + {251,611,}, + {252,611,}, + {253,556,97,-30,225,-30,226,-30,228,-30,224,-30,229,-30,227,-30,44,-80,101,-10,233,-10,234,-10,235,-10,232,-10,111,-25,243,-25,244,-25,246,-25,242,-25,248,-25,245,-25,46,-80,}, + {254,611,}, + {255,556,97,-30,225,-30,226,-30,228,-30,224,-30,229,-30,227,-30,44,-80,101,-10,233,-10,234,-10,235,-10,232,-10,111,-25,243,-25,244,-25,246,-25,242,-25,248,-25,245,-25,46,-80,}, + }; +} diff --git a/PDFJet/src/main/java/com/pdfjet/Helvetica_BoldOblique.java b/PDFJet/src/main/java/com/pdfjet/Helvetica_BoldOblique.java new file mode 100644 index 0000000..cdfbe6a --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Helvetica_BoldOblique.java @@ -0,0 +1,238 @@ +package com.pdfjet; + +class Helvetica_BoldOblique { + protected static final String name = "Helvetica-BoldOblique"; + protected static final int bBoxLLx = -174; + protected static final int bBoxLLy = -228; + protected static final int bBoxURx = 1114; + protected static final int bBoxURy = 962; + protected static final int underlinePosition = -100; + protected static final int underlineThickness = 50; + protected static final String notice = "Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated. All Rights Reserved. Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries."; + protected static final int[][] metrics = { + {32,278,84,-100,86,-80,87,-80,89,-120,221,-120,159,-120,147,-80,145,-60,}, + {33,333,}, + {34,474,}, + {35,556,}, + {36,556,}, + {37,889,}, + {38,722,}, + {39,238,}, + {40,333,}, + {41,333,}, + {42,389,}, + {43,584,}, + {44,278,148,-120,146,-120,32,-40,}, + {45,333,}, + {46,278,148,-120,146,-120,32,-40,}, + {47,278,}, + {48,556,}, + {49,556,}, + {50,556,}, + {51,556,}, + {52,556,}, + {53,556,}, + {54,556,}, + {55,556,}, + {56,556,}, + {57,556,}, + {58,333,32,-40,}, + {59,333,32,-40,}, + {60,584,}, + {61,584,}, + {62,584,}, + {63,611,}, + {64,975,}, + {65,722,67,-40,199,-40,71,-50,79,-40,211,-40,212,-40,214,-40,210,-40,216,-40,213,-40,81,-40,84,-90,85,-50,218,-50,219,-50,220,-50,217,-50,86,-80,87,-60,89,-110,221,-110,159,-110,117,-30,250,-30,251,-30,252,-30,249,-30,118,-40,119,-30,121,-30,253,-30,255,-30,}, + {66,722,65,-30,193,-30,194,-30,196,-30,192,-30,197,-30,195,-30,85,-10,218,-10,219,-10,220,-10,217,-10,}, + {67,722,}, + {68,722,65,-40,193,-40,194,-40,196,-40,192,-40,197,-40,195,-40,86,-40,87,-40,89,-70,221,-70,159,-70,44,-30,46,-30,}, + {69,667,}, + {70,611,65,-80,193,-80,194,-80,196,-80,192,-80,197,-80,195,-80,97,-20,225,-20,226,-20,228,-20,224,-20,229,-20,227,-20,44,-100,46,-100,}, + {71,778,}, + {72,722,}, + {73,278,}, + {74,556,65,-20,193,-20,194,-20,196,-20,192,-20,197,-20,195,-20,44,-20,46,-20,117,-20,250,-20,251,-20,252,-20,249,-20,}, + {75,722,79,-30,211,-30,212,-30,214,-30,210,-30,216,-30,213,-30,101,-15,233,-15,234,-15,235,-15,232,-15,111,-35,243,-35,244,-35,246,-35,242,-35,248,-35,245,-35,117,-30,250,-30,251,-30,252,-30,249,-30,121,-40,253,-40,255,-40,}, + {76,611,84,-90,86,-110,87,-80,89,-120,221,-120,159,-120,148,-140,146,-140,121,-30,253,-30,255,-30,}, + {77,833,}, + {78,722,}, + {79,778,65,-50,193,-50,194,-50,196,-50,192,-50,197,-50,195,-50,84,-40,86,-50,87,-50,88,-50,89,-70,221,-70,159,-70,44,-40,46,-40,}, + {80,667,65,-100,193,-100,194,-100,196,-100,192,-100,197,-100,195,-100,97,-30,225,-30,226,-30,228,-30,224,-30,229,-30,227,-30,44,-120,101,-30,233,-30,234,-30,235,-30,232,-30,111,-40,243,-40,244,-40,246,-40,242,-40,248,-40,245,-40,46,-120,}, + {81,778,85,-10,218,-10,219,-10,220,-10,217,-10,44,20,46,20,}, + {82,722,79,-20,211,-20,212,-20,214,-20,210,-20,216,-20,213,-20,84,-20,85,-20,218,-20,219,-20,220,-20,217,-20,86,-50,87,-40,89,-50,221,-50,159,-50,}, + {83,667,}, + {84,611,65,-90,193,-90,194,-90,196,-90,192,-90,197,-90,195,-90,79,-40,211,-40,212,-40,214,-40,210,-40,216,-40,213,-40,97,-80,225,-80,226,-80,228,-80,224,-80,229,-80,227,-80,58,-40,44,-80,101,-60,233,-60,234,-60,235,-60,232,-60,45,-120,111,-80,243,-80,244,-80,246,-80,242,-80,248,-80,245,-80,46,-80,114,-80,59,-40,117,-90,250,-90,251,-90,252,-90,249,-90,119,-60,121,-60,253,-60,255,-60,}, + {85,722,65,-50,193,-50,194,-50,196,-50,192,-50,197,-50,195,-50,44,-30,46,-30,}, + {86,667,65,-80,193,-80,194,-80,196,-80,192,-80,197,-80,195,-80,71,-50,79,-50,211,-50,212,-50,214,-50,210,-50,216,-50,213,-50,97,-60,225,-60,226,-60,228,-60,224,-60,229,-60,227,-60,58,-40,44,-120,101,-50,233,-50,234,-50,235,-50,232,-50,45,-80,111,-90,243,-90,244,-90,246,-90,242,-90,248,-90,245,-90,46,-120,59,-40,117,-60,250,-60,251,-60,252,-60,249,-60,}, + {87,944,65,-60,193,-60,194,-60,196,-60,192,-60,197,-60,195,-60,79,-20,211,-20,212,-20,214,-20,210,-20,216,-20,213,-20,97,-40,225,-40,226,-40,228,-40,224,-40,229,-40,227,-40,58,-10,44,-80,101,-35,233,-35,234,-35,235,-35,232,-35,45,-40,111,-60,243,-60,244,-60,246,-60,242,-60,248,-60,245,-60,46,-80,59,-10,117,-45,250,-45,251,-45,252,-45,249,-45,121,-20,253,-20,255,-20,}, + {88,667,}, + {89,667,65,-110,193,-110,194,-110,196,-110,192,-110,197,-110,195,-110,79,-70,211,-70,212,-70,214,-70,210,-70,216,-70,213,-70,97,-90,225,-90,226,-90,228,-90,224,-90,229,-90,227,-90,58,-50,44,-100,101,-80,233,-80,234,-80,235,-80,232,-80,111,-100,243,-100,244,-100,246,-100,242,-100,248,-100,245,-100,46,-100,59,-50,117,-100,250,-100,251,-100,252,-100,249,-100,}, + {90,611,}, + {91,333,}, + {92,278,}, + {93,333,}, + {94,584,}, + {95,556,}, + {96,333,}, + {97,556,103,-10,118,-15,119,-15,121,-20,253,-20,255,-20,}, + {98,611,108,-10,117,-20,250,-20,251,-20,252,-20,249,-20,118,-20,121,-20,253,-20,255,-20,}, + {99,556,104,-10,107,-20,108,-20,121,-10,253,-10,255,-10,}, + {100,611,100,-10,118,-15,119,-15,121,-15,253,-15,255,-15,}, + {101,556,44,10,46,20,118,-15,119,-15,120,-15,121,-15,253,-15,255,-15,}, + {102,333,44,-10,101,-10,233,-10,234,-10,235,-10,232,-10,111,-20,243,-20,244,-20,246,-20,242,-20,248,-20,245,-20,46,-10,148,30,146,30,}, + {103,611,101,10,233,10,234,10,235,10,232,10,103,-10,}, + {104,611,121,-20,253,-20,255,-20,}, + {105,278,}, + {106,278,}, + {107,556,111,-15,243,-15,244,-15,246,-15,242,-15,248,-15,245,-15,}, + {108,278,119,-15,121,-15,253,-15,255,-15,}, + {109,889,117,-20,250,-20,251,-20,252,-20,249,-20,121,-30,253,-30,255,-30,}, + {110,611,117,-10,250,-10,251,-10,252,-10,249,-10,118,-40,121,-20,253,-20,255,-20,}, + {111,611,118,-20,119,-15,120,-30,121,-20,253,-20,255,-20,}, + {112,611,121,-15,253,-15,255,-15,}, + {113,611,}, + {114,389,99,-20,231,-20,44,-60,100,-20,103,-15,45,-20,111,-20,243,-20,244,-20,246,-20,242,-20,248,-20,245,-20,46,-60,113,-20,115,-15,154,-15,116,20,118,10,121,10,253,10,255,10,}, + {115,556,119,-15,}, + {116,333,}, + {117,611,}, + {118,556,97,-20,225,-20,226,-20,228,-20,224,-20,229,-20,227,-20,44,-80,111,-30,243,-30,244,-30,246,-30,242,-30,248,-30,245,-30,46,-80,}, + {119,778,44,-40,111,-20,243,-20,244,-20,246,-20,242,-20,248,-20,245,-20,46,-40,}, + {120,556,101,-10,233,-10,234,-10,235,-10,232,-10,}, + {121,556,97,-30,225,-30,226,-30,228,-30,224,-30,229,-30,227,-30,44,-80,101,-10,233,-10,234,-10,235,-10,232,-10,111,-25,243,-25,244,-25,246,-25,242,-25,248,-25,245,-25,46,-80,}, + {122,500,101,10,233,10,234,10,235,10,232,10,}, + {123,389,}, + {124,280,}, + {125,389,}, + {126,584,}, + {127,278,}, + {128,556,}, + {129,278,}, + {130,278,}, + {131,556,}, + {132,500,}, + {133,1000,}, + {134,556,}, + {135,556,}, + {136,333,}, + {137,1000,}, + {138,667,}, + {139,333,}, + {140,1000,}, + {141,278,}, + {142,611,}, + {143,278,}, + {144,278,}, + {145,278,145,-46,}, + {146,278,100,-80,108,-20,146,-46,114,-40,115,-60,154,-60,32,-80,118,-20,}, + {147,500,}, + {148,500,32,-80,}, + {149,350,}, + {150,556,}, + {151,1000,}, + {152,333,}, + {153,1000,}, + {154,556,119,-15,}, + {155,333,}, + {156,944,}, + {157,278,}, + {158,500,101,10,233,10,234,10,235,10,232,10,}, + {159,667,65,-110,193,-110,194,-110,196,-110,192,-110,197,-110,195,-110,79,-70,211,-70,212,-70,214,-70,210,-70,216,-70,213,-70,97,-90,225,-90,226,-90,228,-90,224,-90,229,-90,227,-90,58,-50,44,-100,101,-80,233,-80,234,-80,235,-80,232,-80,111,-100,243,-100,244,-100,246,-100,242,-100,248,-100,245,-100,46,-100,59,-50,117,-100,250,-100,251,-100,252,-100,249,-100,}, + {160,278,}, + {161,333,}, + {162,556,}, + {163,556,}, + {164,556,}, + {165,556,}, + {166,280,}, + {167,556,}, + {168,333,}, + {169,737,}, + {170,370,}, + {171,556,}, + {172,584,}, + {173,278,}, + {174,737,}, + {175,333,}, + {176,400,}, + {177,584,}, + {178,333,}, + {179,333,}, + {180,333,}, + {181,611,}, + {182,556,}, + {183,278,}, + {184,333,}, + {185,333,}, + {186,365,}, + {187,556,}, + {188,834,}, + {189,834,}, + {190,834,}, + {191,611,}, + {192,722,67,-40,199,-40,71,-50,79,-40,211,-40,212,-40,214,-40,210,-40,216,-40,213,-40,81,-40,84,-90,85,-50,218,-50,219,-50,220,-50,217,-50,86,-80,87,-60,89,-110,221,-110,159,-110,117,-30,250,-30,251,-30,252,-30,249,-30,118,-40,119,-30,121,-30,253,-30,255,-30,}, + {193,722,67,-40,199,-40,71,-50,79,-40,211,-40,212,-40,214,-40,210,-40,216,-40,213,-40,81,-40,84,-90,85,-50,218,-50,219,-50,220,-50,217,-50,86,-80,87,-60,89,-110,221,-110,159,-110,117,-30,250,-30,251,-30,252,-30,249,-30,118,-40,119,-30,121,-30,253,-30,255,-30,}, + {194,722,67,-40,199,-40,71,-50,79,-40,211,-40,212,-40,214,-40,210,-40,216,-40,213,-40,81,-40,84,-90,85,-50,218,-50,219,-50,220,-50,217,-50,86,-80,87,-60,89,-110,221,-110,159,-110,117,-30,250,-30,251,-30,252,-30,249,-30,118,-40,119,-30,121,-30,253,-30,255,-30,}, + {195,722,67,-40,199,-40,71,-50,79,-40,211,-40,212,-40,214,-40,210,-40,216,-40,213,-40,81,-40,84,-90,85,-50,218,-50,219,-50,220,-50,217,-50,86,-80,87,-60,89,-110,221,-110,159,-110,117,-30,250,-30,251,-30,252,-30,249,-30,118,-40,119,-30,121,-30,253,-30,255,-30,}, + {196,722,67,-40,199,-40,71,-50,79,-40,211,-40,212,-40,214,-40,210,-40,216,-40,213,-40,81,-40,84,-90,85,-50,218,-50,219,-50,220,-50,217,-50,86,-80,87,-60,89,-110,221,-110,159,-110,117,-30,250,-30,251,-30,252,-30,249,-30,118,-40,119,-30,121,-30,253,-30,255,-30,}, + {197,722,67,-40,199,-40,71,-50,79,-40,211,-40,212,-40,214,-40,210,-40,216,-40,213,-40,81,-40,84,-90,85,-50,218,-50,219,-50,220,-50,217,-50,86,-80,87,-60,89,-110,221,-110,159,-110,117,-30,250,-30,251,-30,252,-30,249,-30,118,-40,119,-30,121,-30,253,-30,255,-30,}, + {198,1000,}, + {199,722,}, + {200,667,}, + {201,667,}, + {202,667,}, + {203,667,}, + {204,278,}, + {205,278,}, + {206,278,}, + {207,278,}, + {208,722,}, + {209,722,}, + {210,778,65,-50,193,-50,194,-50,196,-50,192,-50,197,-50,195,-50,84,-40,86,-50,87,-50,88,-50,89,-70,221,-70,159,-70,44,-40,46,-40,}, + {211,778,65,-50,193,-50,194,-50,196,-50,192,-50,197,-50,195,-50,84,-40,86,-50,87,-50,88,-50,89,-70,221,-70,159,-70,44,-40,46,-40,}, + {212,778,65,-50,193,-50,194,-50,196,-50,192,-50,197,-50,195,-50,84,-40,86,-50,87,-50,88,-50,89,-70,221,-70,159,-70,44,-40,46,-40,}, + {213,778,65,-50,193,-50,194,-50,196,-50,192,-50,197,-50,195,-50,84,-40,86,-50,87,-50,88,-50,89,-70,221,-70,159,-70,44,-40,46,-40,}, + {214,778,65,-50,193,-50,194,-50,196,-50,192,-50,197,-50,195,-50,84,-40,86,-50,87,-50,88,-50,89,-70,221,-70,159,-70,44,-40,46,-40,}, + {215,584,}, + {216,778,65,-50,193,-50,194,-50,196,-50,192,-50,197,-50,195,-50,84,-40,86,-50,87,-50,88,-50,89,-70,221,-70,159,-70,44,-40,46,-40,}, + {217,722,65,-50,193,-50,194,-50,196,-50,192,-50,197,-50,195,-50,44,-30,46,-30,}, + {218,722,65,-50,193,-50,194,-50,196,-50,192,-50,197,-50,195,-50,44,-30,46,-30,}, + {219,722,65,-50,193,-50,194,-50,196,-50,192,-50,197,-50,195,-50,44,-30,46,-30,}, + {220,722,65,-50,193,-50,194,-50,196,-50,192,-50,197,-50,195,-50,44,-30,46,-30,}, + {221,667,65,-110,193,-110,194,-110,196,-110,192,-110,197,-110,195,-110,79,-70,211,-70,212,-70,214,-70,210,-70,216,-70,213,-70,97,-90,225,-90,226,-90,228,-90,224,-90,229,-90,227,-90,58,-50,44,-100,101,-80,233,-80,234,-80,235,-80,232,-80,111,-100,243,-100,244,-100,246,-100,242,-100,248,-100,245,-100,46,-100,59,-50,117,-100,250,-100,251,-100,252,-100,249,-100,}, + {222,667,}, + {223,611,}, + {224,556,103,-10,118,-15,119,-15,121,-20,253,-20,255,-20,}, + {225,556,103,-10,118,-15,119,-15,121,-20,253,-20,255,-20,}, + {226,556,103,-10,118,-15,119,-15,121,-20,253,-20,255,-20,}, + {227,556,103,-10,118,-15,119,-15,121,-20,253,-20,255,-20,}, + {228,556,103,-10,118,-15,119,-15,121,-20,253,-20,255,-20,}, + {229,556,103,-10,118,-15,119,-15,121,-20,253,-20,255,-20,}, + {230,889,}, + {231,556,104,-10,107,-20,108,-20,121,-10,253,-10,255,-10,}, + {232,556,44,10,46,20,118,-15,119,-15,120,-15,121,-15,253,-15,255,-15,}, + {233,556,44,10,46,20,118,-15,119,-15,120,-15,121,-15,253,-15,255,-15,}, + {234,556,44,10,46,20,118,-15,119,-15,120,-15,121,-15,253,-15,255,-15,}, + {235,556,44,10,46,20,118,-15,119,-15,120,-15,121,-15,253,-15,255,-15,}, + {236,278,}, + {237,278,}, + {238,278,}, + {239,278,}, + {240,611,}, + {241,611,117,-10,250,-10,251,-10,252,-10,249,-10,118,-40,121,-20,253,-20,255,-20,}, + {242,611,118,-20,119,-15,120,-30,121,-20,253,-20,255,-20,}, + {243,611,118,-20,119,-15,120,-30,121,-20,253,-20,255,-20,}, + {244,611,118,-20,119,-15,120,-30,121,-20,253,-20,255,-20,}, + {245,611,118,-20,119,-15,120,-30,121,-20,253,-20,255,-20,}, + {246,611,118,-20,119,-15,120,-30,121,-20,253,-20,255,-20,}, + {247,584,}, + {248,611,118,-20,119,-15,120,-30,121,-20,253,-20,255,-20,}, + {249,611,}, + {250,611,}, + {251,611,}, + {252,611,}, + {253,556,97,-30,225,-30,226,-30,228,-30,224,-30,229,-30,227,-30,44,-80,101,-10,233,-10,234,-10,235,-10,232,-10,111,-25,243,-25,244,-25,246,-25,242,-25,248,-25,245,-25,46,-80,}, + {254,611,}, + {255,556,97,-30,225,-30,226,-30,228,-30,224,-30,229,-30,227,-30,44,-80,101,-10,233,-10,234,-10,235,-10,232,-10,111,-25,243,-25,244,-25,246,-25,242,-25,248,-25,245,-25,46,-80,}, + }; +} diff --git a/PDFJet/src/main/java/com/pdfjet/Helvetica_Oblique.java b/PDFJet/src/main/java/com/pdfjet/Helvetica_Oblique.java new file mode 100644 index 0000000..60a13d2 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Helvetica_Oblique.java @@ -0,0 +1,238 @@ +package com.pdfjet; + +class Helvetica_Oblique { + protected static final String name = "Helvetica-Oblique"; + protected static final int bBoxLLx = -170; + protected static final int bBoxLLy = -225; + protected static final int bBoxURx = 1116; + protected static final int bBoxURy = 931; + protected static final int underlinePosition = -100; + protected static final int underlineThickness = 50; + protected static final String notice = "Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated. All Rights Reserved. Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries."; + protected static final int[][] metrics = { + {32,278,84,-50,86,-50,87,-40,89,-90,221,-90,159,-90,147,-30,145,-60,}, + {33,278,}, + {34,355,}, + {35,556,}, + {36,556,}, + {37,889,}, + {38,667,}, + {39,191,}, + {40,333,}, + {41,333,}, + {42,389,}, + {43,584,}, + {44,278,148,-100,146,-100,}, + {45,333,}, + {46,278,148,-100,146,-100,32,-60,}, + {47,278,}, + {48,556,}, + {49,556,}, + {50,556,}, + {51,556,}, + {52,556,}, + {53,556,}, + {54,556,}, + {55,556,}, + {56,556,}, + {57,556,}, + {58,278,32,-50,}, + {59,278,32,-50,}, + {60,584,}, + {61,584,}, + {62,584,}, + {63,556,}, + {64,1015,}, + {65,667,67,-30,199,-30,71,-30,79,-30,211,-30,212,-30,214,-30,210,-30,216,-30,213,-30,81,-30,84,-120,85,-50,218,-50,219,-50,220,-50,217,-50,86,-70,87,-50,89,-100,221,-100,159,-100,117,-30,250,-30,251,-30,252,-30,249,-30,118,-40,119,-40,121,-40,253,-40,255,-40,}, + {66,667,85,-10,218,-10,219,-10,220,-10,217,-10,44,-20,46,-20,}, + {67,722,44,-30,46,-30,}, + {68,722,65,-40,193,-40,194,-40,196,-40,192,-40,197,-40,195,-40,86,-70,87,-40,89,-90,221,-90,159,-90,44,-70,46,-70,}, + {69,667,}, + {70,611,65,-80,193,-80,194,-80,196,-80,192,-80,197,-80,195,-80,97,-50,225,-50,226,-50,228,-50,224,-50,229,-50,227,-50,44,-150,101,-30,233,-30,234,-30,235,-30,232,-30,111,-30,243,-30,244,-30,246,-30,242,-30,248,-30,245,-30,46,-150,114,-45,}, + {71,778,}, + {72,722,}, + {73,278,}, + {74,500,65,-20,193,-20,194,-20,196,-20,192,-20,197,-20,195,-20,97,-20,225,-20,226,-20,228,-20,224,-20,229,-20,227,-20,44,-30,46,-30,117,-20,250,-20,251,-20,252,-20,249,-20,}, + {75,667,79,-50,211,-50,212,-50,214,-50,210,-50,216,-50,213,-50,101,-40,233,-40,234,-40,235,-40,232,-40,111,-40,243,-40,244,-40,246,-40,242,-40,248,-40,245,-40,117,-30,250,-30,251,-30,252,-30,249,-30,121,-50,253,-50,255,-50,}, + {76,556,84,-110,86,-110,87,-70,89,-140,221,-140,159,-140,148,-140,146,-160,121,-30,253,-30,255,-30,}, + {77,833,}, + {78,722,}, + {79,778,65,-20,193,-20,194,-20,196,-20,192,-20,197,-20,195,-20,84,-40,86,-50,87,-30,88,-60,89,-70,221,-70,159,-70,44,-40,46,-40,}, + {80,667,65,-120,193,-120,194,-120,196,-120,192,-120,197,-120,195,-120,97,-40,225,-40,226,-40,228,-40,224,-40,229,-40,227,-40,44,-180,101,-50,233,-50,234,-50,235,-50,232,-50,111,-50,243,-50,244,-50,246,-50,242,-50,248,-50,245,-50,46,-180,}, + {81,778,85,-10,218,-10,219,-10,220,-10,217,-10,}, + {82,722,79,-20,211,-20,212,-20,214,-20,210,-20,216,-20,213,-20,84,-30,85,-40,218,-40,219,-40,220,-40,217,-40,86,-50,87,-30,89,-50,221,-50,159,-50,}, + {83,667,44,-20,46,-20,}, + {84,611,65,-120,193,-120,194,-120,196,-120,192,-120,197,-120,195,-120,79,-40,211,-40,212,-40,214,-40,210,-40,216,-40,213,-40,97,-120,225,-120,226,-120,228,-120,224,-120,229,-120,227,-60,58,-20,44,-120,101,-120,233,-120,234,-120,235,-120,232,-60,45,-140,111,-120,243,-120,244,-120,246,-120,242,-120,248,-120,245,-60,46,-120,114,-120,59,-20,117,-120,250,-120,251,-120,252,-120,249,-120,119,-120,121,-120,253,-120,255,-60,}, + {85,722,65,-40,193,-40,194,-40,196,-40,192,-40,197,-40,195,-40,44,-40,46,-40,}, + {86,667,65,-80,193,-80,194,-80,196,-80,192,-80,197,-80,195,-80,71,-40,79,-40,211,-40,212,-40,214,-40,210,-40,216,-40,213,-40,97,-70,225,-70,226,-70,228,-70,224,-70,229,-70,227,-70,58,-40,44,-125,101,-80,233,-80,234,-80,235,-80,232,-80,45,-80,111,-80,243,-80,244,-80,246,-80,242,-80,248,-80,245,-80,46,-125,59,-40,117,-70,250,-70,251,-70,252,-70,249,-70,}, + {87,944,65,-50,193,-50,194,-50,196,-50,192,-50,197,-50,195,-50,79,-20,211,-20,212,-20,214,-20,210,-20,216,-20,213,-20,97,-40,225,-40,226,-40,228,-40,224,-40,229,-40,227,-40,44,-80,101,-30,233,-30,234,-30,235,-30,232,-30,45,-40,111,-30,243,-30,244,-30,246,-30,242,-30,248,-30,245,-30,46,-80,117,-30,250,-30,251,-30,252,-30,249,-30,121,-20,253,-20,255,-20,}, + {88,667,}, + {89,667,65,-110,193,-110,194,-110,196,-110,192,-110,197,-110,195,-110,79,-85,211,-85,212,-85,214,-85,210,-85,216,-85,213,-85,97,-140,225,-140,226,-140,228,-140,224,-140,229,-140,227,-140,58,-60,44,-140,101,-140,233,-140,234,-140,235,-140,232,-140,45,-140,105,-20,237,-20,111,-140,243,-140,244,-140,246,-140,242,-140,248,-140,245,-140,46,-140,59,-60,117,-110,250,-110,251,-110,252,-110,249,-110,}, + {90,611,}, + {91,278,}, + {92,278,}, + {93,278,}, + {94,469,}, + {95,556,}, + {96,333,}, + {97,556,118,-20,119,-20,121,-30,253,-30,255,-30,}, + {98,556,98,-10,44,-40,108,-20,46,-40,117,-20,250,-20,251,-20,252,-20,249,-20,118,-20,121,-20,253,-20,255,-20,}, + {99,500,44,-15,107,-20,}, + {100,556,}, + {101,556,44,-15,46,-15,118,-30,119,-20,120,-30,121,-20,253,-20,255,-20,}, + {102,278,97,-30,225,-30,226,-30,228,-30,224,-30,229,-30,227,-30,44,-30,101,-30,233,-30,234,-30,235,-30,232,-30,111,-30,243,-30,244,-30,246,-30,242,-30,248,-30,245,-30,46,-30,148,60,146,50,}, + {103,556,114,-10,}, + {104,556,121,-30,253,-30,255,-30,}, + {105,222,}, + {106,222,}, + {107,500,101,-20,233,-20,234,-20,235,-20,232,-20,111,-20,243,-20,244,-20,246,-20,242,-20,248,-20,245,-20,}, + {108,222,}, + {109,833,117,-10,250,-10,251,-10,252,-10,249,-10,121,-15,253,-15,255,-15,}, + {110,556,117,-10,250,-10,251,-10,252,-10,249,-10,118,-20,121,-15,253,-15,255,-15,}, + {111,556,44,-40,46,-40,118,-15,119,-15,120,-30,121,-30,253,-30,255,-30,}, + {112,556,44,-35,46,-35,121,-30,253,-30,255,-30,}, + {113,556,}, + {114,333,97,-10,225,-10,226,-10,228,-10,224,-10,229,-10,227,-10,58,30,44,-50,105,15,237,15,238,15,239,15,236,15,107,15,108,15,109,25,110,25,241,25,112,30,46,-50,59,30,116,40,117,15,250,15,251,15,252,15,249,15,118,30,121,30,253,30,255,30,}, + {115,500,44,-15,46,-15,119,-30,}, + {116,278,}, + {117,556,}, + {118,500,97,-25,225,-25,226,-25,228,-25,224,-25,229,-25,227,-25,44,-80,101,-25,233,-25,234,-25,235,-25,232,-25,111,-25,243,-25,244,-25,246,-25,242,-25,248,-25,245,-25,46,-80,}, + {119,722,97,-15,225,-15,226,-15,228,-15,224,-15,229,-15,227,-15,44,-60,101,-10,233,-10,234,-10,235,-10,232,-10,111,-10,243,-10,244,-10,246,-10,242,-10,248,-10,245,-10,46,-60,}, + {120,500,101,-30,233,-30,234,-30,235,-30,232,-30,}, + {121,500,97,-20,225,-20,226,-20,228,-20,224,-20,229,-20,227,-20,44,-100,101,-20,233,-20,234,-20,235,-20,232,-20,111,-20,243,-20,244,-20,246,-20,242,-20,248,-20,245,-20,46,-100,}, + {122,500,101,-15,233,-15,234,-15,235,-15,232,-15,111,-15,243,-15,244,-15,246,-15,242,-15,248,-15,245,-15,}, + {123,334,}, + {124,260,}, + {125,334,}, + {126,584,}, + {127,278,}, + {128,556,}, + {129,278,}, + {130,222,}, + {131,556,}, + {132,333,}, + {133,1000,}, + {134,556,}, + {135,556,}, + {136,333,}, + {137,1000,}, + {138,667,44,-20,46,-20,}, + {139,333,}, + {140,1000,}, + {141,278,}, + {142,611,}, + {143,278,}, + {144,278,}, + {145,222,145,-57,}, + {146,222,100,-50,146,-57,114,-50,115,-50,154,-50,32,-70,}, + {147,333,}, + {148,333,32,-40,}, + {149,350,}, + {150,556,}, + {151,1000,}, + {152,333,}, + {153,1000,}, + {154,500,44,-15,46,-15,119,-30,}, + {155,333,}, + {156,944,}, + {157,278,}, + {158,500,101,-15,233,-15,234,-15,235,-15,232,-15,111,-15,243,-15,244,-15,246,-15,242,-15,248,-15,245,-15,}, + {159,667,65,-110,193,-110,194,-110,196,-110,192,-110,197,-110,195,-110,79,-85,211,-85,212,-85,214,-85,210,-85,216,-85,213,-85,97,-140,225,-140,226,-140,228,-140,224,-140,229,-140,227,-70,58,-60,44,-140,101,-140,233,-140,234,-140,235,-140,232,-140,45,-140,105,-20,237,-20,111,-140,243,-140,244,-140,246,-140,242,-140,248,-140,245,-140,46,-140,59,-60,117,-110,250,-110,251,-110,252,-110,249,-110,}, + {160,278,}, + {161,333,}, + {162,556,}, + {163,556,}, + {164,556,}, + {165,556,}, + {166,260,}, + {167,556,}, + {168,333,}, + {169,737,}, + {170,370,}, + {171,556,}, + {172,584,}, + {173,278,}, + {174,737,}, + {175,333,}, + {176,400,}, + {177,584,}, + {178,333,}, + {179,333,}, + {180,333,}, + {181,556,}, + {182,537,}, + {183,278,}, + {184,333,}, + {185,333,}, + {186,365,}, + {187,556,}, + {188,834,}, + {189,834,}, + {190,834,}, + {191,611,}, + {192,667,67,-30,199,-30,71,-30,79,-30,211,-30,212,-30,214,-30,210,-30,216,-30,213,-30,81,-30,84,-120,85,-50,218,-50,219,-50,220,-50,217,-50,86,-70,87,-50,89,-100,221,-100,159,-100,117,-30,250,-30,251,-30,252,-30,249,-30,118,-40,119,-40,121,-40,253,-40,255,-40,}, + {193,667,67,-30,199,-30,71,-30,79,-30,211,-30,212,-30,214,-30,210,-30,216,-30,213,-30,81,-30,84,-120,85,-50,218,-50,219,-50,220,-50,217,-50,86,-70,87,-50,89,-100,221,-100,159,-100,117,-30,250,-30,251,-30,252,-30,249,-30,118,-40,119,-40,121,-40,253,-40,255,-40,}, + {194,667,67,-30,199,-30,71,-30,79,-30,211,-30,212,-30,214,-30,210,-30,216,-30,213,-30,81,-30,84,-120,85,-50,218,-50,219,-50,220,-50,217,-50,86,-70,87,-50,89,-100,221,-100,159,-100,117,-30,250,-30,251,-30,252,-30,249,-30,118,-40,119,-40,121,-40,253,-40,255,-40,}, + {195,667,67,-30,199,-30,71,-30,79,-30,211,-30,212,-30,214,-30,210,-30,216,-30,213,-30,81,-30,84,-120,85,-50,218,-50,219,-50,220,-50,217,-50,86,-70,87,-50,89,-100,221,-100,159,-100,117,-30,250,-30,251,-30,252,-30,249,-30,118,-40,119,-40,121,-40,253,-40,255,-40,}, + {196,667,67,-30,199,-30,71,-30,79,-30,211,-30,212,-30,214,-30,210,-30,216,-30,213,-30,81,-30,84,-120,85,-50,218,-50,219,-50,220,-50,217,-50,86,-70,87,-50,89,-100,221,-100,159,-100,117,-30,250,-30,251,-30,252,-30,249,-30,118,-40,119,-40,121,-40,253,-40,255,-40,}, + {197,667,67,-30,199,-30,71,-30,79,-30,211,-30,212,-30,214,-30,210,-30,216,-30,213,-30,81,-30,84,-120,85,-50,218,-50,219,-50,220,-50,217,-50,86,-70,87,-50,89,-100,221,-100,159,-100,117,-30,250,-30,251,-30,252,-30,249,-30,118,-40,119,-40,121,-40,253,-40,255,-40,}, + {198,1000,}, + {199,722,44,-30,46,-30,}, + {200,667,}, + {201,667,}, + {202,667,}, + {203,667,}, + {204,278,}, + {205,278,}, + {206,278,}, + {207,278,}, + {208,722,}, + {209,722,}, + {210,778,65,-20,193,-20,194,-20,196,-20,192,-20,197,-20,195,-20,84,-40,86,-50,87,-30,88,-60,89,-70,221,-70,159,-70,44,-40,46,-40,}, + {211,778,65,-20,193,-20,194,-20,196,-20,192,-20,197,-20,195,-20,84,-40,86,-50,87,-30,88,-60,89,-70,221,-70,159,-70,44,-40,46,-40,}, + {212,778,65,-20,193,-20,194,-20,196,-20,192,-20,197,-20,195,-20,84,-40,86,-50,87,-30,88,-60,89,-70,221,-70,159,-70,44,-40,46,-40,}, + {213,778,65,-20,193,-20,194,-20,196,-20,192,-20,197,-20,195,-20,84,-40,86,-50,87,-30,88,-60,89,-70,221,-70,159,-70,44,-40,46,-40,}, + {214,778,65,-20,193,-20,194,-20,196,-20,192,-20,197,-20,195,-20,84,-40,86,-50,87,-30,88,-60,89,-70,221,-70,159,-70,44,-40,46,-40,}, + {215,584,}, + {216,778,65,-20,193,-20,194,-20,196,-20,192,-20,197,-20,195,-20,84,-40,86,-50,87,-30,88,-60,89,-70,221,-70,159,-70,44,-40,46,-40,}, + {217,722,65,-40,193,-40,194,-40,196,-40,192,-40,197,-40,195,-40,44,-40,46,-40,}, + {218,722,65,-40,193,-40,194,-40,196,-40,192,-40,197,-40,195,-40,44,-40,46,-40,}, + {219,722,65,-40,193,-40,194,-40,196,-40,192,-40,197,-40,195,-40,44,-40,46,-40,}, + {220,722,65,-40,193,-40,194,-40,196,-40,192,-40,197,-40,195,-40,44,-40,46,-40,}, + {221,667,65,-110,193,-110,194,-110,196,-110,192,-110,197,-110,195,-110,79,-85,211,-85,212,-85,214,-85,210,-85,216,-85,213,-85,97,-140,225,-140,226,-140,228,-140,224,-140,229,-140,227,-70,58,-60,44,-140,101,-140,233,-140,234,-140,235,-140,232,-140,45,-140,105,-20,237,-20,111,-140,243,-140,244,-140,246,-140,242,-140,248,-140,245,-140,46,-140,59,-60,117,-110,250,-110,251,-110,252,-110,249,-110,}, + {222,667,}, + {223,611,}, + {224,556,118,-20,119,-20,121,-30,253,-30,255,-30,}, + {225,556,118,-20,119,-20,121,-30,253,-30,255,-30,}, + {226,556,118,-20,119,-20,121,-30,253,-30,255,-30,}, + {227,556,118,-20,119,-20,121,-30,253,-30,255,-30,}, + {228,556,118,-20,119,-20,121,-30,253,-30,255,-30,}, + {229,556,118,-20,119,-20,121,-30,253,-30,255,-30,}, + {230,889,}, + {231,500,44,-15,107,-20,}, + {232,556,44,-15,46,-15,118,-30,119,-20,120,-30,121,-20,253,-20,255,-20,}, + {233,556,44,-15,46,-15,118,-30,119,-20,120,-30,121,-20,253,-20,255,-20,}, + {234,556,44,-15,46,-15,118,-30,119,-20,120,-30,121,-20,253,-20,255,-20,}, + {235,556,44,-15,46,-15,118,-30,119,-20,120,-30,121,-20,253,-20,255,-20,}, + {236,278,}, + {237,278,}, + {238,278,}, + {239,278,}, + {240,556,}, + {241,556,117,-10,250,-10,251,-10,252,-10,249,-10,118,-20,121,-15,253,-15,255,-15,}, + {242,556,44,-40,46,-40,118,-15,119,-15,120,-30,121,-30,253,-30,255,-30,}, + {243,556,44,-40,46,-40,118,-15,119,-15,120,-30,121,-30,253,-30,255,-30,}, + {244,556,44,-40,46,-40,118,-15,119,-15,120,-30,121,-30,253,-30,255,-30,}, + {245,556,44,-40,46,-40,118,-15,119,-15,120,-30,121,-30,253,-30,255,-30,}, + {246,556,44,-40,46,-40,118,-15,119,-15,120,-30,121,-30,253,-30,255,-30,}, + {247,584,}, + {248,611,97,-55,225,-55,226,-55,228,-55,224,-55,229,-55,227,-55,98,-55,99,-55,231,-55,44,-95,100,-55,101,-55,233,-55,234,-55,235,-55,232,-55,102,-55,103,-55,104,-55,105,-55,237,-55,238,-55,239,-55,236,-55,106,-55,107,-55,108,-55,109,-55,110,-55,241,-55,111,-55,243,-55,244,-55,246,-55,242,-55,248,-55,245,-55,112,-55,46,-95,113,-55,114,-55,115,-55,154,-55,116,-55,117,-55,250,-55,251,-55,252,-55,249,-55,118,-70,119,-70,120,-85,121,-70,253,-70,255,-70,122,-55,158,-55,}, + {249,556,}, + {250,556,}, + {251,556,}, + {252,556,}, + {253,500,97,-20,225,-20,226,-20,228,-20,224,-20,229,-20,227,-20,44,-100,101,-20,233,-20,234,-20,235,-20,232,-20,111,-20,243,-20,244,-20,246,-20,242,-20,248,-20,245,-20,46,-100,}, + {254,556,}, + {255,500,97,-20,225,-20,226,-20,228,-20,224,-20,229,-20,227,-20,44,-100,101,-20,233,-20,234,-20,235,-20,232,-20,111,-20,243,-20,244,-20,246,-20,242,-20,248,-20,245,-20,46,-100,}, + }; +} diff --git a/PDFJet/src/main/java/com/pdfjet/ICCBlackScaled.java b/PDFJet/src/main/java/com/pdfjet/ICCBlackScaled.java new file mode 100644 index 0000000..9c317ea --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/ICCBlackScaled.java @@ -0,0 +1,2584 @@ +package com.pdfjet; + + +class ICCBlackScaled { + public static byte[] profile = { +(byte) 0x78, +(byte) 0x9C, +(byte) 0xB5, +(byte) 0x56, +(byte) 0x79, +(byte) 0x3C, +(byte) 0x94, +(byte) 0x6B, +(byte) 0x1B, +(byte) 0x7E, +(byte) 0xDE, +(byte) 0xF7, +(byte) 0x9D, +(byte) 0x7D, +(byte) 0xB1, +(byte) 0xCD, +(byte) 0x90, +(byte) 0xDD, +(byte) 0xD8, +(byte) 0xB7, +(byte) 0x46, +(byte) 0x96, +(byte) 0x30, +(byte) 0xC8, +(byte) 0xBE, +(byte) 0x93, +(byte) 0xC8, +(byte) 0x4E, +(byte) 0x9B, +(byte) 0x31, +(byte) 0x33, +(byte) 0x18, +(byte) 0xCB, +(byte) 0x60, +(byte) 0xCC, +(byte) 0xA0, +(byte) 0xD2, +(byte) 0x26, +(byte) 0xA9, +(byte) 0x70, +(byte) 0x22, +(byte) 0x49, +(byte) 0xB6, +(byte) 0x12, +(byte) 0x39, +(byte) 0x15, +(byte) 0x3A, +(byte) 0x74, +(byte) 0x5A, +(byte) 0x90, +(byte) 0xD3, +(byte) 0x22, +(byte) 0x2D, +(byte) 0xDA, +(byte) 0x8E, +(byte) 0xD2, +(byte) 0xA6, +(byte) 0xA2, +(byte) 0xCE, +(byte) 0xC8, +(byte) 0x11, +(byte) 0xAA, +(byte) 0xD3, +(byte) 0xD1, +(byte) 0x22, +(byte) 0x95, +(byte) 0xCA, +(byte) 0xF7, +(byte) 0x0E, +(byte) 0x7F, +(byte) 0xE8, +(byte) 0xFB, +(byte) 0x7D, +(byte) 0xE7, +(byte) 0xCF, +(byte) 0xF3, +(byte) 0x5D, +(byte) 0xBF, +(byte) 0xDF, +(byte) 0xF3, +(byte) 0xBC, +(byte) 0xD7, +(byte) 0x7B, +(byte) 0xFD, +(byte) 0xEE, +(byte) 0xFB, +(byte) 0x7E, +(byte) 0xEE, +(byte) 0xE7, +(byte) 0x7E, +(byte) 0xFF, +(byte) 0x78, +(byte) 0x2F, +(byte) 0x00, +(byte) 0xC8, +(byte) 0x63, +(byte) 0x00, +(byte) 0x05, +(byte) 0x8C, +(byte) 0xAE, +(byte) 0x14, +(byte) 0x81, +(byte) 0x48, +(byte) 0x18, +(byte) 0xEC, +(byte) 0xED, +(byte) 0xC6, +(byte) 0x88, +(byte) 0x8C, +(byte) 0x8A, +(byte) 0x66, +(byte) 0xE0, +(byte) 0x1F, +(byte) 0x03, +(byte) 0x04, +(byte) 0xA8, +(byte) 0x01, +(byte) 0x45, +(byte) 0xA0, +(byte) 0x07, +(byte) 0xB4, +(byte) 0xD8, +(byte) 0x9C, +(byte) 0x8C, +(byte) 0x34, +(byte) 0xF0, +(byte) 0xBF, +(byte) 0x80, +(byte) 0xE6, +(byte) 0xE9, +(byte) 0xC7, +(byte) 0x87, +(byte) 0x73, +(byte) 0x6F, +(byte) 0xF7, +(byte) 0x98, +(byte) 0xD2, +(byte) 0xDD, +(byte) 0xF8, +(byte) 0x93, +(byte) 0xE3, +(byte) 0xB3, +(byte) 0xD6, +(byte) 0x77, +(byte) 0x61, +(byte) 0x2D, +(byte) 0xD9, +(byte) 0x6E, +(byte) 0x5F, +(byte) 0xFE, +(byte) 0xBC, +(byte) 0xB1, +(byte) 0xD5, +(byte) 0x8E, +(byte) 0xFA, +(byte) 0x0F, +(byte) 0xB9, +(byte) 0x3F, +(byte) 0x42, +(byte) 0x8E, +(byte) 0xCB, +(byte) 0xCB, +(byte) 0xE0, +(byte) 0xA0, +(byte) 0xE5, +(byte) 0x3C, +(byte) 0x50, +(byte) 0xBE, +(byte) 0x36, +(byte) 0x16, +(byte) 0x3D, +(byte) 0x1C, +(byte) 0xE5, +(byte) 0x5D, +(byte) 0x28, +(byte) 0xA7, +(byte) 0xC7, +(byte) 0x86, +(byte) 0x06, +(byte) 0xBB, +(byte) 0xA3, +(byte) 0xFC, +(byte) 0x3E, +(byte) 0x00, +(byte) 0x04, +(byte) 0x0A, +(byte) 0x37, +(byte) 0x85, +(byte) 0xCB, +(byte) 0x05, +(byte) 0x80, +(byte) 0x28, +(byte) 0x41, +(byte) 0xF5, +(byte) 0x1D, +(byte) 0xF1, +(byte) 0xB3, +(byte) 0x31, +(byte) 0xA4, +(byte) 0x04, +(byte) 0x69, +(byte) 0x4C, +(byte) 0xFC, +(byte) 0x0F, +(byte) 0x31, +(byte) 0xC9, +(byte) 0xE2, +(byte) 0x14, +(byte) 0x3E, +(byte) 0xAA, +(byte) 0xE7, +(byte) 0x48, +(byte) 0xF5, +(byte) 0x14, +(byte) 0x1E, +(byte) 0x3B, +(byte) 0x03, +(byte) 0xE5, +(byte) 0x25, +(byte) 0x28, +(byte) 0xD7, +(byte) 0x8B, +(byte) 0x4D, +(byte) 0x4A, +(byte) 0x13, +(byte) 0xA1, +(byte) 0xFC, +(byte) 0x94, +(byte) 0x54, +(byte) 0x17, +(byte) 0xCE, +(byte) 0xE5, +(byte) 0x5E, +(byte) 0x9B, +(byte) 0xE5, +(byte) 0x3F, +(byte) 0xE4, +(byte) 0x8A, +(byte) 0x78, +(byte) 0x1C, +(byte) 0xB4, +(byte) 0x1E, +(byte) 0x69, +(byte) 0x10, +(byte) 0xD5, +(byte) 0x29, +(byte) 0x99, +(byte) 0x62, +(byte) 0x1E, +(byte) 0x7A, +(byte) 0x16, +(byte) 0x49, +(byte) 0x3A, +(byte) 0x97, +(byte) 0xED, +(byte) 0x59, +(byte) 0x22, +(byte) 0x69, +(byte) 0x2E, +(byte) 0x59, +(byte) 0x7A, +(byte) 0x7F, +(byte) 0x3A, +(byte) 0x27, +(byte) 0x4D, +(byte) 0x28, +(byte) 0xE5, +(byte) 0x79, +(byte) 0x28, +(byte) 0xB7, +(byte) 0xE5, +(byte) 0x24, +(byte) 0xB0, +(byte) 0xD1, +(byte) 0x18, +(byte) 0xF2, +(byte) 0x59, +(byte) 0x94, +(byte) 0x2F, +(byte) 0x9C, +(byte) 0xEB, +(byte) 0x7F, +(byte) 0x16, +(byte) 0x5A, +(byte) 0x19, +(byte) 0xD2, +(byte) 0x01, +(byte) 0xFA, +(byte) 0x7A, +(byte) 0xBA, +(byte) 0xDB, +(byte) 0x58, +(byte) 0xD8, +(byte) 0xD9, +(byte) 0xD8, +(byte) 0x30, +(byte) 0x2D, +(byte) 0x99, +(byte) 0x16, +(byte) 0x8C, +(byte) 0xD8, +(byte) 0x64, +(byte) 0x36, +(byte) 0x27, +(byte) 0x89, +(byte) 0x91, +(byte) 0xC1, +(byte) 0x61, +(byte) 0x27, +(byte) 0x4B, +(byte) 0xAB, +(byte) 0xFE, +(byte) 0xDB, +(byte) 0x90, +(byte) 0x7E, +(byte) 0xAB, +(byte) 0x39, +(byte) 0xA6, +(byte) 0x77, +(byte) 0x10, +(byte) 0x00, +(byte) 0x59, +(byte) 0xB4, +(byte) 0xB7, +(byte) 0xB6, +(byte) 0xDB, +(byte) 0x1C, +(byte) 0xB1, +(byte) 0x30, +(byte) 0x73, +(byte) 0x4E, +(byte) 0xC3, +(byte) 0x48, +(byte) 0x37, +(byte) 0x2C, +(byte) 0x20, +(byte) 0x01, +(byte) 0x59, +(byte) 0x40, +(byte) 0x07, +(byte) 0x2A, +(byte) 0x40, +(byte) 0x13, +(byte) 0xE8, +(byte) 0x02, +(byte) 0x23, +(byte) 0xC0, +(byte) 0x04, +(byte) 0x96, +(byte) 0xC0, +(byte) 0x16, +(byte) 0x38, +(byte) 0x00, +(byte) 0x17, +(byte) 0xE0, +(byte) 0x09, +(byte) 0xFC, +(byte) 0x40, +(byte) 0x20, +(byte) 0x08, +(byte) 0x05, +(byte) 0x51, +(byte) 0x60, +(byte) 0x35, +(byte) 0xE0, +(byte) 0x80, +(byte) 0x04, +(byte) 0x90, +(byte) 0x02, +(byte) 0x84, +(byte) 0x20, +(byte) 0x0B, +(byte) 0xE4, +(byte) 0x80, +(byte) 0x2D, +(byte) 0x20, +(byte) 0x1F, +(byte) 0x14, +(byte) 0x82, +(byte) 0x12, +(byte) 0xB0, +(byte) 0x17, +(byte) 0x54, +(byte) 0x81, +(byte) 0x5A, +(byte) 0xD0, +(byte) 0x00, +(byte) 0x1A, +(byte) 0x41, +(byte) 0x0B, +(byte) 0x38, +(byte) 0x01, +(byte) 0xDA, +(byte) 0xC1, +(byte) 0x59, +(byte) 0x70, +(byte) 0x11, +(byte) 0x5C, +(byte) 0x05, +(byte) 0x37, +(byte) 0xC1, +(byte) 0x1D, +(byte) 0xF0, +(byte) 0x00, +(byte) 0x0C, +(byte) 0x00, +(byte) 0x09, +(byte) 0x18, +(byte) 0x01, +(byte) 0xAF, +(byte) 0xC0, +(byte) 0x04, +(byte) 0xF8, +(byte) 0x08, +(byte) 0xA6, +(byte) 0x21, +(byte) 0x08, +(byte) 0xC2, +(byte) 0x43, +(byte) 0x54, +(byte) 0x88, +(byte) 0x06, +(byte) 0xA9, +(byte) 0x40, +(byte) 0x5A, +(byte) 0x90, +(byte) 0x3E, +(byte) 0x64, +(byte) 0x0A, +(byte) 0x59, +(byte) 0x42, +(byte) 0x2C, +(byte) 0xC8, +(byte) 0x09, +(byte) 0xF2, +(byte) 0x84, +(byte) 0x96, +(byte) 0x42, +(byte) 0xC1, +(byte) 0x50, +(byte) 0x14, +(byte) 0x14, +(byte) 0x03, +(byte) 0xC5, +(byte) 0x43, +(byte) 0x02, +(byte) 0x48, +(byte) 0x0C, +(byte) 0xE5, +(byte) 0x40, +(byte) 0x5B, +(byte) 0xA1, +(byte) 0x42, +(byte) 0xA8, +(byte) 0x14, +(byte) 0xAA, +(byte) 0x82, +(byte) 0xEA, +(byte) 0xA0, +(byte) 0x46, +(byte) 0xE8, +(byte) 0x57, +(byte) 0xE8, +(byte) 0x0C, +(byte) 0x74, +(byte) 0x11, +(byte) 0xBA, +(byte) 0x0E, +(byte) 0xF5, +(byte) 0x41, +(byte) 0x8F, +(byte) 0xA1, +(byte) 0x21, +(byte) 0x68, +(byte) 0x1C, +(byte) 0x7A, +(byte) 0x07, +(byte) 0x7D, +(byte) 0x81, +(byte) 0x11, +(byte) 0x98, +(byte) 0x02, +(byte) 0xD3, +(byte) 0x61, +(byte) 0x0D, +(byte) 0xD8, +(byte) 0x00, +(byte) 0x5E, +(byte) 0x04, +(byte) 0xB3, +(byte) 0x60, +(byte) 0x57, +(byte) 0xD8, +(byte) 0x1F, +(byte) 0x0E, +(byte) 0x85, +(byte) 0x57, +(byte) 0xC1, +(byte) 0xF1, +(byte) 0x70, +(byte) 0x3A, +(byte) 0xBC, +(byte) 0x0E, +(byte) 0xCE, +(byte) 0x83, +(byte) 0x77, +(byte) 0xC1, +(byte) 0x15, +(byte) 0x70, +(byte) 0x3D, +(byte) 0x7C, +(byte) 0x0C, +(byte) 0x6E, +(byte) 0x83, +(byte) 0x2F, +(byte) 0xC2, +(byte) 0x37, +(byte) 0xE1, +(byte) 0x07, +(byte) 0xB0, +(byte) 0x04, +(byte) 0x7E, +(byte) 0x05, +(byte) 0x4F, +(byte) 0x22, +(byte) 0x00, +(byte) 0x21, +(byte) 0x23, +(byte) 0x4A, +(byte) 0x88, +(byte) 0x36, +(byte) 0xC2, +(byte) 0x44, +(byte) 0x58, +(byte) 0x88, +(byte) 0x3B, +(byte) 0x12, +(byte) 0x88, +(byte) 0x44, +(byte) 0x23, +(byte) 0x71, +(byte) 0x88, +(byte) 0x10, +(byte) 0xD9, +(byte) 0x88, +(byte) 0x14, +(byte) 0x20, +(byte) 0xE5, +(byte) 0x48, +(byte) 0x3D, +(byte) 0xD2, +(byte) 0x82, +(byte) 0x74, +(byte) 0x22, +(byte) 0x3D, +(byte) 0xC8, +(byte) 0x3D, +(byte) 0x44, +(byte) 0x82, +(byte) 0xBC, +(byte) 0x46, +(byte) 0x3E, +(byte) 0x63, +(byte) 0x70, +(byte) 0x18, +(byte) 0x1A, +(byte) 0x86, +(byte) 0x81, +(byte) 0x61, +(byte) 0x62, +(byte) 0x1C, +(byte) 0x30, +(byte) 0x3E, +(byte) 0x98, +(byte) 0x30, +(byte) 0x0C, +(byte) 0x07, +(byte) 0x93, +(byte) 0x8E, +(byte) 0xD9, +(byte) 0x88, +(byte) 0x29, +(byte) 0xC2, +(byte) 0x54, +(byte) 0x61, +(byte) 0x8E, +(byte) 0x62, +(byte) 0xDA, +(byte) 0x30, +(byte) 0x97, +(byte) 0x31, +(byte) 0xF7, +(byte) 0x30, +(byte) 0x43, +(byte) 0x98, +(byte) 0x09, +(byte) 0xCC, +(byte) 0x77, +(byte) 0x2C, +(byte) 0x15, +(byte) 0xAB, +(byte) 0x8E, +(byte) 0x35, +(byte) 0xC5, +(byte) 0xDA, +(byte) 0x63, +(byte) 0x7D, +(byte) 0xB1, +(byte) 0x91, +(byte) 0xD8, +(byte) 0x78, +(byte) 0x6C, +(byte) 0x16, +(byte) 0x36, +(byte) 0x1F, +(byte) 0x5B, +(byte) 0x8E, +(byte) 0x3D, +(byte) 0x8C, +(byte) 0x3D, +(byte) 0x8D, +(byte) 0xBD, +(byte) 0x82, +(byte) 0x7D, +(byte) 0x80, +(byte) 0x1D, +(byte) 0xC1, +(byte) 0x7E, +(byte) 0xC4, +(byte) 0xE1, +(byte) 0x70, +(byte) 0x4A, +(byte) 0x38, +(byte) 0x43, +(byte) 0x9C, +(byte) 0x2D, +(byte) 0xCE, +(byte) 0x07, +(byte) 0x17, +(byte) 0x85, +(byte) 0x4B, +(byte) 0xC4, +(byte) 0xAD, +(byte) 0xC7, +(byte) 0x15, +(byte) 0xE1, +(byte) 0xF6, +(byte) 0xE3, +(byte) 0x5A, +(byte) 0x71, +(byte) 0x5D, +(byte) 0xB8, +(byte) 0x3E, +(byte) 0xDC, +(byte) 0x30, +(byte) 0x6E, +(byte) 0x12, +(byte) 0x8F, +(byte) 0xC7, +(byte) 0xAB, +(byte) 0xE0, +(byte) 0x4D, +(byte) 0xF1, +(byte) 0x8E, +(byte) 0xF8, +(byte) 0x40, +(byte) 0x3C, +(byte) 0x1B, +(byte) 0x2F, +(byte) 0xC2, +(byte) 0xE7, +(byte) 0xE3, +(byte) 0x2B, +(byte) 0xF1, +(byte) 0xC7, +(byte) 0xF0, +(byte) 0x17, +(byte) 0xF0, +(byte) 0x77, +(byte) 0xF1, +(byte) 0x23, +(byte) 0xF8, +(byte) 0x4F, +(byte) 0x04, +(byte) 0x32, +(byte) 0x41, +(byte) 0x8B, +(byte) 0x60, +(byte) 0x49, +(byte) 0xF0, +(byte) 0x22, +(byte) 0x44, +(byte) 0x13, +(byte) 0x04, +(byte) 0x84, +(byte) 0x5C, +(byte) 0x42, +(byte) 0x39, +(byte) 0xA1, +(byte) 0x89, +(byte) 0x70, +(byte) 0x9E, +(byte) 0x70, +(byte) 0x97, +(byte) 0x30, +(byte) 0x4A, +(byte) 0x98, +(byte) 0x26, +(byte) 0xCA, +(byte) 0x11, +(byte) 0xF5, +(byte) 0x89, +(byte) 0xF6, +(byte) 0xC4, +(byte) 0x40, +(byte) 0x22, +(byte) 0x97, +(byte) 0xB8, +(byte) 0x96, +(byte) 0x58, +(byte) 0x4C, +(byte) 0x6C, +(byte) 0x20, +(byte) 0x76, +(byte) 0x12, +(byte) 0x6F, +(byte) 0x13, +(byte) 0x47, +(byte) 0x88, +(byte) 0xD3, +(byte) 0x24, +(byte) 0x79, +(byte) 0x92, +(byte) 0x21, +(byte) 0xC9, +(byte) 0x91, +(byte) 0x14, +(byte) 0x4A, +(byte) 0x4A, +(byte) 0x24, +(byte) 0x6D, +(byte) 0x21, +(byte) 0x55, +(byte) 0x90, +(byte) 0x5A, +(byte) 0x48, +(byte) 0x57, +(byte) 0x48, +(byte) 0x83, +(byte) 0xA4, +(byte) 0xF7, +(byte) 0x64, +(byte) 0x32, +(byte) 0x59, +(byte) 0x87, +(byte) 0x6C, +(byte) 0x47, +(byte) 0x5E, +(byte) 0x4E, +(byte) 0xE6, +(byte) 0x93, +(byte) 0x37, +(byte) 0x93, +(byte) 0x2B, +(byte) 0xC8, +(byte) 0xC7, +(byte) 0xC9, +(byte) 0xD7, +(byte) 0xC8, +(byte) 0x43, +(byte) 0xE4, +(byte) 0xCF, +(byte) 0x14, +(byte) 0x05, +(byte) 0x8A, +(byte) 0x09, +(byte) 0xC5, +(byte) 0x9D, +(byte) 0xB2, +(byte) 0x92, +(byte) 0x22, +(byte) 0xA6, +(byte) 0xEC, +(byte) 0xA2, +(byte) 0x1C, +(byte) 0xA1, +(byte) 0x74, +(byte) 0x51, +(byte) 0x1E, +(byte) 0x53, +(byte) 0xDE, +(byte) 0x53, +(byte) 0xA9, +(byte) 0x54, +(byte) 0x03, +(byte) 0xAA, +(byte) 0x0B, +(byte) 0x35, +(byte) 0x9A, +(byte) 0x2A, +(byte) 0xA2, +(byte) 0xEE, +(byte) 0xA2, +(byte) 0x36, +(byte) 0x52, +(byte) 0x2F, +(byte) 0x51, +(byte) 0x9F, +(byte) 0x51, +(byte) 0x3F, +(byte) 0xC9, +(byte) 0xD0, +(byte) 0x64, +(byte) 0xCC, +(byte) 0x64, +(byte) 0x7C, +(byte) 0x65, +(byte) 0xB8, +(byte) 0x32, +(byte) 0x9B, +(byte) 0x64, +(byte) 0xAA, +(byte) 0x65, +(byte) 0xDA, +(byte) 0x64, +(byte) 0xEE, +(byte) 0xCA, +(byte) 0xBC, +(byte) 0x91, +(byte) 0x25, +(byte) 0xCA, +(byte) 0xEA, +(byte) 0xCB, +(byte) 0xBA, +(byte) 0xCA, +(byte) 0xAE, +(byte) 0x96, +(byte) 0x5D, +(byte) 0x27, +(byte) 0x5B, +(byte) 0x2E, +(byte) 0x7B, +(byte) 0x52, +(byte) 0xF6, +(byte) 0xB6, +(byte) 0xEC, +(byte) 0x6B, +(byte) 0x39, +(byte) 0xA2, +(byte) 0x9C, +(byte) 0x81, +(byte) 0x9C, +(byte) 0xBB, +(byte) 0x1C, +(byte) 0x5B, +(byte) 0x6E, +(byte) 0xA3, +(byte) 0x5C, +(byte) 0xB5, +(byte) 0xDC, +(byte) 0x19, +(byte) 0xB9, +(byte) 0x7E, +(byte) 0xB9, +(byte) 0x49, +(byte) 0x79, +(byte) 0x9A, +(byte) 0xBC, +(byte) 0x85, +(byte) 0x7C, +(byte) 0xA0, +(byte) 0x7C, +(byte) 0x8A, +(byte) 0x7C, +(byte) 0x91, +(byte) 0x7C, +(byte) 0x93, +(byte) 0xFC, +(byte) 0x75, +(byte) 0xF9, +(byte) 0x31, +(byte) 0x05, +(byte) 0xBC, +(byte) 0x82, +(byte) 0x81, +(byte) 0x82, +(byte) 0xA7, +(byte) 0x02, +(byte) 0x57, +(byte) 0x21, +(byte) 0x4F, +(byte) 0xE1, +(byte) 0x90, +(byte) 0xC2, +(byte) 0x25, +(byte) 0x85, +(byte) 0x61, +(byte) 0x1A, +(byte) 0x42, +(byte) 0xD3, +(byte) 0xA5, +(byte) 0xB9, +(byte) 0xD3, +(byte) 0x38, +(byte) 0xB4, +(byte) 0xAD, +(byte) 0xB4, +(byte) 0x06, +(byte) 0xDA, +(byte) 0x15, +(byte) 0xDA, +(byte) 0x08, +(byte) 0x1D, +(byte) 0x47, +(byte) 0x37, +(byte) 0xA4, +(byte) 0xFB, +(byte) 0xD2, +(byte) 0x13, +(byte) 0xE9, +(byte) 0x85, +(byte) 0xF4, +(byte) 0x5F, +(byte) 0xE8, +(byte) 0xBD, +(byte) 0xF4, +(byte) 0x09, +(byte) 0x45, +(byte) 0x05, +(byte) 0xC5, +(byte) 0xC5, +(byte) 0x8A, +(byte) 0xE1, +(byte) 0x8A, +(byte) 0xD9, +(byte) 0x8A, +(byte) 0xD5, +(byte) 0x8A, +(byte) 0xE7, +(byte) 0x14, +(byte) 0x25, +(byte) 0x4A, +(byte) 0x88, +(byte) 0x92, +(byte) 0x81, +(byte) 0x92, +(byte) 0xAF, +(byte) 0x52, +(byte) 0xB2, +(byte) 0x52, +(byte) 0xB1, +(byte) 0xD2, +(byte) 0x09, +(byte) 0xA5, +(byte) 0x87, +(byte) 0x4A, +(byte) 0x5F, +(byte) 0x16, +(byte) 0x68, +(byte) 0x2C, +(byte) 0x70, +(byte) 0x5D, +(byte) 0xC0, +(byte) 0x5B, +(byte) 0xB0, +(byte) 0x73, +(byte) 0x41, +(byte) 0xCB, +(byte) 0x82, +(byte) 0xBB, +(byte) 0x0B, +(byte) 0xA6, +(byte) 0x94, +(byte) 0xD5, +(byte) 0x94, +(byte) 0x5D, +(byte) 0x94, +(byte) 0x79, +(byte) 0xCA, +(byte) 0x05, +(byte) 0xCA, +(byte) 0xAD, +(byte) 0xCA, +(byte) 0x0F, +(byte) 0x94, +(byte) 0xBF, +(byte) 0xA8, +(byte) 0x30, +(byte) 0x54, +(byte) 0x3C, +(byte) 0x55, +(byte) 0x92, +(byte) 0x54, +(byte) 0x76, +(byte) 0xAB, +(byte) 0xB4, +(byte) 0xAB, +(byte) 0x3C, +(byte) 0x55, +(byte) 0xC5, +(byte) 0xA8, +(byte) 0x9A, +(byte) 0xA8, +(byte) 0x2E, +(byte) 0x57, +(byte) 0xCD, +(byte) 0x52, +(byte) 0x3D, +(byte) 0xA0, +(byte) 0x7A, +(byte) 0x45, +(byte) 0xF5, +(byte) 0xB5, +(byte) 0x1A, +(byte) 0x5D, +(byte) 0xCD, +(byte) 0x41, +(byte) 0x8D, +(byte) 0xA3, +(byte) 0x56, +(byte) 0xA0, +(byte) 0x76, +(byte) 0x42, +(byte) 0xED, +(byte) 0x89, +(byte) 0x3A, +(byte) 0xAC, +(byte) 0x6E, +(byte) 0xA2, +(byte) 0x1E, +(byte) 0xAC, +(byte) 0xBE, +(byte) 0x5E, +(byte) 0xFD, +(byte) 0x90, +(byte) 0xFA, +(byte) 0x2D, +(byte) 0xF5, +(byte) 0x49, +(byte) 0x0D, +(byte) 0x4D, +(byte) 0x0D, +(byte) 0x6F, +(byte) 0x8D, +(byte) 0x34, +(byte) 0x8D, +(byte) 0x4A, +(byte) 0x8D, +(byte) 0x4B, +(byte) 0x1A, +(byte) 0xAF, +(byte) 0x35, +(byte) 0x95, +(byte) 0x34, +(byte) 0x5D, +(byte) 0x34, +(byte) 0x13, +(byte) 0x35, +(byte) 0xCB, +(byte) 0x34, +(byte) 0xCF, +(byte) 0x6B, +(byte) 0x8E, +(byte) 0x6B, +(byte) 0xD1, +(byte) 0xB4, +(byte) 0x9C, +(byte) 0xB4, +(byte) 0xF8, +(byte) 0x5A, +(byte) 0x65, +(byte) 0x5A, +(byte) 0x17, +(byte) 0xB4, +(byte) 0x5E, +(byte) 0x32, +(byte) 0x14, +(byte) 0x19, +(byte) 0xAE, +(byte) 0x8C, +(byte) 0x64, +(byte) 0x46, +(byte) 0x05, +(byte) 0xE3, +(byte) 0x32, +(byte) 0x63, +(byte) 0x42, +(byte) 0x5B, +(byte) 0x5D, +(byte) 0xDB, +(byte) 0x47, +(byte) 0x5B, +(byte) 0xAC, +(byte) 0x5D, +(byte) 0xA7, +(byte) 0xDD, +(byte) 0xAB, +(byte) 0x3D, +(byte) 0xAD, +(byte) 0x63, +(byte) 0xA8, +(byte) 0x13, +(byte) 0xA6, +(byte) 0x93, +(byte) 0xAB, +(byte) 0xD3, +(byte) 0xAA, +(byte) 0xF3, +(byte) 0x54, +(byte) 0x97, +(byte) 0xA4, +(byte) 0xCB, +(byte) 0xD2, +(byte) 0x8D, +(byte) 0xD3, +(byte) 0x2D, +(byte) 0xD3, +(byte) 0xED, +(byte) 0xD6, +(byte) 0x9D, +(byte) 0xD0, +(byte) 0xD3, +(byte) 0xD2, +(byte) 0x0B, +(byte) 0xD0, +(byte) 0xCB, +(byte) 0xD1, +(byte) 0x6B, +(byte) 0xD6, +(byte) 0x7B, +(byte) 0xA2, +(byte) 0x4F, +(byte) 0xD4, +(byte) 0x67, +(byte) 0xE9, +(byte) 0x27, +(byte) 0xE8, +(byte) 0xEF, +(byte) 0xD3, +(byte) 0xEF, +(byte) 0xD1, +(byte) 0x9F, +(byte) 0x32, +(byte) 0x30, +(byte) 0x34, +(byte) 0x88, +(byte) 0x30, +(byte) 0xD8, +(byte) 0x6E, +(byte) 0xD0, +(byte) 0x6E, +(byte) 0x30, +(byte) 0x66, +(byte) 0xA8, +(byte) 0x6C, +(byte) 0xE8, +(byte) 0x6B, +(byte) 0xB8, +(byte) 0xCE, +(byte) 0xB0, +(byte) 0xD9, +(byte) 0x70, +(byte) 0xD0, +(byte) 0x88, +(byte) 0x6A, +(byte) 0xE4, +(byte) 0x6C, +(byte) 0x94, +(byte) 0x6E, +(byte) 0x54, +(byte) 0x6F, +(byte) 0x74, +(byte) 0xDF, +(byte) 0x18, +(byte) 0x67, +(byte) 0xCC, +(byte) 0x32, +(byte) 0x4E, +(byte) 0x32, +(byte) 0xDE, +(byte) 0x6F, +(byte) 0x7C, +(byte) 0xC7, +(byte) 0x04, +(byte) 0x36, +(byte) 0xB1, +(byte) 0x36, +(byte) 0x49, +(byte) 0x30, +(byte) 0xA9, +(byte) 0x36, +(byte) 0xB9, +(byte) 0x6D, +(byte) 0x0A, +(byte) 0x9B, +(byte) 0xDA, +(byte) 0x98, +(byte) 0xF2, +(byte) 0x4D, +(byte) 0xF7, +(byte) 0x9B, +(byte) 0xF6, +(byte) 0x2D, +(byte) 0xC4, +(byte) 0x2E, +(byte) 0xB4, +(byte) 0x5B, +(byte) 0x28, +(byte) 0x58, +(byte) 0x58, +(byte) 0xBF, +(byte) 0xB0, +(byte) 0x9F, +(byte) 0x49, +(byte) 0x61, +(byte) 0xBA, +(byte) 0x32, +(byte) 0x33, +(byte) 0x99, +(byte) 0xCD, +(byte) 0xCC, +(byte) 0x21, +(byte) 0x33, +(byte) 0x25, +(byte) 0xB3, +(byte) 0xA5, +(byte) 0x66, +(byte) 0xB9, +(byte) 0x66, +(byte) 0xED, +(byte) 0x66, +(byte) 0x6F, +(byte) 0x16, +(byte) 0xE9, +(byte) 0x2D, +(byte) 0x8A, +(byte) 0x5E, +(byte) 0xB4, +(byte) 0x7B, +(byte) 0x51, +(byte) 0xCF, +(byte) 0xA2, +(byte) 0xEF, +(byte) 0xE6, +(byte) 0xD6, +(byte) 0xE6, +(byte) 0xC9, +(byte) 0xE6, +(byte) 0x0D, +(byte) 0xE6, +(byte) 0x03, +(byte) 0x16, +(byte) 0x0A, +(byte) 0x16, +(byte) 0x7E, +(byte) 0x16, +(byte) 0xB9, +(byte) 0x16, +(byte) 0x9D, +(byte) 0x16, +(byte) 0xEF, +(byte) 0x2C, +(byte) 0x4D, +(byte) 0x2C, +(byte) 0x39, +(byte) 0x96, +(byte) 0xD5, +(byte) 0x96, +(byte) 0xF7, +(byte) 0xAD, +(byte) 0xA8, +(byte) 0x56, +(byte) 0x5E, +(byte) 0x56, +(byte) 0x9B, +(byte) 0xAC, +(byte) 0x3A, +(byte) 0xAC, +(byte) 0xDE, +(byte) 0x2E, +(byte) 0x36, +(byte) 0x5D, +(byte) 0xCC, +(byte) 0x5B, +(byte) 0x7C, +(byte) 0x60, +(byte) 0xF1, +(byte) 0x23, +(byte) 0x6B, +(byte) 0x9A, +(byte) 0x75, +(byte) 0x80, +(byte) 0xF5, +(byte) 0x76, +(byte) 0xEB, +(byte) 0x6E, +(byte) 0xEB, +(byte) 0x6F, +(byte) 0x36, +(byte) 0xB6, +(byte) 0x36, +(byte) 0x42, +(byte) 0x9B, +(byte) 0x16, +(byte) 0x9B, +(byte) 0x71, +(byte) 0x5B, +(byte) 0x3D, +(byte) 0xDB, +(byte) 0x18, +(byte) 0xDB, +(byte) 0x1A, +(byte) 0xDB, +(byte) 0x7E, +(byte) 0x16, +(byte) 0x9D, +(byte) 0x15, +(byte) 0xC4, +(byte) 0x2A, +(byte) 0x62, +(byte) 0x5D, +(byte) 0xB3, +(byte) 0xC3, +(byte) 0xDA, +(byte) 0xB9, +(byte) 0xD9, +(byte) 0x6D, +(byte) 0xB2, +(byte) 0x3B, +(byte) 0x6B, +(byte) 0xF7, +(byte) 0xD9, +(byte) 0xDE, +(byte) 0xC6, +(byte) 0x5E, +(byte) 0x64, +(byte) 0x7F, +(byte) 0xC2, +(byte) 0xFE, +(byte) 0x6F, +(byte) 0x07, +(byte) 0xA6, +(byte) 0x43, +(byte) 0x92, +(byte) 0x43, +(byte) 0x93, +(byte) 0xC3, +(byte) 0xD8, +(byte) 0x12, +(byte) 0xC3, +(byte) 0x25, +(byte) 0xBC, +(byte) 0x25, +(byte) 0x0D, +(byte) 0x4B, +(byte) 0x86, +(byte) 0x1D, +(byte) 0x75, +(byte) 0x1C, +(byte) 0xD9, +(byte) 0x8E, +(byte) 0x75, +(byte) 0x8E, +(byte) 0x12, +(byte) 0x27, +(byte) 0x86, +(byte) 0x53, +(byte) 0x8C, +(byte) 0xD3, +(byte) 0x41, +(byte) 0x27, +(byte) 0x89, +(byte) 0xB3, +(byte) 0xB6, +(byte) 0x33, +(byte) 0xDB, +(byte) 0xB9, +(byte) 0xDE, +(byte) 0xF9, +(byte) 0xB9, +(byte) 0x8B, +(byte) 0xAE, +(byte) 0x0B, +(byte) 0xD7, +(byte) 0xE5, +(byte) 0xB0, +(byte) 0xCB, +(byte) 0xA8, +(byte) 0xAB, +(byte) 0xB1, +(byte) 0x6B, +(byte) 0xA2, +(byte) 0xEB, +(byte) 0x31, +(byte) 0xD7, +(byte) 0x37, +(byte) 0x6E, +(byte) 0xE6, +(byte) 0x6E, +(byte) 0x42, +(byte) 0xB7, +(byte) 0xD3, +(byte) 0x6E, +(byte) 0x53, +(byte) 0xEE, +(byte) 0xF6, +(byte) 0xEE, +(byte) 0x1B, +(byte) 0xDC, +(byte) 0xBB, +(byte) 0x3C, +(byte) 0x10, +(byte) 0x0F, +(byte) 0x6F, +(byte) 0x8F, +(byte) 0x02, +(byte) 0x8F, +(byte) 0x5E, +(byte) 0x4F, +(byte) 0x05, +(byte) 0xCF, +(byte) 0x30, +(byte) 0xCF, +(byte) 0x2A, +(byte) 0xCF, +(byte) 0x67, +(byte) 0x5E, +(byte) 0x3A, +(byte) 0x5E, +(byte) 0xF1, +(byte) 0x5E, +(byte) 0xCD, +(byte) 0x5E, +(byte) 0x13, +(byte) 0xDE, +(byte) 0xD6, +(byte) 0xDE, +(byte) 0xEB, +(byte) 0xBD, +(byte) 0xBB, +(byte) 0x7C, +(byte) 0xB0, +(byte) 0x3E, +(byte) 0xFE, +(byte) 0x3E, +(byte) 0xBB, +(byte) 0x7D, +(byte) 0xFA, +(byte) 0x7D, +(byte) 0x35, +(byte) 0x7C, +(byte) 0x39, +(byte) 0xBE, +(byte) 0x8D, +(byte) 0xBE, +(byte) 0x13, +(byte) 0x7E, +(byte) 0xB6, +(byte) 0x7E, +(byte) 0x1B, +(byte) 0xFC, +(byte) 0x2E, +(byte) 0xFB, +(byte) 0x53, +(byte) 0xFC, +(byte) 0x43, +(byte) 0xFC, +(byte) 0xAB, +(byte) 0xFC, +(byte) 0x9F, +(byte) 0x2F, +(byte) 0x35, +(byte) 0x59, +(byte) 0x2A, +(byte) 0x5C, +(byte) 0xDA, +(byte) 0x19, +(byte) 0x00, +(byte) 0x07, +(byte) 0xF8, +(byte) 0x05, +(byte) 0xEC, +(byte) 0x09, +(byte) 0x18, +(byte) 0x5C, +(byte) 0xA6, +(byte) 0xBF, +(byte) 0x4C, +(byte) 0xB0, +(byte) 0xAC, +(byte) 0x3D, +(byte) 0x10, +(byte) 0x04, +(byte) 0xFA, +(byte) 0x06, +(byte) 0xEE, +(byte) 0x09, +(byte) 0x7C, +(byte) 0x1A, +(byte) 0x64, +(byte) 0x18, +(byte) 0x94, +(byte) 0x1E, +(byte) 0xF4, +(byte) 0xDB, +(byte) 0x72, +(byte) 0xDC, +(byte) 0xF2, +(byte) 0xA0, +(byte) 0xE5, +(byte) 0xD5, +(byte) 0xCB, +(byte) 0x5F, +(byte) 0x04, +(byte) 0x5B, +(byte) 0x04, +(byte) 0xE7, +(byte) 0x04, +(byte) 0xF7, +(byte) 0x84, +(byte) 0xD0, +(byte) 0x42, +(byte) 0xD6, +(byte) 0x84, +(byte) 0x34, +(byte) 0x85, +(byte) 0x7C, +(byte) 0x0C, +(byte) 0x75, +(byte) 0x0B, +(byte) 0x2D, +(byte) 0x0E, +(byte) 0x1D, +(byte) 0x08, +(byte) 0x33, +(byte) 0x0A, +(byte) 0x13, +(byte) 0x87, +(byte) 0x75, +(byte) 0x87, +(byte) 0xCB, +(byte) 0x86, +(byte) 0xAF, +(byte) 0x0C, +(byte) 0x6F, +(byte) 0x0C, +(byte) 0x9F, +(byte) 0x8A, +(byte) 0xF0, +(byte) 0x88, +(byte) 0x28, +(byte) 0x8D, +(byte) 0x90, +(byte) 0x44, +(byte) 0x2E, +(byte) 0x8A, +(byte) 0xDC, +(byte) 0x10, +(byte) 0x79, +(byte) 0x33, +(byte) 0x4A, +(byte) 0x35, +(byte) 0x8A, +(byte) 0x1F, +(byte) 0xD5, +(byte) 0x11, +(byte) 0x8D, +(byte) 0x8F, +(byte) 0x0E, +(byte) 0x8F, +(byte) 0x3E, +(byte) 0x1C, +(byte) 0x3D, +(byte) 0xB9, +(byte) 0xC2, +(byte) 0x73, +(byte) 0xC5, +(byte) 0xDE, +(byte) 0x15, +(byte) 0x23, +(byte) 0x2B, +(byte) 0xAD, +(byte) 0x57, +(byte) 0xE6, +(byte) 0xAF, +(byte) 0x7C, +(byte) 0xB8, +(byte) 0xCA, +(byte) 0x70, +(byte) 0x55, +(byte) 0xF6, +(byte) 0xAA, +(byte) 0xEB, +(byte) 0xAB, +(byte) 0x55, +(byte) 0x57, +(byte) 0x27, +(byte) 0xAF, +(byte) 0x3E, +(byte) 0xB7, +(byte) 0x46, +(byte) 0x76, +(byte) 0x0D, +(byte) 0x7B, +(byte) 0xCD, +(byte) 0xC9, +(byte) 0x18, +(byte) 0x6C, +(byte) 0x4C, +(byte) 0x44, +(byte) 0x4C, +(byte) 0x53, +(byte) 0xCC, +(byte) 0x57, +(byte) 0x76, +(byte) 0x20, +(byte) 0xBB, +(byte) 0x9E, +(byte) 0x3D, +(byte) 0x19, +(byte) 0xEB, +(byte) 0x1B, +(byte) 0x5B, +(byte) 0x13, +(byte) 0x3B, +(byte) 0xC1, +(byte) 0x71, +(byte) 0xE7, +(byte) 0xEC, +(byte) 0xE3, +(byte) 0xBC, +(byte) 0xE2, +(byte) 0xBA, +(byte) 0x70, +(byte) 0xCB, +(byte) 0xB8, +(byte) 0xE3, +(byte) 0x3C, +(byte) 0x47, +(byte) 0x5E, +(byte) 0x29, +(byte) 0x6F, +(byte) 0x34, +(byte) 0xCE, +(byte) 0x31, +(byte) 0xAE, +(byte) 0x34, +(byte) 0x6E, +(byte) 0x2C, +(byte) 0xDE, +(byte) 0x31, +(byte) 0x7E, +(byte) 0x4F, +(byte) 0xFC, +(byte) 0x78, +(byte) 0x82, +(byte) 0x73, +(byte) 0x42, +(byte) 0x79, +(byte) 0xC2, +(byte) 0x6B, +(byte) 0xBE, +(byte) 0x3B, +(byte) 0xBF, +(byte) 0x8A, +(byte) 0xFF, +(byte) 0x36, +(byte) 0xD1, +(byte) 0x27, +(byte) 0xB1, +(byte) 0x36, +(byte) 0x71, +(byte) 0x2A, +(byte) 0x29, +(byte) 0x30, +(byte) 0xE9, +(byte) 0x48, +(byte) 0xD2, +(byte) 0x4C, +(byte) 0x72, +(byte) 0x44, +(byte) 0x72, +(byte) 0x6B, +(byte) 0x0A, +(byte) 0x21, +(byte) 0x25, +(byte) 0x26, +(byte) 0xE5, +(byte) 0x8C, +(byte) 0x40, +(byte) 0x41, +(byte) 0x90, +(byte) 0x24, +(byte) 0xB8, +(byte) 0x9C, +(byte) 0xAA, +(byte) 0x99, +(byte) 0x9A, +(byte) 0x9D, +(byte) 0xDA, +(byte) 0x97, +(byte) 0x66, +(byte) 0x9A, +(byte) 0x96, +(byte) 0x9F, +(byte) 0x26, +(byte) 0x49, +(byte) 0xB7, +(byte) 0x4F, +(byte) 0xDF, +(byte) 0x9B, +(byte) 0x3E, +(byte) 0x21, +(byte) 0xF4, +(byte) 0x17, +(byte) 0x1E, +(byte) 0xCE, +(byte) 0x80, +(byte) 0x32, +(byte) 0x56, +(byte) 0x65, +(byte) 0x74, +(byte) 0x88, +(byte) 0xE8, +(byte) 0xE8, +(byte) 0x0F, +(byte) 0xE6, +(byte) 0x96, +(byte) 0xD8, +(byte) 0x48, +(byte) 0xBC, +(byte) 0x4D, +(byte) 0x3C, +(byte) 0x94, +(byte) 0xE9, +(byte) 0x94, +(byte) 0x59, +(byte) 0x9D, +(byte) 0xF9, +(byte) 0x29, +(byte) 0x2B, +(byte) 0x3C, +(byte) 0xEB, +(byte) 0x64, +(byte) 0xB6, +(byte) 0x7C, +(byte) 0xB6, +(byte) 0x20, +(byte) 0xFB, +(byte) 0xD6, +(byte) 0x5A, +(byte) 0x93, +(byte) 0xB5, +(byte) 0x3B, +(byte) 0xD7, +(byte) 0x8E, +(byte) 0xAE, +(byte) 0xF3, +(byte) 0x5A, +(byte) 0xF7, +(byte) 0xF3, +(byte) 0x7A, +(byte) 0xCC, +(byte) 0x7A, +(byte) 0xCE, +(byte) 0xFA, +(byte) 0xEE, +(byte) 0x1C, +(byte) 0xED, +(byte) 0x9C, +(byte) 0x2D, +(byte) 0x39, +(byte) 0x43, +(byte) 0x1B, +(byte) 0x5C, +(byte) 0x37, +(byte) 0xD4, +(byte) 0x6D, +(byte) 0x84, +(byte) 0x36, +(byte) 0xC6, +(byte) 0x6E, +(byte) 0xEC, +(byte) 0xDE, +(byte) 0xA4, +(byte) 0xBB, +(byte) 0x29, +(byte) 0x6F, +(byte) 0xD3, +(byte) 0xC8, +(byte) 0x66, +(byte) 0xEF, +(byte) 0xCD, +(byte) 0x47, +(byte) 0xB7, +(byte) 0x90, +(byte) 0xB6, +(byte) 0x24, +(byte) 0x6D, +(byte) 0xF9, +(byte) 0x3D, +(byte) 0xD7, +(byte) 0x3C, +(byte) 0xB7, +(byte) 0x34, +(byte) 0xF7, +(byte) 0xC3, +(byte) 0xD6, +(byte) 0x88, +(byte) 0xAD, +(byte) 0x9D, +(byte) 0x79, +(byte) 0x1A, +(byte) 0x79, +(byte) 0x9B, +(byte) 0xF3, +(byte) 0x86, +(byte) 0xB7, +(byte) 0x79, +(byte) 0x6F, +(byte) 0x6B, +(byte) 0xCE, +(byte) 0x97, +(byte) 0xC9, +(byte) 0x17, +(byte) 0xE6, +(byte) 0xF7, +(byte) 0x6F, +(byte) 0x77, +(byte) 0xD8, +(byte) 0x5E, +(byte) 0xBB, +(byte) 0x03, +(byte) 0xB3, +(byte) 0x83, +(byte) 0xBF, +(byte) 0xA3, +(byte) 0x77, +(byte) 0xA7, +(byte) 0xD5, +(byte) 0xCE, +(byte) 0xCA, +(byte) 0x9D, +(byte) 0xDF, +(byte) 0x0B, +(byte) 0xB8, +(byte) 0x05, +(byte) 0x37, +(byte) 0x0A, +(byte) 0xCD, +(byte) 0x0B, +(byte) 0xCB, +(byte) 0x0B, +(byte) 0xBF, +(byte) 0x16, +(byte) 0x71, +(byte) 0x8A, +(byte) 0x6E, +(byte) 0xFC, +(byte) 0x64, +(byte) 0xF1, +(byte) 0x53, +(byte) 0xC5, +(byte) 0x4F, +(byte) 0x33, +(byte) 0xBB, +(byte) 0xE2, +(byte) 0x76, +(byte) 0xF5, +(byte) 0x16, +(byte) 0xDB, +(byte) 0x14, +(byte) 0x1F, +(byte) 0x28, +(byte) 0xC1, +(byte) 0x95, +(byte) 0x08, +(byte) 0x4A, +(byte) 0x1E, +(byte) 0xEE, +(byte) 0x76, +(byte) 0xDE, +(byte) 0x7D, +(byte) 0xB4, +(byte) 0x54, +(byte) 0xBE, +(byte) 0x74, +(byte) 0x5D, +(byte) 0xE9, +(byte) 0xF0, +(byte) 0x9E, +(byte) 0x80, +(byte) 0x3D, +(byte) 0x6D, +(byte) 0x65, +(byte) 0x8C, +(byte) 0xB2, +(byte) 0x82, +(byte) 0xB2, +(byte) 0x0F, +(byte) 0x7B, +(byte) 0xD7, +(byte) 0xEC, +(byte) 0xBD, +(byte) 0x5E, +(byte) 0xBE, +(byte) 0xB8, +(byte) 0xBC, +(byte) 0x76, +(byte) 0x1F, +(byte) 0x69, +(byte) 0x9F, +(byte) 0x78, +(byte) 0x9F, +(byte) 0xA4, +(byte) 0x62, +(byte) 0x69, +(byte) 0x45, +(byte) 0x47, +(byte) 0xA5, +(byte) 0x5E, +(byte) 0x65, +(byte) 0x49, +(byte) 0xE5, +(byte) 0xD7, +(byte) 0xAA, +(byte) 0x84, +(byte) 0xAA, +(byte) 0x07, +(byte) 0xD5, +(byte) 0x6E, +(byte) 0xD5, +(byte) 0xAD, +(byte) 0x35, +(byte) 0xEA, +(byte) 0x35, +(byte) 0x3B, +(byte) 0x6B, +(byte) 0xA6, +(byte) 0xF6, +(byte) 0x73, +(byte) 0xF7, +(byte) 0xDF, +(byte) 0x3D, +(byte) 0xE0, +(byte) 0x72, +(byte) 0xA0, +(byte) 0xA5, +(byte) 0x56, +(byte) 0xA3, +(byte) 0xB6, +(byte) 0xB0, +(byte) 0xF6, +(byte) 0xCB, +(byte) 0x41, +(byte) 0xFE, +(byte) 0xC1, +(byte) 0x47, +(byte) 0x75, +(byte) 0xDE, +(byte) 0x75, +(byte) 0x6D, +(byte) 0xF5, +(byte) 0x06, +(byte) 0xF5, +(byte) 0xE5, +(byte) 0x87, +(byte) 0x70, +(byte) 0x87, +(byte) 0x32, +(byte) 0x0F, +(byte) 0xBD, +(byte) 0x68, +(byte) 0x08, +(byte) 0x6F, +(byte) 0xE8, +(byte) 0xF9, +(byte) 0x99, +(byte) 0xF5, +(byte) 0x73, +(byte) 0xE3, +(byte) 0x61, +(byte) 0xD5, +(byte) 0xC3, +(byte) 0x85, +(byte) 0x87, +(byte) 0xBF, +(byte) 0x1D, +(byte) 0x11, +(byte) 0x1C, +(byte) 0x91, +(byte) 0x1C, +(byte) 0x0D, +(byte) 0x3E, +(byte) 0x7A, +(byte) 0xB9, +(byte) 0xD1, +(byte) 0xB6, +(byte) 0xB1, +(byte) 0xB1, +(byte) 0x49, +(byte) 0xBD, +(byte) 0xA9, +(byte) 0xB8, +(byte) 0x19, +(byte) 0x6E, +(byte) 0x16, +(byte) 0x37, +(byte) 0x8F, +(byte) 0x1F, +(byte) 0x5B, +(byte) 0x79, +(byte) 0xEC, +(byte) 0xCE, +(byte) 0x2F, +(byte) 0x1E, +(byte) 0xBF, +(byte) 0x74, +(byte) 0xB4, +(byte) 0x30, +(byte) 0x5B, +(byte) 0xEA, +(byte) 0x5A, +(byte) 0x95, +(byte) 0x5A, +(byte) 0x0B, +(byte) 0x8F, +(byte) 0x83, +(byte) 0xE3, +(byte) 0xE2, +(byte) 0xE3, +(byte) 0x2F, +(byte) 0x7F, +(byte) 0x8D, +(byte) 0xF9, +(byte) 0xF5, +(byte) 0xE1, +(byte) 0x09, +(byte) 0xFF, +(byte) 0x13, +(byte) 0xDD, +(byte) 0x27, +(byte) 0x59, +(byte) 0x27, +(byte) 0x5B, +(byte) 0x4E, +(byte) 0xE9, +(byte) 0x9F, +(byte) 0xAA, +(byte) 0x39, +(byte) 0x4D, +(byte) 0x3B, +(byte) 0x5D, +(byte) 0xD0, +(byte) 0x06, +(byte) 0xB5, +(byte) 0xAD, +(byte) 0x6D, +(byte) 0x9B, +(byte) 0x68, +(byte) 0x4F, +(byte) 0x68, +(byte) 0x97, +(byte) 0x74, +(byte) 0x44, +(byte) 0x75, +(byte) 0xF4, +(byte) 0x9D, +(byte) 0xF1, +(byte) 0x3B, +(byte) 0xD3, +(byte) 0xDD, +(byte) 0xE9, +(byte) 0xD0, +(byte) 0x79, +(byte) 0xFA, +(byte) 0x37, +(byte) 0xB3, +(byte) 0xDF, +(byte) 0x8E, +(byte) 0x9C, +(byte) 0xD5, +(byte) 0x3E, +(byte) 0x5B, +(byte) 0x7D, +(byte) 0x4E, +(byte) 0xF1, +(byte) 0x5C, +(byte) 0xF1, +(byte) 0x79, +(byte) 0xD2, +(byte) 0xF9, +(byte) 0xBC, +(byte) 0xF3, +(byte) 0x33, +(byte) 0x17, +(byte) 0xD6, +(byte) 0x5D, +(byte) 0x98, +(byte) 0xEC, +(byte) 0x4A, +(byte) 0xEB, +(byte) 0x7A, +(byte) 0x7D, +(byte) 0x31, +(byte) 0xFE, +(byte) 0xE2, +(byte) 0x70, +(byte) 0xF7, +(byte) 0x9A, +(byte) 0xEE, +(byte) 0x81, +(byte) 0x4B, +(byte) 0x91, +(byte) 0x97, +(byte) 0xEE, +(byte) 0x5F, +(byte) 0x5E, +(byte) 0x7E, +(byte) 0xB9, +(byte) 0xF7, +(byte) 0x8A, +(byte) 0xFF, +(byte) 0x95, +(byte) 0x6B, +(byte) 0x57, +(byte) 0xBD, +(byte) 0xAE, +(byte) 0x5E, +(byte) 0xEA, +(byte) 0x71, +(byte) 0xED, +(byte) 0xB9, +(byte) 0x70, +(byte) 0xCD, +(byte) 0xF1, +(byte) 0xDA, +(byte) 0xD9, +(byte) 0xEB, +(byte) 0xF6, +(byte) 0xD7, +(byte) 0xCF, +(byte) 0xDC, +(byte) 0x60, +(byte) 0xDD, +(byte) 0x68, +(byte) 0xBF, +(byte) 0x69, +(byte) 0x73, +(byte) 0xB3, +(byte) 0xED, +(byte) 0x96, +(byte) 0xF5, +(byte) 0xAD, +(byte) 0xD3, +(byte) 0xBF, +(byte) 0x5B, +(byte) 0xFF, +(byte) 0x7E, +(byte) 0xBA, +(byte) 0xD7, +(byte) 0xA6, +(byte) 0xB7, +(byte) 0xED, +(byte) 0xB6, +(byte) 0xED, +(byte) 0xED, +(byte) 0x8E, +(byte) 0x3B, +(byte) 0x76, +(byte) 0x77, +(byte) 0x3A, +(byte) 0xFB, +(byte) 0x96, +(byte) 0xF4, +(byte) 0x9D, +(byte) 0xBF, +(byte) 0xEB, +(byte) 0x7C, +(byte) 0xF7, +(byte) 0xE2, +(byte) 0x3D, +(byte) 0x8F, +(byte) 0x7B, +(byte) 0x57, +(byte) 0xEF, +(byte) 0xFB, +(byte) 0xDE, +(byte) 0xBF, +(byte) 0xF9, +(byte) 0x60, +(byte) 0xD9, +(byte) 0x83, +(byte) 0xBE, +(byte) 0x87, +(byte) 0x61, +(byte) 0x0F, +(byte) 0x1F, +(byte) 0xF5, +(byte) 0xAF, +(byte) 0xEC, +(byte) 0x97, +(byte) 0x3C, +(byte) 0xE2, +(byte) 0x3E, +(byte) 0x1A, +(byte) 0x7B, +(byte) 0x9C, +(byte) 0xFC, +(byte) 0xF8, +(byte) 0xED, +(byte) 0x93, +(byte) 0xCC, +(byte) 0x27, +(byte) 0xD3, +(byte) 0x03, +(byte) 0x9B, +(byte) 0x07, +(byte) 0xB1, +(byte) 0x83, +(byte) 0x05, +(byte) 0x4F, +(byte) 0xE5, +(byte) 0x9E, +(byte) 0x96, +(byte) 0x3F, +(byte) 0x53, +(byte) 0x7F, +(byte) 0x56, +(byte) 0xFF, +(byte) 0x87, +(byte) 0xF1, +(byte) 0x1F, +(byte) 0xAD, +(byte) 0x12, +(byte) 0x1B, +(byte) 0xC9, +(byte) 0xB9, +(byte) 0x21, +(byte) 0x8F, +(byte) 0xA1, +(byte) 0x5B, +(byte) 0xCF, +(byte) 0x43, +(byte) 0x9E, +(byte) 0x0F, +(byte) 0x0C, +(byte) 0x73, +(byte) 0x86, +(byte) 0x5F, +(byte) 0xFD, +(byte) 0x99, +(byte) 0xF1, +(byte) 0xE7, +(byte) 0xD7, +(byte) 0x91, +(byte) 0xBC, +(byte) 0x17, +(byte) 0xD4, +(byte) 0x17, +(byte) 0xE5, +(byte) 0xA3, +(byte) 0x5A, +(byte) 0xA3, +(byte) 0x8D, +(byte) 0x63, +(byte) 0x96, +(byte) 0x63, +(byte) 0x67, +(byte) 0xC7, +(byte) 0xBD, +(byte) 0xC6, +(byte) 0xEF, +(byte) 0xBC, +(byte) 0x5C, +(byte) 0xF1, +(byte) 0x72, +(byte) 0xE4, +(byte) 0x55, +(byte) 0xDA, +(byte) 0xAB, +(byte) 0xE9, +(byte) 0xD7, +(byte) 0xF9, +(byte) 0x7F, +(byte) 0xC9, +(byte) 0xFF, +(byte) 0x55, +(byte) 0xF3, +(byte) 0xC6, +(byte) 0xE8, +(byte) 0xCD, +(byte) 0xA9, +(byte) 0xBF, +(byte) 0x5D, +(byte) 0xFE, +(byte) 0xBE, +(byte) 0x35, +(byte) 0x11, +(byte) 0x39, +(byte) 0x31, +(byte) 0xF2, +(byte) 0x56, +(byte) 0xF8, +(byte) 0x76, +(byte) 0xE6, +(byte) 0x5D, +(byte) 0xD1, +(byte) 0x7B, +(byte) 0x95, +(byte) 0xF7, +(byte) 0x47, +(byte) 0x3E, +(byte) 0x2C, +(byte) 0xFE, +(byte) 0xD0, +(byte) 0x3D, +(byte) 0x19, +(byte) 0x34, +(byte) 0xF9, +(byte) 0xEC, +(byte) 0x63, +(byte) 0xCA, +(byte) 0xC7, +(byte) 0xE9, +(byte) 0xA9, +(byte) 0x82, +(byte) 0x4F, +(byte) 0x2A, +(byte) 0x9F, +(byte) 0x8E, +(byte) 0x7E, +(byte) 0x66, +(byte) 0x7D, +(byte) 0xEE, +(byte) 0xF9, +(byte) 0x12, +(byte) 0xF1, +(byte) 0x65, +(byte) 0x74, +(byte) 0x3A, +(byte) 0xEB, +(byte) 0x2B, +(byte) 0xFE, +(byte) 0x6B, +(byte) 0xC5, +(byte) 0x37, +(byte) 0xE3, +(byte) 0x6F, +(byte) 0x9D, +(byte) 0xDF, +(byte) 0xFD, +(byte) 0xBF, +(byte) 0x0F, +(byte) 0xCE, +(byte) 0xA4, +(byte) 0xCC, +(byte) 0xCC, +(byte) 0xFC, +(byte) 0xE0, +(byte) 0x4D, +(byte) 0xCC, +(byte) 0x50, +(byte) 0x5B, +(byte) 0xC2, +(byte) 0x98, +(byte) 0xF7, +(byte) 0x25, +(byte) 0x1E, +(byte) 0xBC, +(byte) 0x38, +(byte) 0xB6, +(byte) 0x38, +(byte) 0x59, +(byte) 0xC4, +(byte) 0x90, +(byte) 0x1A, +(byte) 0x16, +(byte) 0xF7, +(byte) 0xD4, +(byte) 0xE4, +(byte) 0x54, +(byte) 0xB1, +(byte) 0x90, +(byte) 0x11, +(byte) 0x92, +(byte) 0xC6, +(byte) 0xE6, +(byte) 0xF0, +(byte) 0x18, +(byte) 0x4C, +(byte) 0x86, +(byte) 0xD4, +(byte) 0xC4, +(byte) 0xFC, +(byte) 0xDF, +(byte) 0x7C, +(byte) 0x4A, +(byte) 0x6C, +(byte) 0x25, +(byte) 0x00, +(byte) 0xED, +(byte) 0xDB, +(byte) 0x00, +(byte) 0x50, +(byte) 0x7E, +(byte) 0x32, +(byte) 0xAF, +(byte) 0xA1, +(byte) 0x08, +(byte) 0x9A, +(byte) 0x7B, +(byte) 0xCC, +(byte) 0xF9, +(byte) 0xB6, +(byte) 0x59, +(byte) 0x40, +(byte) 0xE0, +(byte) 0x9F, +(byte) 0x01, +(byte) 0xCF, +(byte) 0xE7, +(byte) 0x21, +(byte) 0x4A, +(byte) 0xE8, +(byte) 0xB2, +(byte) 0x42, +(byte) 0xA5, +(byte) 0x86, +(byte) 0x79, +(byte) 0x2D, +(byte) 0xB5, +(byte) 0x1E, +(byte) 0x00, +(byte) 0xD6, +(byte) 0x24, +(byte) 0xAA, +(byte) 0x97, +(byte) 0x64, +(byte) 0xF0, +(byte) 0xE3, +(byte) 0x67, +(byte) 0x35, +(byte) 0xF7, +(byte) 0xE0, +(byte) 0x50, +(byte) 0xC6, +(byte) 0x0F, +(byte) 0x73, +(byte) 0x60, +(byte) 0x06, +(byte) 0xF3, +(byte) 0xE2, +(byte) 0x78, +(byte) 0x42, +(byte) 0x9E, +(byte) 0x00, +(byte) 0xBD, +(byte) 0x6A, +(byte) 0x38, +(byte) 0x9F, +(byte) 0x97, +(byte) 0xC5, +(byte) 0x17, +(byte) 0xC4, +(byte) 0xA3, +(byte) 0xF7, +(byte) 0x17, +(byte) 0x70, +(byte) 0xF9, +(byte) 0x22, +(byte) 0x7E, +(byte) 0xAA, +(byte) 0x80, +(byte) 0xC1, +(byte) 0x17, +(byte) 0x30, +(byte) 0xFE, +(byte) 0x6B, +(byte) 0x4C, +(byte) 0xFF, +(byte) 0xCA, +(byte) 0xE5, +(byte) 0x7F, +(byte) 0xC0, +(byte) 0x7C, +(byte) 0x9F, +(byte) 0xF3, +(byte) 0x9E, +(byte) 0x59, +(byte) 0xC4, +(byte) 0xCB, +(byte) 0x16, +(byte) 0xCD, +(byte) 0xF6, +(byte) 0x99, +(byte) 0x9A, +(byte) 0xB6, +(byte) 0x56, +(byte) 0xC8, +(byte) 0x8F, +(byte) 0x4F, +(byte) 0x10, +(byte) 0x31, +(byte) 0x7C, +(byte) 0x05, +(byte) 0x22, +(byte) 0x9E, +(byte) 0x50, +(byte) 0xC0, +(byte) 0x96, +(byte) 0x76, +(byte) 0xC4, +(byte) 0x4E, +(byte) 0x9E, +(byte) 0xFD, +(byte) 0x3A, +(byte) 0x42, +(byte) 0x69, +(byte) 0x8F, +(byte) 0x19, +(byte) 0xA9, +(byte) 0x42, +(byte) 0x11, +(byte) 0x5F, +(byte) 0x9C, +(byte) 0xB2, +(byte) 0x90, +(byte) 0x61, +(byte) 0x69, +(byte) 0x6E, +(byte) 0x6E, +(byte) 0x07, +(byte) 0x40, +(byte) 0x46, +(byte) 0x9C, +(byte) 0x95, +(byte) 0xE5, +(byte) 0x6C, +(byte) 0x29, +(byte) 0x88, +(byte) 0x82, +(byte) 0x7A, +(byte) 0x67, +(byte) 0xEC, +(byte) 0x1F, +(byte) 0x33, +(byte) 0x33, +(byte) 0xEF, +(byte) 0x0D, +(byte) 0x00, +(byte) 0xC0, +(byte) 0x97, +(byte) 0x01, +(byte) 0xF0, +(byte) 0xAD, +(byte) 0x78, +(byte) 0x66, +(byte) 0x66, +(byte) 0xBA, +(byte) 0x6E, +(byte) 0x66, +(byte) 0xE6, +(byte) 0x1B, +(byte) 0x3A, +(byte) 0x0B, +(byte) 0x64, +(byte) 0x00, +(byte) 0x80, +(byte) 0x2E, +(byte) 0xF1, +(byte) 0x7F, +(byte) 0x00, +(byte) 0x0A, +(byte) 0x3F, +(byte) 0xD9, +(byte) 0xF6, + }; +} diff --git a/PDFJet/src/main/java/com/pdfjet/Image.java b/PDFJet/src/main/java/com/pdfjet/Image.java new file mode 100644 index 0000000..49e733b --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Image.java @@ -0,0 +1,799 @@ +/** + * Image.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + +import java.io.*; +import java.util.*; + + +/** + * Used to create image objects and draw them on a page. + * The image type can be one of the following: ImageType.JPG, ImageType.PNG, ImageType.BMP or ImageType.JET + * + * Please see Example_03 and Example_24. + */ +public class Image implements Drawable { + + protected int objNumber; + + protected float x = 0f; // Position of the image on the page + protected float y = 0f; + protected float w; // Image width + protected float h; // Image height + + protected String uri; + protected String key; + + private float box_x; + private float box_y; + + private int degrees = 0; + private boolean flipUpsideDown = false; + + private String language = null; + private String altDescription = Single.space; + private String actualText = Single.space; + + + /** + * The main constructor for the Image class. + * + * @param pdf the PDF to which we add this image. + * @param inputStream the input stream to read the image from. + * @param imageType ImageType.JPG, ImageType.PNG and ImageType.BMP. + * + */ + public Image(PDF pdf, InputStream inputStream, int imageType) + throws Exception { + byte[] data; + if (imageType == ImageType.JPG) { + JPGImage jpg = new JPGImage(inputStream); + data = jpg.getData(); + w = jpg.getWidth(); + h = jpg.getHeight(); + if (jpg.getColorComponents() == 1) { + addImage(pdf, data, null, imageType, "DeviceGray", 8); + } + else if (jpg.getColorComponents() == 3) { + addImage(pdf, data, null, imageType, "DeviceRGB", 8); + } + else if (jpg.getColorComponents() == 4) { + addImage(pdf, data, null, imageType, "DeviceCMYK", 8); + } + } + else if (imageType == ImageType.PNG) { + PNGImage png = new PNGImage(inputStream); + data = png.getData(); + w = png.getWidth(); + h = png.getHeight(); + if (png.getColorType() == 0) { + addImage(pdf, data, null, imageType, "DeviceGray", png.getBitDepth()); + } + else { + if (png.getBitDepth() == 16) { + addImage(pdf, data, null, imageType, "DeviceRGB", 16); + } + else { + addImage(pdf, data, png.getAlpha(), imageType, "DeviceRGB", 8); + } + } + } + else if (imageType == ImageType.BMP) { + BMPImage bmp = new BMPImage(inputStream); + data = bmp.getData(); + w = bmp.getWidth(); + h = bmp.getHeight(); + addImage(pdf, data, null, imageType, "DeviceRGB", 8); + } + else if (imageType == ImageType.JET) { + addImage(pdf, inputStream); + } + + inputStream.close(); + } + + + public Image(PDF pdf, PDFobj obj) throws Exception { + w = Float.valueOf(obj.getValue("/Width")); + h = Float.valueOf(obj.getValue("/Height")); + pdf.newobj(); + pdf.append("<<\n"); + pdf.append("/Type /XObject\n"); + pdf.append("/Subtype /Image\n"); + pdf.append("/Filter "); + pdf.append(obj.getValue("/Filter")); + pdf.append("\n"); + pdf.append("/Width "); + pdf.append(w); + pdf.append('\n'); + pdf.append("/Height "); + pdf.append(h); + pdf.append('\n'); + String colorSpace = obj.getValue("/ColorSpace"); + if (!colorSpace.equals("")) { + pdf.append("/ColorSpace "); + pdf.append(colorSpace); + pdf.append("\n"); + } + pdf.append("/BitsPerComponent "); + pdf.append(obj.getValue("/BitsPerComponent")); + pdf.append("\n"); + String decodeParms = obj.getValue("/DecodeParms"); + if (!decodeParms.equals("")) { + pdf.append("/DecodeParms "); + pdf.append(decodeParms); + pdf.append("\n"); + } + String imageMask = obj.getValue("/ImageMask"); + if (!imageMask.equals("")) { + pdf.append("/ImageMask "); + pdf.append(imageMask); + pdf.append("\n"); + } + pdf.append("/Length "); + pdf.append(obj.stream.length); + pdf.append('\n'); + pdf.append(">>\n"); + pdf.append("stream\n"); + pdf.append(obj.stream, 0, obj.stream.length); + pdf.append("\nendstream\n"); + pdf.endobj(); + pdf.images.add(this); + objNumber = pdf.objNumber; + } + + + /** + * Sets the position of this image on the page to (x, y). + * + * @param x the x coordinate of the top left corner of the image. + * @param y the y coordinate of the top left corner of the image. + */ + public Image setPosition(double x, double y) { + return setPosition((float) x, (float) y); + } + + + /** + * Sets the position of this image on the page to (x, y). + * + * @param x the x coordinate of the top left corner of the image. + * @param y the y coordinate of the top left corner of the image. + */ + public Image setPosition(float x, float y) { + return setLocation(x, y); + } + + + /** + * Sets the location of this image on the page to (x, y). + * + * @param x the x coordinate of the top left corner of the image. + * @param y the y coordinate of the top left corner of the image. + */ + public Image setLocation(float x, float y) { + this.x = x; + this.y = y; + return this; + } + + + /** + * Scales this image by the specified factor. + * + * @param factor the factor used to scale the image. + */ + public Image scaleBy(double factor) { + return this.scaleBy((float) factor, (float) factor); + } + + + /** + * Scales this image by the specified factor. + * + * @param factor the factor used to scale the image. + */ + public Image scaleBy(float factor) { + return this.scaleBy(factor, factor); + } + + + /** + * Scales this image by the specified width and height factor. + *

Author: Pieter Libin, pieter@emweb.be

+ * + * @param widthFactor the factor used to scale the width of the image + * @param heightFactor the factor used to scale the height of the image + */ + public Image scaleBy(float widthFactor, float heightFactor) { + this.w *= widthFactor; + this.h *= heightFactor; + return this; + } + + + /** + * Places this image in the specified box. + * + * @param box the specified box. + */ + public void placeIn(Box box) throws Exception { + box_x = box.x; + box_y = box.y; + } + + + /** + * Sets the URI for the "click box" action. + * + * @param uri the URI + */ + public void setURIAction(String uri) { + this.uri = uri; + } + + + /** + * Sets the destination key for the action. + * + * @param key the destination name. + */ + public void setGoToAction(String key) { + this.key = key; + } + + + /** + * Sets the rotate90 flag. + * When the flag is true the image is rotated 90 degrees clockwise. + * + * @param rotate90 the flag. + */ + public void setRotateCW90(boolean rotate90) { + if (rotate90) { + this.degrees = 90; + } + else { + this.degrees = 0; + } + } + + + /** + * Sets the image rotation to the specified number of degrees. + * + * @param degrees the number of degrees. + */ + public void setRotate(int degrees) { + this.degrees = degrees; + } + + + /** + * Sets the alternate description of this image. + * + * @param altDescription the alternate description of the image. + * @return this Image. + */ + public Image setAltDescription(String altDescription) { + this.altDescription = altDescription; + return this; + } + + + /** + * Sets the actual text for this image. + * + * @param actualText the actual text for the image. + * @return this Image. + */ + public Image setActualText(String actualText) { + this.actualText = actualText; + return this; + } + + + /** + * Draws this image on the specified page. + * + * @param page the page to draw this image on. + * @return x and y coordinates of the bottom right corner of this component. + * @throws Exception + */ + public float[] drawOn(Page page) throws Exception { + page.addBMC(StructElem.SPAN, language, altDescription, actualText); + + x += box_x; + y += box_y; + page.append("q\n"); + + if (degrees == 0) { + page.append(w); + page.append(' '); + page.append(0f); + page.append(' '); + page.append(0f); + page.append(' '); + page.append(h); + page.append(' '); + page.append(x); + page.append(' '); + page.append(page.height - (y + h)); + page.append(" cm\n"); + } + else if (degrees == 90) { + page.append(h); + page.append(' '); + page.append(0f); + page.append(' '); + page.append(0f); + page.append(' '); + page.append(w); + page.append(' '); + page.append(x); + page.append(' '); + page.append(page.height - y); + page.append(" cm\n"); + page.append("0 -1 1 0 0 0 cm\n"); + } + else if (degrees == 180) { + page.append(w); + page.append(' '); + page.append(0f); + page.append(' '); + page.append(0f); + page.append(' '); + page.append(h); + page.append(' '); + page.append(x + w); + page.append(' '); + page.append(page.height - y); + page.append(" cm\n"); + page.append("-1 0 0 -1 0 0 cm\n"); + } + else if (degrees == 270) { + page.append(h); + page.append(' '); + page.append(0f); + page.append(' '); + page.append(0f); + page.append(' '); + page.append(w); + page.append(' '); + page.append(x + h); + page.append(' '); + page.append(page.height - (y + w)); + page.append(" cm\n"); + page.append("0 1 -1 0 0 0 cm\n"); + } + + if (flipUpsideDown) { + page.append("1 0 0 -1 0 0 cm\n"); + } + + page.append("/Im"); + page.append(objNumber); + page.append(" Do\n"); + page.append("Q\n"); + + page.addEMC(); + + if (uri != null || key != null) { + page.addAnnotation(new Annotation( + uri, + key, // The destination name + x, + page.height - y, + x + w, + page.height - (y + h), + language, + altDescription, + actualText)); + } + + return new float[] {x + w, y + h}; + } + + + /** + * Returns the width of this image when drawn on the page. + * The scaling is take into account. + * + * @return w - the width of this image. + */ + public float getWidth() { + return this.w; + } + + + /** + * Returns the height of this image when drawn on the page. + * The scaling is take into account. + * + * @return h - the height of this image. + */ + public float getHeight() { + return this.h; + } + + + private void addSoftMask( + PDF pdf, + byte[] data, + String colorSpace, + int bitsPerComponent) throws Exception { + pdf.newobj(); + pdf.append("<<\n"); + pdf.append("/Type /XObject\n"); + pdf.append("/Subtype /Image\n"); + pdf.append("/Filter /FlateDecode\n"); + pdf.append("/Width "); + pdf.append(( int ) w); + pdf.append('\n'); + pdf.append("/Height "); + pdf.append(( int ) h); + pdf.append('\n'); + pdf.append("/ColorSpace /"); + pdf.append(colorSpace); + pdf.append('\n'); + pdf.append("/BitsPerComponent "); + pdf.append(bitsPerComponent); + pdf.append('\n'); + pdf.append("/Length "); + pdf.append(data.length); + pdf.append('\n'); + pdf.append(">>\n"); + pdf.append("stream\n"); + pdf.append(data, 0, data.length); + pdf.append("\nendstream\n"); + pdf.endobj(); + objNumber = pdf.objNumber; + } + + + private void addImage( + PDF pdf, + byte[] data, + byte[] alpha, + int imageType, + String colorSpace, + int bitsPerComponent) throws Exception { + if (alpha != null) { + addSoftMask(pdf, alpha, "DeviceGray", 8); + } + pdf.newobj(); + pdf.append("<<\n"); + pdf.append("/Type /XObject\n"); + pdf.append("/Subtype /Image\n"); + if (imageType == ImageType.JPG) { + pdf.append("/Filter /DCTDecode\n"); + } + else if (imageType == ImageType.PNG || imageType == ImageType.BMP) { + pdf.append("/Filter /FlateDecode\n"); + if (alpha != null) { + pdf.append("/SMask "); + pdf.append(objNumber); + pdf.append(" 0 R\n"); + } + } + pdf.append("/Width "); + pdf.append(( int ) w); + pdf.append('\n'); + pdf.append("/Height "); + pdf.append(( int ) h); + pdf.append('\n'); + pdf.append("/ColorSpace /"); + pdf.append(colorSpace); + pdf.append('\n'); + pdf.append("/BitsPerComponent "); + pdf.append(bitsPerComponent); + pdf.append('\n'); + if (colorSpace.equals("DeviceCMYK")) { + // If the image was created with Photoshop - invert the colors: + pdf.append("/Decode [1.0 0.0 1.0 0.0 1.0 0.0 1.0 0.0]\n"); + } + pdf.append("/Length "); + pdf.append(data.length); + pdf.append('\n'); + pdf.append(">>\n"); + pdf.append("stream\n"); + pdf.append(data, 0, data.length); + pdf.append("\nendstream\n"); + pdf.endobj(); + pdf.images.add(this); + objNumber = pdf.objNumber; + } + + + private void addImage(PDF pdf, InputStream inputStream) throws Exception { + + w = getInt(inputStream); // Width + h = getInt(inputStream); // Height + byte c = (byte) inputStream.read(); // Color Space + byte a = (byte) inputStream.read(); // Alpha + + if (a != 0) { + pdf.newobj(); + pdf.append("<<\n"); + pdf.append("/Type /XObject\n"); + pdf.append("/Subtype /Image\n"); + pdf.append("/Filter /FlateDecode\n"); + pdf.append("/Width "); + pdf.append(w); + pdf.append('\n'); + pdf.append("/Height "); + pdf.append(h); + pdf.append('\n'); + pdf.append("/ColorSpace /DeviceGray\n"); + pdf.append("/BitsPerComponent 8\n"); + int length = getInt(inputStream); + pdf.append("/Length "); + pdf.append(length); + pdf.append('\n'); + pdf.append(">>\n"); + pdf.append("stream\n"); + byte[] buf1 = new byte[length]; + inputStream.read(buf1, 0, length); + pdf.append(buf1, 0, length); + pdf.append("\nendstream\n"); + pdf.endobj(); + objNumber = pdf.objNumber; + } + + pdf.newobj(); + pdf.append("<<\n"); + pdf.append("/Type /XObject\n"); + pdf.append("/Subtype /Image\n"); + pdf.append("/Filter /FlateDecode\n"); + if (a != 0) { + pdf.append("/SMask "); + pdf.append(objNumber); + pdf.append(" 0 R\n"); + } + pdf.append("/Width "); + pdf.append(w); + pdf.append('\n'); + pdf.append("/Height "); + pdf.append(h); + pdf.append('\n'); + pdf.append("/ColorSpace /"); + if (c == 1) { + pdf.append("DeviceGray"); + } + else if (c == 3 || c == 6) { + pdf.append("DeviceRGB"); + } + pdf.append('\n'); + pdf.append("/BitsPerComponent 8\n"); + pdf.append("/Length "); + pdf.append(getInt(inputStream)); + pdf.append('\n'); + pdf.append(">>\n"); + pdf.append("stream\n"); + byte[] buf2 = new byte[2048]; + int count; + while ((count = inputStream.read(buf2, 0, buf2.length)) > 0) { + pdf.append(buf2, 0, count); + } + pdf.append("\nendstream\n"); + pdf.endobj(); + pdf.images.add(this); + objNumber = pdf.objNumber; + } + + + private int getInt(InputStream inputStream) throws Exception { + byte[] buf = new byte[4]; + inputStream.read(buf, 0, 4); + int val = 0; + val |= buf[0] & 0xff; + val <<= 8; + val |= buf[1] & 0xff; + val <<= 8; + val |= buf[2] & 0xff; + val <<= 8; + val |= buf[3] & 0xff; + return val; + } + + + /** + * Constructor used to attach images to existing PDF. + * + * @param objects the map to which we add this image. + * @param inputStream the input stream to read the image from. + * @param imageType ImageType.JPG, ImageType.PNG and ImageType.BMP. + * + */ + public Image(Map objects, InputStream inputStream, int imageType) + throws Exception { + byte[] data; + if (imageType == ImageType.JPG) { + JPGImage jpg = new JPGImage(inputStream); + data = jpg.getData(); + w = jpg.getWidth(); + h = jpg.getHeight(); + if (jpg.getColorComponents() == 1) { + addImage(objects, data, null, imageType, "DeviceGray", 8); + } + else if (jpg.getColorComponents() == 3) { + addImage(objects, data, null, imageType, "DeviceRGB", 8); + } + else if (jpg.getColorComponents() == 4) { + addImage(objects, data, null, imageType, "DeviceCMYK", 8); + } + } + else if (imageType == ImageType.PNG) { + PNGImage png = new PNGImage(inputStream); + data = png.getData(); + w = png.getWidth(); + h = png.getHeight(); + if (png.getColorType() == 0) { + addImage(objects, data, null, imageType, "DeviceGray", png.getBitDepth()); + } + else { + if (png.getBitDepth() == 16) { + addImage(objects, data, null, imageType, "DeviceRGB", 16); + } + else { + addImage(objects, data, png.getAlpha(), imageType, "DeviceRGB", 8); + } + } + } + else if (imageType == ImageType.BMP) { + BMPImage bmp = new BMPImage(inputStream); + data = bmp.getData(); + w = bmp.getWidth(); + h = bmp.getHeight(); + addImage(objects, data, null, imageType, "DeviceRGB", 8); + } +/* + else if (imageType == ImageType.JET) { + addImage(pdf, inputStream); + } +*/ + inputStream.close(); + } + + + private void addSoftMask( + Map objects, + byte[] data, + String colorSpace, + int bitsPerComponent) throws Exception { + PDFobj obj = new PDFobj(); + List dict = obj.getDict(); + dict.add("<<"); + dict.add("/Type"); + dict.add("/XObject"); + dict.add("/Subtype"); + dict.add("/Image"); + dict.add("/Filter"); + dict.add("/FlateDecode"); + dict.add("/Width"); + dict.add(String.valueOf((int) w)); + dict.add("/Height"); + dict.add(String.valueOf((int) h)); + dict.add("/ColorSpace"); + dict.add("/" + colorSpace); + dict.add("/BitsPerComponent"); + dict.add(String.valueOf(bitsPerComponent)); + dict.add("/Length"); + dict.add(String.valueOf(data.length)); + dict.add(">>"); + obj.setStream(data); + obj.number = Collections.max(objects.keySet()) + 1; + objects.put(obj.number, obj); + objNumber = obj.number; + } + + + private void addImage( + Map objects, + byte[] data, + byte[] alpha, + int imageType, + String colorSpace, + int bitsPerComponent) throws Exception { + if (alpha != null) { + addSoftMask(objects, alpha, "DeviceGray", 8); + } + PDFobj obj = new PDFobj(); + List dict = obj.getDict(); + dict.add("<<"); + dict.add("/Type"); + dict.add("/XObject"); + dict.add("/Subtype"); + dict.add("/Image"); + if (imageType == ImageType.JPG) { + dict.add("/Filter"); + dict.add("/DCTDecode"); + } + else if (imageType == ImageType.PNG || imageType == ImageType.BMP) { + dict.add("/Filter"); + dict.add("/FlateDecode"); + if (alpha != null) { + dict.add("/SMask"); + dict.add(String.valueOf(objNumber)); + dict.add("0"); + dict.add("R"); + } + } + dict.add("/Width"); + dict.add(String.valueOf((int) w)); + dict.add("/Height"); + dict.add(String.valueOf((int) h)); + dict.add("/ColorSpace"); + dict.add("/" + colorSpace); + dict.add("/BitsPerComponent"); + dict.add(String.valueOf(bitsPerComponent)); + if (colorSpace.equals("DeviceCMYK")) { + // If the image was created with Photoshop - invert the colors: + dict.add("/Decode"); + dict.add("["); + dict.add("1.0"); + dict.add("0.0"); + dict.add("1.0"); + dict.add("0.0"); + dict.add("1.0"); + dict.add("0.0"); + dict.add("1.0"); + dict.add("0.0"); + dict.add("]"); + } + dict.add("/Length"); + dict.add(String.valueOf(data.length)); + dict.add(">>"); + obj.setStream(data); + obj.number = Collections.max(objects.keySet()) + 1; + objects.put(obj.number, obj); + objNumber = obj.number; + } + + + public void resizeToFit(Page page, boolean keepAspectRatio) { + float page_w = page.getWidth(); + float page_h = page.getHeight(); + float image_w = this.getWidth(); + float image_h = this.getHeight(); + if (keepAspectRatio) { + this.scaleBy(Math.min((page_w - x)/image_w, (page_h - y)/image_h)); + } + else { + this.scaleBy((page_w - x)/image_w, (page_h - y)/image_h); + } + } + + + public void flipUpsideDown(boolean flipUpsideDown) { + this.flipUpsideDown = flipUpsideDown; + } + +} // End of Image.java diff --git a/PDFJet/src/main/java/com/pdfjet/ImageType.java b/PDFJet/src/main/java/com/pdfjet/ImageType.java new file mode 100644 index 0000000..a5fd831 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/ImageType.java @@ -0,0 +1,44 @@ +/** + * ImageType.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + + +/** + * Used to specify the image type of an image. + * Supported types: ImageType.JPG, ImageType.PNG, ImageType.BMP and ImageType.JET + * See the Image class for more information. + * + */ +public class ImageType { + public static final int JPG = 0; + public static final int PNG = 1; + public static final int BMP = 2; + public static final int JET = 3; +} diff --git a/PDFJet/src/main/java/com/pdfjet/JPGImage.java b/PDFJet/src/main/java/com/pdfjet/JPGImage.java new file mode 100644 index 0000000..93e71bb --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/JPGImage.java @@ -0,0 +1,237 @@ +/** + * JPGImage.java + * + * The authors make NO WARRANTY or representation, either express or implied, + * with respect to this software, its quality, accuracy, merchantability, or + * fitness for a particular purpose. This software is provided "AS IS", and you, + * its user, assume the entire risk as to its quality and accuracy. + * + * This software is copyright (C) 1991-1998, Thomas G. Lane. + * All Rights Reserved except as specified below. + * + * Permission is hereby granted to use, copy, modify, and distribute this + * software (or portions thereof) for any purpose, without fee, subject to these + * conditions: + * (1) If any part of the source code for this software is distributed, then this + * README file must be included, with this copyright and no-warranty notice + * unaltered; and any additions, deletions, or changes to the original files + * must be clearly indicated in accompanying documentation. + * (2) If only executable code is distributed, then the accompanying + * documentation must state that "this software is based in part on the work of + * the Independent JPEG Group". + * (3) Permission for use of this software is granted only if the user accepts + * full responsibility for any undesirable consequences; the authors accept + * NO LIABILITY for damages of any kind. + * + * These conditions apply to any software derived from or based on the IJG code, + * not just to the unmodified library. If you use our work, you ought to + * acknowledge us. + * + * Permission is NOT granted for the use of any IJG author's name or company name + * in advertising or publicity relating to this software or products derived from + * it. This software may be referred to only as "the Independent JPEG Group's + * software". + * + * We specifically permit and encourage the use of this software as the basis of + * commercial products, provided that all warranty or liability claims are + * assumed by the product vendor. + */ + +package com.pdfjet; + +import java.io.*; + + +/** + * Used to embed JPG images in the PDF document. + * + */ +class JPGImage { + + static final char M_SOF0 = (char) 0x00C0; // Start Of Frame N + static final char M_SOF1 = (char) 0x00C1; // N indicates which compression process + static final char M_SOF2 = (char) 0x00C2; // Only SOF0-SOF2 are now in common use + static final char M_SOF3 = (char) 0x00C3; + static final char M_SOF5 = (char) 0x00C5; // NB: codes C4 and CC are NOT SOF markers + static final char M_SOF6 = (char) 0x00C6; + static final char M_SOF7 = (char) 0x00C7; + static final char M_SOF9 = (char) 0x00C9; + static final char M_SOF10 = (char) 0x00CA; + static final char M_SOF11 = (char) 0x00CB; + static final char M_SOF13 = (char) 0x00CD; + static final char M_SOF14 = (char) 0x00CE; + static final char M_SOF15 = (char) 0x00CF; + + int width; + int height; + long size; + int colorComponents; + byte[] data; + + + public JPGImage(InputStream inputStream) throws Exception { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte[] buf = new byte[2048]; + int count; + while ((count = inputStream.read(buf, 0, buf.length)) > 0) { + baos.write(buf, 0, count); + } + inputStream.close(); + data = baos.toByteArray(); + readJPGImage(new ByteArrayInputStream(data)); + } + + + protected int getWidth() { + return this.width; + } + + + protected int getHeight() { + return this.height; + } + + + protected long getFileSize() { + return this.size; + } + + + protected int getColorComponents() { + return this.colorComponents; + } + + + protected byte[] getData() { + return this.data; + } + + + private void readJPGImage(InputStream is) throws Exception { + char ch1 = (char) is.read(); + char ch2 = (char) is.read(); + size += 2; + if (ch1 == 0x00FF && ch2 == 0x00D8) { + boolean foundSOFn = false; + while (true) { + char ch = nextMarker(is); + switch (ch) { + // Note that marker codes 0xC4, 0xC8, 0xCC are not, + // and must not be treated as SOFn. C4 in particular + // is actually DHT. + case M_SOF0: // Baseline + case M_SOF1: // Extended sequential, Huffman + case M_SOF2: // Progressive, Huffman + case M_SOF3: // Lossless, Huffman + case M_SOF5: // Differential sequential, Huffman + case M_SOF6: // Differential progressive, Huffman + case M_SOF7: // Differential lossless, Huffman + case M_SOF9: // Extended sequential, arithmetic + case M_SOF10: // Progressive, arithmetic + case M_SOF11: // Lossless, arithmetic + case M_SOF13: // Differential sequential, arithmetic + case M_SOF14: // Differential progressive, arithmetic + case M_SOF15: // Differential lossless, arithmetic + // Skip 3 bytes to get to the image height and width + is.read(); + is.read(); + is.read(); + size += 3; + height = readTwoBytes(is); + width = readTwoBytes(is); + colorComponents = is.read(); + size++; + foundSOFn = true; + break; + + default: + skipVariable(is); + break; + } + + if (foundSOFn) { + while (is.read() != -1) { + size++; + } + break; + } + } + } + else { + throw new Exception(); + } +// System.out.println("size == " + size); + } + + + private int readTwoBytes(InputStream is) throws Exception { + int value = is.read(); + value <<= 8; + value |= is.read(); + size += 2; + return value; + } + + + // Find the next JPEG marker and return its marker code. + // We expect at least one FF byte, possibly more if the compressor + // used FFs to pad the file. + // There could also be non-FF garbage between markers. The treatment + // of such garbage is unspecified; we choose to skip over it but + // emit a warning msg. + // NB: this routine must not be used after seeing SOS marker, since + // it will not deal correctly with FF/00 sequences in the compressed + // image data... + private char nextMarker(InputStream is) throws Exception { + int discarded_bytes = 0; + char ch = ' '; + + // Find 0xFF byte; count and skip any non-FFs. + ch = (char) is.read(); + size++; + while (ch != 0x00FF) { + discarded_bytes++; + ch = (char) is.read(); + size++; + } + + // Get marker code byte, swallowing any duplicate FF bytes. + // Extra FFs are legal as pad bytes, so don't count them in discarded_bytes. + do { + ch = (char) is.read(); + size++; + } while (ch == 0x00FF); + + if (discarded_bytes != 0) { + throw new Exception(); + } + + return ch; + } + + + // Most types of marker are followed by a variable-length parameter + // segment. This routine skips over the parameters for any marker we + // don't otherwise want to process. + // Note that we MUST skip the parameter segment explicitly in order + // not to be fooled by 0xFF bytes that might appear within the + // parameter segment such bytes do NOT introduce new markers. + private void skipVariable(InputStream is) throws Exception { + // Get the marker parameter length count + int length = readTwoBytes(is); + + // Length includes itself, so must be at least 2 + if (length < 2) { + throw new Exception(); + } + length -= 2; + + // Skip over the remaining bytes + while (length > 0) { + is.read(); + size++; + length--; + } + } + +} // End of JPGImage.java diff --git a/PDFJet/src/main/java/com/pdfjet/Join.java b/PDFJet/src/main/java/com/pdfjet/Join.java new file mode 100644 index 0000000..8c5361f --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Join.java @@ -0,0 +1,42 @@ +/** + * Join.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + + +/** + * Used to specify the join style when joining two lines. + * See the Page and Line classes for more details. + * + */ +public class Join { + public static final int MITER = 0; + public static final int ROUND = 1; + public static final int BEVEL = 2; +} diff --git a/PDFJet/src/main/java/com/pdfjet/LZWEncode.java b/PDFJet/src/main/java/com/pdfjet/LZWEncode.java new file mode 100644 index 0000000..2770f14 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/LZWEncode.java @@ -0,0 +1,112 @@ +package com.pdfjet; + +import java.io.*; +import java.util.*; + + +public class LZWEncode { + + private LookupTable table = new LookupTable(); + private int bitBuffer = 0; + private int bitsInBuffer = 0; + + public LZWEncode(byte[] buffer, OutputStream stream) throws Exception { + int code1 = 0; + int code2 = 258; + int length = 9; + writeCode(256, length, stream); // Clear Table code + + List key = new ArrayList(); + int i = 0; + while (i < buffer.length) { + key.add(buffer[i]); + int code = table.at(key, /*put:*/ code2); + if (code >= 0) { + code1 = code; + i += 1; + if (i < buffer.length) { + continue; + } + writeCode(code1, length, stream); + } + else { + writeCode(code1, length, stream); + code2 += 1; + if (code2 == 512) { + length = 10; + } + else if (code2 == 1024) { + length = 11; + } + else if (code2 == 2048) { + length = 12; + } + else if (code2 == 4095) { // EarlyChange is 1 + writeCode(256, length, stream); // Clear Table code + code2 = 258; + length = 9; + table.clear(); + } + key.clear(); + } + } + + writeCode(257, length, stream); // EOD + if (bitsInBuffer > 0) { + stream.write((bitBuffer << (8 - bitsInBuffer)) & 0xFF); + } + } + + private void writeCode( + int code, int length, OutputStream stream) throws Exception { + bitBuffer <<= length; + bitBuffer |= code; + bitsInBuffer += length; + while (bitsInBuffer >= 8) { + stream.write((bitBuffer >>> (bitsInBuffer - 8)) & 0xFF); + bitsInBuffer -= 8; + } + } +/* + private static String toBinaryString( + int value, + int numOfDigits) { + StringBuilder buf = new StringBuilder(); + String str = Integer.toBinaryString(value).toUpperCase(); + int len = str.length(); + while (len < numOfDigits) { + buf.append("0"); + len += 1; + } + buf.append(str); + str = buf.toString(); + if (numOfDigits == 32) { + buf.setLength(0); + for (int i = 0; i < str.length(); i++) { + if (i > 0 && i % 8 == 0) { + buf.append(" "); + } + buf.append(str.charAt(i)); + } + str = buf.toString(); + } + return str; + } + + public static void main(String[] args) throws Exception { + String fileName = "data/world-communications.txt"; + int fileSize = (int) (new File(fileName)).length(); + BufferedOutputStream stream = + new BufferedOutputStream(new FileOutputStream("world-commnunications.lzw")); + FileInputStream fis = new FileInputStream(fileName); + byte[] buf = new byte[fileSize]; + int len = fis.read(buf, 0, buf.length); +long time1 = System.currentTimeMillis(); + new LZWEncode(buf, stream); +long time2 = System.currentTimeMillis(); +System.out.println(time2 - time1); + fis.close(); + stream.close(); + } +*/ +} diff --git a/PDFJet/src/main/java/com/pdfjet/Legal.java b/PDFJet/src/main/java/com/pdfjet/Legal.java new file mode 100644 index 0000000..c9d3bcd --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Legal.java @@ -0,0 +1,40 @@ +/** + * Legal.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + + +/** + * Used to specify PDF page with size Legal. + * For more information about the page size classes - A3, A4, A5, B5, Executive, Letter, Legal and Tabloid - see the Page class. + */ +public class Legal { + public static final float[] PORTRAIT = new float[] {612.0f, 1008.0f}; + public static final float[] LANDSCAPE = new float[] {1008.0f, 612.0f}; +} diff --git a/PDFJet/src/main/java/com/pdfjet/Letter.java b/PDFJet/src/main/java/com/pdfjet/Letter.java new file mode 100644 index 0000000..f779937 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Letter.java @@ -0,0 +1,41 @@ +/** + * Letter.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + + +/** + * Used to specify PDF page with size Letter. + * For more information about the page size classes - A3, A4, A5, B5, Executive, Letter, Legal and Tabloid - see the Page class. + * + */ +public class Letter { + public static final float[] PORTRAIT = new float[] {612.0f, 792.0f}; + public static final float[] LANDSCAPE = new float[] {792.0f, 612.0f}; +} diff --git a/PDFJet/src/main/java/com/pdfjet/Line.java b/PDFJet/src/main/java/com/pdfjet/Line.java new file mode 100644 index 0000000..9f12459 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Line.java @@ -0,0 +1,412 @@ +/** + * Line.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + + +/** + * Used to create line objects. + * + * Please see Example_01. + */ +public class Line implements Drawable { + + private float x1; + private float y1; + private float x2; + private float y2; + + private float box_x; + private float box_y; + + private int color = Color.black; + private float width = 0.3f; + private String pattern = "[] 0"; + private int capStyle = 0; + + private String language = null; + private String altDescription = Single.space; + private String actualText = Single.space; + + + /** + * The default constructor. + * + * + */ + public Line() { + } + + + /** + * Create a line object. + * + * @param x1 the x coordinate of the start point. + * @param y1 the y coordinate of the start point. + * @param x2 the x coordinate of the end point. + * @param y2 the y coordinate of the end point. + */ + public Line(double x1, double y1, double x2, double y2) { + this.x1 = (float) x1; + this.y1 = (float) y1; + this.x2 = (float) x2; + this.y2 = (float) y2; + } + + + /** + * Create a line object. + * + * @param x1 the x coordinate of the start point. + * @param y1 the y coordinate of the start point. + * @param x2 the x coordinate of the end point. + * @param y2 the y coordinate of the end point. + */ + public Line(float x1, float y1, float x2, float y2) { + this.x1 = x1; + this.y1 = y1; + this.x2 = x2; + this.y2 = y2; + } + + + /** + * The line dash pattern controls the pattern of dashes and gaps used to stroke paths. + * It is specified by a dash array and a dash phase. + * The elements of the dash array are positive numbers that specify the lengths of + * alternating dashes and gaps. + * The dash phase specifies the distance into the dash pattern at which to start the dash. + * The elements of both the dash array and the dash phase are expressed in user space units. + *
+     *  Examples of line dash patterns:
+     *
+     *      "[Array] Phase"     Appearance          Description
+     *      _______________     _________________   ____________________________________
+     *
+     *      "[] 0"              -----------------   Solid line
+     *      "[3] 0"             ---   ---   ---     3 units on, 3 units off, ...
+     *      "[2] 1"             -  --  --  --  --   1 on, 2 off, 2 on, 2 off, ...
+     *      "[2 1] 0"           -- -- -- -- -- --   2 on, 1 off, 2 on, 1 off, ...
+     *      "[3 5] 6"             ---     ---       2 off, 3 on, 5 off, 3 on, 5 off, ...
+     *      "[2 3] 11"          -   --   --   --    1 on, 3 off, 2 on, 3 off, 2 on, ...
+     *  
+ * + * @param pattern the line dash pattern. + * @return this Line object. + */ + public Line setPattern(String pattern) { + this.pattern = pattern; + return this; + } + + + /** + * Sets the x and y coordinates of the start point. + * + * @param x the x coordinate of the start point. + * @param y the y coordinate of the start point. + * @return this Line object. + */ + public Line setStartPoint(double x, double y) { + this.x1 = (float) x; + this.y1 = (float) y; + return this; + } + + + /** + * Sets the x and y coordinates of the start point. + * + * @param x the x coordinate of the start point. + * @param y the y coordinate of the start point. + * @return this Line object. + */ + public Line setStartPoint(float x, float y) { + this.x1 = x; + this.y1 = y; + return this; + } + + + /** + * Sets the x and y coordinates of the start point. + * + * @param x the x coordinate of the start point. + * @param y the y coordinate of the start point. + * @return this Line object. + */ + public Line setPointA(float x, float y) { + this.x1 = x; + this.y1 = y; + return this; + } + + + /** + * Returns the start point of this line. + * + * @return Point the point. + */ + public Point getStartPoint() { + return new Point(x1, y1); + } + + + /** + * Sets the x and y coordinates of the end point. + * + * @param x the x coordinate of the end point. + * @param y the y coordinate of the end point. + * @return this Line object. + */ + public Line setEndPoint(double x, double y) { + this.x2 = (float) x; + this.y2 = (float) y; + return this; + } + + + /** + * Sets the x and y coordinates of the end point. + * + * @param x the x coordinate of the end point. + * @param y the t coordinate of the end point. + * @return this Line object. + */ + public Line setEndPoint(float x, float y) { + this.x2 = x; + this.y2 = y; + return this; + } + + + /** + * Sets the x and y coordinates of the end point. + * + * @param x the x coordinate of the end point. + * @param y the t coordinate of the end point. + * @return this Line object. + */ + public Line setPointB(float x, float y) { + this.x2 = x; + this.y2 = y; + return this; + } + + + /** + * Returns the end point of this line. + * + * @return Point the point. + */ + public Point getEndPoint() { + return new Point(x2, y2); + } + + + /** + * Sets the width of this line. + * + * @param width the width. + * @return this Line object. + */ + public Line setWidth(double width) { + this.width = (float) width; + return this; + } + + + /** + * Sets the width of this line. + * + * @param width the width. + * @return this Line object. + */ + public Line setWidth(float width) { + this.width = width; + return this; + } + + + /** + * Sets the color for this line. + * + * @param color the color specified as an integer. + * @return this Line object. + */ + public Line setColor(int color) { + this.color = color; + return this; + } + + + /** + * Sets the line cap style. + * + * @param style the cap style of the current line. Supported values: Cap.BUTT, Cap.ROUND and Cap.PROJECTING_SQUARE + * @return this Line object. + */ + public Line setCapStyle(int style) { + this.capStyle = style; + return this; + } + + + /** + * Returns the line cap style. + * + * @return the cap style. + */ + public int getCapStyle() { + return capStyle; + } + + + /** + * Sets the alternate description of this line. + * + * @param altDescription the alternate description of the line. + * @return this Line. + */ + public Line setAltDescription(String altDescription) { + this.altDescription = altDescription; + return this; + } + + + /** + * Sets the actual text for this line. + * + * @param actualText the actual text for the line. + * @return this Line. + */ + public Line setActualText(String actualText) { + this.actualText = actualText; + return this; + } + + + /** + * Places this line in the specified box at position (0.0f, 0.0f). + * + * @param box the specified box. + * @return this Line object. + */ + public Line placeIn(Box box) throws Exception { + return placeIn(box, 0f, 0f); + } + + + /** + * Places this line in the specified box. + * + * @param box the specified box. + * @param x_offset the x offset from the top left corner of the box. + * @param y_offset the y offset from the top left corner of the box. + * @return this Line object. + */ + public Line placeIn( + Box box, + double x_offset, + double y_offset) throws Exception { + placeIn(box, (float) x_offset, (float) y_offset); + return this; + } + + + /** + * Places this line in the specified box. + * + * @param box the specified box. + * @param x_offset the x offset from the top left corner of the box. + * @param y_offset the y offset from the top left corner of the box. + * @return this Line object. + */ + public Line placeIn( + Box box, + float x_offset, + float y_offset) throws Exception { + box_x = box.x + x_offset; + box_y = box.y + y_offset; + return this; + } + + + /** + * Scales this line by the spacified factor. + * + * @param factor the factor used to scale the line. + * @return this Line object. + */ + public Line scaleBy(double factor) throws Exception { + return scaleBy((float) factor); + } + + + /** + * Scales this line by the spacified factor. + * + * @param factor the factor used to scale the line. + * @return this Line object. + */ + public Line scaleBy(float factor) throws Exception { + this.x1 *= factor; + this.x2 *= factor; + this.y1 *= factor; + this.y2 *= factor; + return this; + } + + + /** + * Draws this line on the specified page. + * + * @param page the page to draw this line on. + * @return x and y coordinates of the bottom right corner of this component. + * @throws Exception + */ + public float[] drawOn(Page page) throws Exception { + page.setPenColor(color); + page.setPenWidth(width); + page.setLineCapStyle(capStyle); + page.setLinePattern(pattern); + page.addBMC(StructElem.SPAN, language, altDescription, actualText); + page.drawLine( + x1 + box_x, + y1 + box_y, + x2 + box_x, + y2 + box_y); + page.addEMC(); + + float x_max = Math.max(x1 + box_x, x2 + box_x); + float y_max = Math.max(y1 + box_y, y2 + box_y); + return new float[] {x_max, y_max}; + } + +} // End of Line.java diff --git a/PDFJet/src/main/java/com/pdfjet/LookupTable.java b/PDFJet/src/main/java/com/pdfjet/LookupTable.java new file mode 100644 index 0000000..8c43365 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/LookupTable.java @@ -0,0 +1,57 @@ +package com.pdfjet; + +import java.util.*; + +class Pair { + List key; + int code; +} + +public class LookupTable { + + private final int mask = 0xFFFF; + private Pair[] pairs = new Pair[mask + 1]; + + public LookupTable() { + for (int i = 0; i < pairs.length; i++) { + pairs[i] = new Pair(); + } + } + + public void clear() { + for (int i = 0; i < pairs.length; i++) { + pairs[i].key = null; + } + } + + public int at(List key, int code) { + if (key.size() == 1) { + return key.get(0) & 0xFF; + } + int index = hash(key); + while (true) { + if (pairs[index].key == null) { + break; + } + if (pairs[index].key.equals(key)) { + return pairs[index].code; + } + index += 1; + if (index > mask) { + index = 0; + } + } + pairs[index].key = new ArrayList(key); + pairs[index].code = code; + return -1; + } + + private int hash(List buffer) { + int hash = 5381; + for (Byte b1 : buffer) { + hash = ((hash << 5) + hash) + (int) b1; + } + return hash & mask; + } + +} diff --git a/PDFJet/src/main/java/com/pdfjet/Mark.java b/PDFJet/src/main/java/com/pdfjet/Mark.java new file mode 100644 index 0000000..8cafd4b --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Mark.java @@ -0,0 +1,41 @@ +/** + * Mark.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + + +/** + * Used to specify the check mark in CheckBox. + * + */ +public class Mark { + public static final int UNCHECK = 0; + public static final int CHECK = 1; + public static final int X = 2; +} diff --git a/PDFJet/src/main/java/com/pdfjet/MaskPattern.java b/PDFJet/src/main/java/com/pdfjet/MaskPattern.java new file mode 100644 index 0000000..b6c6543 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/MaskPattern.java @@ -0,0 +1,30 @@ +/** + * +Copyright (c) 2009 Kazuhiko Arase + +URL: http://www.d-project.com/ + +Licensed under the MIT license: + http://www.opensource.org/licenses/mit-license.php + +The word "QR Code" is registered trademark of +DENSO WAVE INCORPORATED + http://www.denso-wave.com/qrcode/faqpatent-e.html +*/ + +package com.pdfjet; + + +/** + * @author Kazuhiko Arase + */ +interface MaskPattern { + public static final int PATTERN000 = 0; + public static final int PATTERN001 = 1; + public static final int PATTERN010 = 2; + public static final int PATTERN011 = 3; + public static final int PATTERN100 = 4; + public static final int PATTERN101 = 5; + public static final int PATTERN110 = 6; + public static final int PATTERN111 = 7; +} diff --git a/PDFJet/src/main/java/com/pdfjet/Operation.java b/PDFJet/src/main/java/com/pdfjet/Operation.java new file mode 100644 index 0000000..b44eb6b --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Operation.java @@ -0,0 +1,41 @@ +/** + * Operation.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + + +/** + * Used to specify the 'stroke', 'close' and 'fill' operations. + * + */ +public class Operation { + public static char STROKE = 'S'; + public static char CLOSE = 's'; + public static char FILL = 'f'; +} diff --git a/PDFJet/src/main/java/com/pdfjet/OptionalContentGroup.java b/PDFJet/src/main/java/com/pdfjet/OptionalContentGroup.java new file mode 100644 index 0000000..a078802 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/OptionalContentGroup.java @@ -0,0 +1,117 @@ +/** + * OptionalContentGroup.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +package com.pdfjet; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + + +/** + * Container for drawable objects that can be drawn on a page as part of Optional Content Group. + * Please see the PDF specification and Example_30 for more details. + * + * @author Mark Paxton + */ +public class OptionalContentGroup { + + protected String name; + protected int ocgNumber; + protected int objNumber; + protected boolean visible; + protected boolean printable; + protected boolean exportable; + private List components; + + public OptionalContentGroup(String name) { + this.name = name; + this.components = new ArrayList(); + } + + public void add(Drawable d) { + components.add(d); + } + + public void setVisible(boolean visible) { + this.visible = visible; + } + + public void setPrintable(boolean printable) { + this.printable = printable; + } + + public void setExportable(boolean exportable) { + this.exportable = exportable; + } + + public void drawOn(Page p) throws Exception { + if (!components.isEmpty()) { + p.pdf.groups.add(this); + ocgNumber = p.pdf.groups.size(); + + p.pdf.newobj(); + p.pdf.append("<<\n"); + p.pdf.append("/Type /OCG\n"); + p.pdf.append("/Name (" + name + ")\n"); + p.pdf.append("/Usage <<\n"); + if (visible) { + p.pdf.append("/View << /ViewState /ON >>\n"); + } + else { + p.pdf.append("/View << /ViewState /OFF >>\n"); + } + if (printable) { + p.pdf.append("/Print << /PrintState /ON >>\n"); + } + else { + p.pdf.append("/Print << /PrintState /OFF >>\n"); + } + if (exportable) { + p.pdf.append("/Export << /ExportState /ON >>\n"); + } + else { + p.pdf.append("/Export << /ExportState /OFF >>\n"); + } + p.pdf.append(">>\n"); + p.pdf.append(">>\n"); + p.pdf.endobj(); + + objNumber = p.pdf.objNumber; + + p.append("/OC /OC"); + p.append(ocgNumber); + p.append(" BDC\n"); + for (Drawable component : components) { + component.drawOn(p); + } + p.append("\nEMC\n"); + } + } + +} // End of OptionalContentGroup.java diff --git a/PDFJet/src/main/java/com/pdfjet/PDF.java b/PDFJet/src/main/java/com/pdfjet/PDF.java new file mode 100644 index 0000000..cd327f7 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/PDF.java @@ -0,0 +1,1853 @@ +/** + * PDF.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + +import java.io.*; +import java.text.*; +import java.util.*; +import java.util.zip.*; + + +/** + * Used to create PDF objects that represent PDF documents. + * + * + */ +public class PDF { + + protected int objNumber = 0; + protected int metadataObjNumber = 0; + protected int outputIntentObjNumber = 0; + protected List fonts = new ArrayList(); + protected List images = new ArrayList(); + protected List pages = new ArrayList(); + protected Map destinations = new HashMap(); + protected List groups = new ArrayList(); + protected Map states = new HashMap(); + protected static final DecimalFormat df = new DecimalFormat("0.###", new DecimalFormatSymbols(Locale.US)); + protected int compliance = 0; + protected List embeddedFiles = new ArrayList(); + + private OutputStream os = null; + private List objOffset = new ArrayList(); + private String title = ""; + private String author = ""; + private String subject = ""; + private String keywords = ""; + private String creator = ""; + private String producer = "PDFjet v6.00 (http://pdfjet.com)"; + private String creationDate; + private String modDate; + private String createDate; + private int byte_count = 0; + private int pagesObjNumber = -1; + private String pageLayout = null; + private String pageMode = null; + private String language = "en-US"; + + protected Bookmark toc = null; + protected List importedFonts = new ArrayList(); + protected String extGState = ""; + + + /** + * The default constructor - use when reading PDF files. + * + * @throws Exception + */ + public PDF() throws Exception { + } + + + /** + * Creates a PDF object that represents a PDF document. + * + * @param os the associated output stream. + */ + public PDF(OutputStream os) throws Exception { this(os, 0); } + + + // Here is the layout of the PDF document: + // + // Metadata Object + // Output Intent Object + // Fonts + // Images + // Resources Object + // Content1 + // Content2 + // ... + // ContentN + // Annot1 + // Annot2 + // ... + // AnnotN + // Page1 + // Page2 + // ... + // PageN + // Pages + // StructElem1 + // StructElem2 + // ... + // StructElemN + // StructTreeRoot + // Info + // Root + // xref table + // Trailer + /** + * Creates a PDF object that represents a PDF document. + * Use this constructor to create PDF/A compliant PDF documents. + * Please note: PDF/A compliance requires all fonts to be embedded in the PDF. + * + * @param os the associated output stream. + * @param compliance must be: Compliance.PDF_A_1B + */ + public PDF(OutputStream os, int compliance) throws Exception { + + this.os = os; + this.compliance = compliance; + + Date date = new Date(); + SimpleDateFormat sdf1 = new SimpleDateFormat("yyyyMMddHHmmss"); + SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); + creationDate = sdf1.format(date); + modDate = sdf1.format(date); + createDate = sdf2.format(date); + + append("%PDF-1.5\n"); + append('%'); + append((byte) 0x00F2); + append((byte) 0x00F3); + append((byte) 0x00F4); + append((byte) 0x00F5); + append((byte) 0x00F6); + append('\n'); + + if (compliance == Compliance.PDF_A_1B || + compliance == Compliance.PDF_UA) { + metadataObjNumber = addMetadataObject("", false); + outputIntentObjNumber = addOutputIntentObject(); + } + + } + + + protected void newobj() throws IOException { + objOffset.add(byte_count); + append(++objNumber); + append(" 0 obj\n"); + } + + + protected void endobj() throws IOException { + append("endobj\n"); + } + + + protected int addMetadataObject(String notice, boolean fontMetadataObject) throws Exception { + StringBuilder sb = new StringBuilder(); + sb.append("\n"); + sb.append("\n"); + sb.append("\n"); + + if (fontMetadataObject) { + sb.append("\n"); + sb.append("\n"); + sb.append("\n"); + sb.append("\n"); + sb.append(notice); + sb.append("\n"); + sb.append("\n"); + sb.append("\n"); + sb.append("\n"); + } + else { + sb.append("\n\n"); + + sb.append("\n"); + sb.append(" application/pdf\n"); + sb.append(" "); + sb.append(title); + sb.append("\n"); + sb.append(" "); + sb.append(author); + sb.append("\n"); + sb.append(" "); + sb.append(subject); + sb.append("\n"); + sb.append("\n"); + + sb.append("\n"); + sb.append(" 1\n"); + sb.append(" B\n"); + sb.append("\n"); + + if (compliance == Compliance.PDF_UA) { + sb.append("\n"); + sb.append(" 1\n"); + sb.append("\n"); + } + + sb.append("\n"); + sb.append(""); + sb.append(createDate + "Z"); + sb.append("\n"); + sb.append("\n"); + } + + sb.append("\n"); + sb.append("\n"); + + if (!fontMetadataObject) { + // Add the recommended 2000 bytes padding + for (int i = 0; i < 20; i++) { + for (int j = 0; j < 10; j++) { + sb.append(" "); + } + sb.append("\n"); + } + } + + sb.append(""); + + byte[] xml = sb.toString().getBytes("UTF-8"); + + // This is the metadata object + newobj(); + append("<<\n"); + append("/Type /Metadata\n"); + append("/Subtype /XML\n"); + append("/Length "); + append(xml.length); + append("\n"); + append(">>\n"); + append("stream\n"); + append(xml, 0, xml.length); + append("\nendstream\n"); + endobj(); + + return objNumber; + } + + + protected int addOutputIntentObject() throws Exception { + newobj(); + append("<<\n"); + append("/N 3\n"); + + append("/Length "); + append(ICCBlackScaled.profile.length); + append("\n"); + + append("/Filter /FlateDecode\n"); + append(">>\n"); + append("stream\n"); + append(ICCBlackScaled.profile, 0, ICCBlackScaled.profile.length); + append("\nendstream\n"); + endobj(); + + // OutputIntent object + newobj(); + append("<<\n"); + append("/Type /OutputIntent\n"); + append("/S /GTS_PDFA1\n"); + append("/OutputCondition (sRGB IEC61966-2.1)\n"); + append("/OutputConditionIdentifier (sRGB IEC61966-2.1)\n"); + append("/Info (sRGB IEC61966-2.1)\n"); + append("/DestOutputProfile "); + append(objNumber - 1); + append(" 0 R\n"); + append(">>\n"); + endobj(); + + return objNumber; + } + + + private int addResourcesObject() throws Exception { + newobj(); + append("<<\n"); + + if (!extGState.equals("")) { + append(extGState); + } + if (fonts.size() > 0 || importedFonts.size() > 0) { + append("/Font\n"); + append("<<\n"); + for (String token : importedFonts) { + append(token); + if (token.equals("R")) { + append('\n'); + } + else { + append(' '); + } + } + for (Font font : fonts) { + append("/F"); + append(font.objNumber); + append(' '); + append(font.objNumber); + append(" 0 R\n"); + } + append(">>\n"); + } + + if (images.size() > 0) { + append("/XObject\n"); + append("<<\n"); + for (int i = 0; i < images.size(); i++) { + Image image = images.get(i); + append("/Im"); + append(image.objNumber); + append(' '); + append(image.objNumber); + append(" 0 R\n"); + } + append(">>\n"); + } + + if (groups.size() > 0) { + append("/Properties\n"); + append("<<\n"); + for (int i = 0; i < groups.size(); i++) { + OptionalContentGroup ocg = groups.get(i); + append("/OC"); + append(i + 1); + append(' '); + append(ocg.objNumber); + append(" 0 R\n"); + } + append(">>\n"); + } + + // String state = "/CA 0.5 /ca 0.5"; + if (states.size() > 0) { + append("/ExtGState <<\n"); + for (String state : states.keySet()) { + append("/GS"); + append(states.get(state)); + append(" << "); + append(state); + append(" >>\n"); + } + append(">>\n"); + } + + append(">>\n"); + endobj(); + return objNumber; + } + + + private int addPagesObject() throws Exception { + newobj(); + append("<<\n"); + append("/Type /Pages\n"); + append("/Kids [\n"); + for (int i = 0; i < pages.size(); i++) { + Page page = pages.get(i); + if (compliance == Compliance.PDF_UA) { + page.setStructElementsPageObjNumber(page.objNumber); + } + append(page.objNumber); + append(" 0 R\n"); + } + append("]\n"); + append("/Count "); + append(pages.size()); + append('\n'); + append(">>\n"); + endobj(); + return objNumber; + } + + + private int addInfoObject() throws Exception { + // Add the info object + newobj(); + append("<<\n"); + append("/Title <"); + append(toHex(title)); + append(">\n"); + append("/Author <"); + append(toHex(author)); + append(">\n"); + append("/Subject <"); + append(toHex(subject)); + append(">\n"); + append("/Keywords <"); + append(toHex(keywords)); + append(">\n"); + append("/Creator <"); + append(toHex(creator)); + append(">\n"); + append("/Producer ("); + append(producer); + append(")\n"); + append("/CreationDate (D:"); + append(creationDate); + append("Z)\n"); + append("/ModDate (D:"); + append(modDate); + append("Z)\n"); + append(">>\n"); + endobj(); + return objNumber; + } + + + private int addStructTreeRootObject() throws Exception { + newobj(); + append("<<\n"); + append("/Type /StructTreeRoot\n"); + append("/K [\n"); + for (int i = 0; i < pages.size(); i++) { + Page page = pages.get(i); + for (int j = 0; j < page.structures.size(); j++) { + append(page.structures.get(j).objNumber); + append(" 0 R\n"); + } + } + append("]\n"); + append("/ParentTree "); + append(objNumber + 1); + append(" 0 R\n"); + append(">>\n"); + endobj(); + return objNumber; + } + + + private void addStructElementObjects() throws Exception { + int structTreeRootObjNumber = objNumber + 1; + for (int i = 0; i < pages.size(); i++) { + Page page = pages.get(i); + structTreeRootObjNumber += page.structures.size(); + } + + for (int i = 0; i < pages.size(); i++) { + Page page = pages.get(i); + for (int j = 0; j < page.structures.size(); j++) { + newobj(); + StructElem element = page.structures.get(j); + element.objNumber = objNumber; + append("<<\n"); + append("/Type /StructElem\n"); + append("/S /"); + append(element.structure); + append("\n"); + append("/P "); + append(structTreeRootObjNumber); + append(" 0 R\n"); + append("/Pg "); + append(element.pageObjNumber); + append(" 0 R\n"); + if (element.annotation == null) { + append("/K "); + append(element.mcid); + append("\n"); + } + else { + append("/K <<\n"); + append("/Type /OBJR\n"); + append("/Obj "); + append(element.annotation.objNumber); + append(" 0 R\n"); + append(">>\n"); + } + if (element.language != null) { + append("/Lang ("); + append(element.language); + append(")\n"); + } + append("/Alt <"); + append(toHex(element.altDescription)); + append(">\n"); + append("/ActualText <"); + append(toHex(element.actualText)); + append(">\n"); + append(">>\n"); + endobj(); + } + } + } + + + private String toHex(String str) { + StringBuilder buf = new StringBuilder(); + if (str != null) { + buf.append("FEFF"); + for (int i = 0; i < str.length(); i++) { + buf.append(String.format("%04X", str.codePointAt(i))); + } + } + return buf.toString(); + } + + + private void addNumsParentTree() throws Exception { + newobj(); + append("<<\n"); + append("/Nums [\n"); + for (int i = 0; i < pages.size(); i++) { + Page page = pages.get(i); + append(i); + append(" [\n"); + for (int j = 0; j < page.structures.size(); j++) { + StructElem element = page.structures.get(j); + if (element.annotation == null) { + append(element.objNumber); + append(" 0 R\n"); + } + } + append("]\n"); + } + + int index = pages.size(); + for (int i = 0; i < pages.size(); i++) { + Page page = pages.get(i); + for (int j = 0; j < page.structures.size(); j++) { + StructElem element = page.structures.get(j); + if (element.annotation != null) { + append(index); + append(" "); + append(element.objNumber); + append(" 0 R\n"); + index++; + } + } + } + append("]\n"); + append(">>\n"); + endobj(); + } + + + private int addRootObject( + int structTreeRootObjNumber, int outlineDictNumber) throws Exception { + // Add the root object + newobj(); + append("<<\n"); + append("/Type /Catalog\n"); + + if (compliance == Compliance.PDF_UA) { + append("/Lang ("); + append(language); + append(")\n"); + + append("/StructTreeRoot "); + append(structTreeRootObjNumber); + append(" 0 R\n"); + + append("/MarkInfo <>\n"); + append("/ViewerPreferences <>\n"); + } + + if (pageLayout != null) { + append("/PageLayout /"); + append(pageLayout); + append("\n"); + } + + if (pageMode != null) { + append("/PageMode /"); + append(pageMode); + append("\n"); + } + + addOCProperties(); + + append("/Pages "); + append(pagesObjNumber); + append(" 0 R\n"); + + if (compliance == Compliance.PDF_A_1B || + compliance == Compliance.PDF_UA) { + append("/Metadata "); + append(metadataObjNumber); + append(" 0 R\n"); + + append("/OutputIntents ["); + append(outputIntentObjNumber); + append(" 0 R]\n"); + } + + if (outlineDictNumber > 0) { + append("/Outlines "); + append(outlineDictNumber); + append(" 0 R\n"); + } + + append(">>\n"); + endobj(); + return objNumber; + } + + + private void addPageBox(String boxName, Page page, float[] rect) throws Exception { + append("/"); + append(boxName); + append(" ["); + append(rect[0]); + append(' '); + append(page.height - rect[3]); + append(' '); + append(rect[2]); + append(' '); + append(page.height - rect[1]); + append("]\n"); + } + + + private void setDestinationObjNumbers() { + int numberOfAnnotations = 0; + for (int i = 0; i < pages.size(); i++) { + Page page = pages.get(i); + numberOfAnnotations += page.annots.size(); + } + for (int i = 0; i < pages.size(); i++) { + Page page = pages.get(i); + for (Destination destination : page.destinations) { + destination.pageObjNumber = + objNumber + numberOfAnnotations + i + 1; + destinations.put(destination.name, destination); + } + } + } + + + private void addAllPages(int resObjNumber) throws Exception { + + setDestinationObjNumbers(); + addAnnotDictionaries(); + + // Calculate the object number of the Pages object + pagesObjNumber = objNumber + pages.size() + 1; + + for (int i = 0; i < pages.size(); i++) { + Page page = pages.get(i); + + // Page object + newobj(); + page.objNumber = objNumber; + append("<<\n"); + append("/Type /Page\n"); + append("/Parent "); + append(pagesObjNumber); + append(" 0 R\n"); + append("/MediaBox [0.0 0.0 "); + append(page.width); + append(' '); + append(page.height); + append("]\n"); + + if (page.cropBox != null) { + addPageBox("CropBox", page, page.cropBox); + } + if (page.bleedBox != null) { + addPageBox("BleedBox", page, page.bleedBox); + } + if (page.trimBox != null) { + addPageBox("TrimBox", page, page.trimBox); + } + if (page.artBox != null) { + addPageBox("ArtBox", page, page.artBox); + } + + append("/Resources "); + append(resObjNumber); + append(" 0 R\n"); + + append("/Contents [ "); + for (Integer n : page.contents) { + append(n); + append(" 0 R "); + } + append("]\n"); + if (page.annots.size() > 0) { + append("/Annots [ "); + for (Annotation annot : page.annots) { + append(annot.objNumber); + append(" 0 R "); + } + append("]\n"); + } + + if (compliance == Compliance.PDF_UA) { + append("/Tabs /S\n"); + append("/StructParents "); + append(i); + append("\n"); + } + + append(">>\n"); + endobj(); + } + } + + + private void addPageContent(Page page) throws Exception { + ByteArrayOutputStream baos = + new ByteArrayOutputStream(); + DeflaterOutputStream dos = + new DeflaterOutputStream(baos, new Deflater()); + byte[] buf = page.buf.toByteArray(); + dos.write(buf, 0, buf.length); + dos.finish(); + page.buf = null; // Release the page content memory! + + newobj(); + append("<<\n"); + append("/Filter /FlateDecode\n"); + append("/Length "); + append(baos.size()); + append("\n"); + append(">>\n"); + append("stream\n"); + append(baos); + append("\nendstream\n"); + endobj(); + page.contents.add(objNumber); + } + +/* + // Use this method on systems that don't have Deflater stream or when troubleshooting. + private void addPageContent(Page page) throws Exception { + newobj(); + append("<<\n"); + append("/Length "); + append(page.buf.size()); + append("\n"); + append(">>\n"); + append("stream\n"); + append(page.buf); + append("\nendstream\n"); + endobj(); + page.buf = null; // Release the page content memory! + page.contents.add(objNumber); + } + + + private void addPageContent(Page page) throws Exception { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + new LZWEncode(page.buf.toByteArray(), baos); + page.buf = null; // Release the page content memory! + + newobj(); + append("<<\n"); + append("/Filter /LZWDecode\n"); + append("/Length "); + append(baos.size()); + append("\n"); + append(">>\n"); + append("stream\n"); + append(baos); + append("\nendstream\n"); + endobj(); + page.contents.add(objNumber); + } +*/ + + private int addAnnotationObject(Annotation annot, int index) + throws Exception { + newobj(); + annot.objNumber = objNumber; + append("<<\n"); + append("/Type /Annot\n"); + if (annot.fileAttachment != null) { + append("/Subtype /FileAttachment\n"); + append("/T ("); + append(annot.fileAttachment.title); + append(")\n"); + append("/Contents ("); + append(annot.fileAttachment.contents); + append(")\n"); + append("/FS "); + append(annot.fileAttachment.embeddedFile.objNumber); + append(" 0 R\n"); + append("/Name /"); + append(annot.fileAttachment.icon); + append("\n"); + } + else { + append("/Subtype /Link\n"); + } + append("/Rect ["); + append(annot.x1); + append(' '); + append(annot.y1); + append(' '); + append(annot.x2); + append(' '); + append(annot.y2); + append("]\n"); + append("/Border [0 0 0]\n"); + if (annot.uri != null) { + append("/F 4\n"); + append("/A <<\n"); + append("/S /URI\n"); + append("/URI ("); + append(annot.uri); + append(")\n"); + append(">>\n"); + } + else if (annot.key != null) { + Destination destination = destinations.get(annot.key); + if (destination != null) { + append("/F 4\n"); // No Zoom + append("/Dest ["); + append(destination.pageObjNumber); + append(" 0 R /XYZ 0 "); + append(destination.yPosition); + append(" 0]\n"); + } + } + if (index != -1) { + append("/StructParent "); + append(index++); + append("\n"); + } + append(">>\n"); + endobj(); + + return index; + } + + + private void addAnnotDictionaries() throws Exception { + int index = pages.size(); + for (int i = 0; i < pages.size(); i++) { + Page page = pages.get(i); + if (page.structures.size() > 0) { + for (int j = 0; j < page.structures.size(); j++) { + StructElem element = page.structures.get(j); + if (element.annotation != null) { + index = addAnnotationObject(element.annotation, index); + } + } + } + else if (page.annots.size() > 0) { + for (int j = 0; j < page.annots.size(); j++) { + Annotation annotation = page.annots.get(j); + if (annotation != null) { + addAnnotationObject(annotation, -1); + } + } + } + } + } + + + private void addOCProperties() throws Exception { + if (!groups.isEmpty()) { + StringBuilder buf = new StringBuilder(); + for (OptionalContentGroup ocg : this.groups) { + buf.append(' '); + buf.append(ocg.objNumber); + buf.append(" 0 R"); + } + + append("/OCProperties\n"); + append("<<\n"); + append("/OCGs ["); + append(buf.toString()); + append(" ]\n"); + append("/D <<\n"); + + append("/AS [\n"); + append("<< /Event /View /Category [/View] /OCGs ["); + append(buf.toString()); + append(" ] >>\n"); + append("<< /Event /Print /Category [/Print] /OCGs ["); + append(buf.toString()); + append(" ] >>\n"); + append("<< /Event /Export /Category [/Export] /OCGs ["); + append(buf.toString()); + append(" ] >>\n"); + append("]\n"); + + append("/Order [[ ()"); + append(buf.toString()); + append(" ]]\n"); + + append(">>\n"); + append(">>\n"); + } + } + + + public void addPage(Page page) throws Exception { + int n = pages.size(); + if (n > 0) { + addPageContent(pages.get(n - 1)); + } + pages.add(page); + } + + + /** + * Writes the PDF object to the output stream. + * Does not close the underlying output stream. + */ + public void flush() throws Exception { + flush(false); + } + + + /** + * Writes the PDF object to the output stream and closes it. + */ + public void close() throws Exception { + flush(true); + } + + + private void flush(boolean close) throws Exception { + if (pagesObjNumber == -1) { + addPageContent(pages.get(pages.size() - 1)); + addAllPages(addResourcesObject()); + addPagesObject(); + } + + int structTreeRootObjNumber = 0; + if (compliance == Compliance.PDF_UA) { + addStructElementObjects(); + structTreeRootObjNumber = addStructTreeRootObject(); + addNumsParentTree(); + } + + int outlineDictNum = 0; + if (toc != null && toc.getChildren() != null) { + List list = toc.toArrayList(); + outlineDictNum = addOutlineDict(toc); + for (int i = 1; i < list.size(); i++) { + Bookmark bookmark = list.get(i); + addOutlineItem(outlineDictNum, i, bookmark); + } + } + + int infoObjNumber = addInfoObject(); + int rootObjNumber = addRootObject(structTreeRootObjNumber, outlineDictNum); + + int startxref = byte_count; + + // Create the xref table + append("xref\n"); + append("0 "); + append(rootObjNumber + 1); + append('\n'); + + append("0000000000 65535 f \n"); + for (int i = 0; i < objOffset.size(); i++) { + int offset = objOffset.get(i); + String str = Integer.toString(offset); + for (int j = 0; j < 10 - str.length(); j++) { + append('0'); + } + append(str); + append(" 00000 n \n"); + } + append("trailer\n"); + append("<<\n"); + append("/Size "); + append(rootObjNumber + 1); + append('\n'); + + String id = (new Salsa20()).getID(); + append("/ID[<"); + append(id); + append("><"); + append(id); + append(">]\n"); + + append("/Info "); + append(infoObjNumber); + append(" 0 R\n"); + + append("/Root "); + append(rootObjNumber); + append(" 0 R\n"); + + append(">>\n"); + append("startxref\n"); + append(startxref); + append('\n'); + append("%%EOF\n"); + + os.flush(); + if (close) { + os.close(); + } + } + + + /** + * Set the "Title" document property of the PDF file. + * @param title The title of this document. + */ + public void setTitle(String title) { + this.title = title; + } + + + /** + * Set the "Author" document property of the PDF file. + * @param author The author of this document. + */ + public void setAuthor(String author) { + this.author = author; + } + + + /** + * Set the "Subject" document property of the PDF file. + * @param subject The subject of this document. + */ + public void setSubject(String subject) { + this.subject = subject; + } + + + public void setKeywords(String keywords) { + this.keywords = keywords; + } + + + public void setCreator(String creator) { + this.creator = creator; + } + + + public void setPageLayout(String pageLayout) { + this.pageLayout = pageLayout; + } + + + public void setPageMode(String pageMode) { + this.pageMode = pageMode; + } + + + protected void append(int num) throws IOException { + append(Integer.toString(num)); + } + + + protected void append(float val) throws IOException { + append(PDF.df.format(val)); + } + + + protected void append(String str) throws IOException { + int len = str.length(); + for (int i = 0; i < len; i++) { + os.write((byte) str.charAt(i)); + } + byte_count += len; + } + + + protected void append(char ch) throws IOException { + append((byte) ch); + } + + + protected void append(byte b) throws IOException { + os.write(b); + byte_count += 1; + } + + + protected void append(byte[] buf, int off, int len) throws IOException { + os.write(buf, off, len); + byte_count += len; + } + + + protected void append(ByteArrayOutputStream baos) throws IOException { + baos.writeTo(os); + byte_count += baos.size(); + } + + + /** + * Returns a list of objects of type PDFobj read from input stream. + * + * @param inputStream the PDF input stream. + * + * @return List the list of PDF objects. + */ + public Map read(InputStream inputStream) throws Exception { + + List objects = new ArrayList(); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + int ch; + while ((ch = inputStream.read()) != -1) { + baos.write(ch); + } + byte[] pdf = baos.toByteArray(); + + int xref = getStartXRef(pdf); + PDFobj obj1 = getObject(pdf, xref); + if (obj1.dict.get(0).equals("xref")) { + // Get the objects using xref table + getObjects1(pdf, obj1, objects); + } + else { + // Get the objects using XRef stream + getObjects2(pdf, obj1, objects); + } + + Map pdfObjects = new TreeMap(); + for (PDFobj obj : objects) { + if (obj.dict.contains("stream")) { + obj.setStream(pdf, obj.getLength(objects)); + if (obj.getValue("/Filter").equals("/FlateDecode")) { + Decompressor decompressor = new Decompressor(obj.stream); + obj.data = decompressor.getDecompressedData(); + } + else { + // Assume no compression. + obj.data = obj.stream; + } + } + + if (obj.getValue("/Type").equals("/ObjStm")) { + int first = Integer.valueOf(obj.getValue("/First")); + PDFobj o2 = getObject(obj.data, 0, first); + int count = o2.dict.size(); + for (int i = 0; i < count; i += 2) { + String num = o2.dict.get(i); + int off = Integer.valueOf(o2.dict.get(i + 1)); + int end = obj.data.length; + if (i <= count - 4) { + end = first + Integer.valueOf(o2.dict.get(i + 3)); + } + PDFobj o3 = getObject(obj.data, first + off, end); + o3.dict.add(0, "obj"); + o3.dict.add(0, "0"); + o3.dict.add(0, num); + pdfObjects.put(Integer.valueOf(num), o3); + } + } + else if (obj.getValue("/Type").equals("/XRef")) { + // Skip the stream XRef object. + } + else { + pdfObjects.put(obj.number, obj); + } + } + + return pdfObjects; + } + + + private boolean process( + PDFobj obj, StringBuilder sb1, byte[] buf, int off) { + String str = sb1.toString().trim(); + if (!str.equals("")) { + obj.dict.add(str); + } + sb1.setLength(0); + + if (str.equals("endobj")) { + return true; + } + else if (str.equals("stream")) { + obj.stream_offset = off; + if (buf[off] == '\n') { + obj.stream_offset += 1; + } + return true; + } + else if (str.equals("startxref")) { + return true; + } + return false; + } + + + private PDFobj getObject(byte[] buf, int off) { + return getObject(buf, off, buf.length); + } + + + private PDFobj getObject(byte[] buf, int off, int len) { + + PDFobj obj = new PDFobj(off); + StringBuilder token = new StringBuilder(); + + int p = 0; + char c1 = ' '; + boolean done = false; + while (!done && off < len) { + char c2 = (char) buf[off++]; + if (c1 == '\\') { + token.append(c2); + c1 = c2; + continue; + } + + if (c2 == '(') { + if (p == 0) { + done = process(obj, token, buf, off); + } + if (!done) { + token.append(c2); + c1 = c2; + ++p; + } + } + else if (c2 == ')') { + token.append(c2); + c1 = c2; + --p; + if (p == 0) { + done = process(obj, token, buf, off); + } + } + else if (c2 == 0x00 // Null + || c2 == 0x09 // Horizontal Tab + || c2 == 0x0A // Line Feed (LF) + || c2 == 0x0C // Form Feed + || c2 == 0x0D // Carriage Return (CR) + || c2 == 0x20) { // Space + done = process(obj, token, buf, off); + if (!done) { + c1 = ' '; + } + } + else if (c2 == '/') { + done = process(obj, token, buf, off); + if (!done) { + token.append(c2); + c1 = c2; + } + } + else if (c2 == '<' || c2 == '>' || c2 == '%') { + if (p > 0) { + token.append(c2); + c1 = c2; + } + else { + if (c2 != c1) { + done = process(obj, token, buf, off); + if (!done) { + token.append(c2); + c1 = c2; + } + } + else { + token.append(c2); + done = process(obj, token, buf, off); + if (!done) { + c1 = ' '; + } + } + } + } + else if (c2 == '[' || c2 == ']' || c2 == '{' || c2 == '}') { + if (p > 0) { + token.append(c2); + c1 = c2; + } + else { + done = process(obj, token, buf, off); + if (!done) { + obj.dict.add(String.valueOf(c2)); + c1 = c2; + } + } + } + else { + token.append(c2); + c1 = c2; + } + } + + return obj; + } + + + /** + * Converts an array of bytes to an integer. + * @param buf byte[] + * @return int + */ + private int toInt(byte[] buf, int off, int len) { + int i = 0; + for (int j = 0; j < len; j++) { + i |= buf[off + j] & 0xFF; + if (j < len - 1) { + i <<= 8; + } + } + return i; + } + + + private void getObjects1( + byte[] pdf, + PDFobj obj, + List objects) throws Exception { + + String xref = obj.getValue("/Prev"); + if (!xref.equals("")) { + getObjects1( + pdf, + getObject(pdf, Integer.valueOf(xref)), + objects); + } + + int i = 1; + while (true) { + String token = obj.dict.get(i++); + if (token.equals("trailer")) { + break; + } + + int n = Integer.valueOf(obj.dict.get(i++)); // Number of entries + for (int j = 0; j < n; j++) { + String offset = obj.dict.get(i++); // Object offset + String number = obj.dict.get(i++); // Generation number + String status = obj.dict.get(i++); // Status keyword + if (!status.equals("f")) { + PDFobj o2 = getObject(pdf, Integer.valueOf(offset)); + o2.number = Integer.valueOf(o2.dict.get(0)); + objects.add(o2); + } + } + } + + } + + + private void getObjects2( + byte[] pdf, + PDFobj obj, + List objects) throws Exception { + + String prev = obj.getValue("/Prev"); + if (!prev.equals("")) { + getObjects2( + pdf, + getObject(pdf, Integer.valueOf(prev)), + objects); + } + + obj.setStream(pdf, obj.getLength(objects)); + if (obj.getValue("/Filter").equals("/FlateDecode")) { + Decompressor decompressor = new Decompressor(obj.stream); + obj.data = decompressor.getDecompressedData(); + } + else { + // Assume no compression. + obj.data = obj.stream; + } + + int p1 = 0; // Predictor byte + int f1 = 0; // Field 1 + int f2 = 0; // Field 2 + int f3 = 0; // Field 3 + for (int i = 0; i < obj.dict.size(); i++) { + String token = obj.dict.get(i); + if (token.equals("/Predictor")) { + if (obj.dict.get(i + 1).equals("12")) { + p1 = 1; + } + } + + if (token.equals("/W")) { + // "/W [ 1 3 1 ]" + f1 = Integer.valueOf(obj.dict.get(i + 2)); + f2 = Integer.valueOf(obj.dict.get(i + 3)); + f3 = Integer.valueOf(obj.dict.get(i + 4)); + } + } + + int n = p1 + f1 + f2 + f3; // Number of bytes per entry + byte[] entry = new byte[n]; + for (int i = 0; i < obj.data.length; i += n) { + // Apply the 'Up' filter. + for (int j = 0; j < n; j++) { + entry[j] += obj.data[i + j]; + } + + // Process the entries in a cross-reference stream + // Page 51 in PDF32000_2008.pdf + if (entry[p1] == 1) { // Type 1 entry + PDFobj o2 = getObject(pdf, toInt(entry, p1 + f1, f2)); + o2.number = Integer.valueOf(o2.dict.get(0)); + objects.add(o2); + } + } + + } + + + private int getStartXRef(byte[] buf) { + StringBuilder sb = new StringBuilder(); + for (int i = (buf.length - 10); i > 10; i--) { + if (buf[i] == 's' && + buf[i + 1] == 't' && + buf[i + 2] == 'a' && + buf[i + 3] == 'r' && + buf[i + 4] == 't' && + buf[i + 5] == 'x' && + buf[i + 6] == 'r' && + buf[i + 7] == 'e' && + buf[i + 8] == 'f') { + i += 10; // Skip over "startxref" and the first EOL character + while (buf[i] < 0x30) { // Skip over possible second EOL character and spaces + i += 1; + } + while (Character.isDigit((char) buf[i])) { + sb.append((char) buf[i]); + i += 1; + } + break; + } + } + return Integer.valueOf(sb.toString()); + } + + + public int addOutlineDict(Bookmark toc) throws Exception { + int numOfChildren = getNumOfChildren(0, toc); + newobj(); + append("<<\n"); + append("/Type /Outlines\n"); + append("/First "); + append(objNumber + 1); + append(" 0 R\n"); + append("/Last "); + append(objNumber + numOfChildren); + append(" 0 R\n"); + append("/Count "); + append(numOfChildren); + append("\n"); + append(">>\n"); + endobj(); + return objNumber; + } + + + public void addOutlineItem(int parent, int i, Bookmark bm1) throws Exception { + + int prev = (bm1.getPrevBookmark() == null) ? 0 : parent + (i - 1); + int next = (bm1.getNextBookmark() == null) ? 0 : parent + (i + 1); + + int first = 0; + int last = 0; + int count = 0; + if (bm1.getChildren() != null && bm1.getChildren().size() > 0) { + first = parent + bm1.getFirstChild().objNumber; + last = parent + bm1.getLastChild().objNumber; + count = (-1) * getNumOfChildren(0, bm1); + } + + newobj(); + append("<<\n"); + append("/Title <"); + append(toHex(bm1.getTitle())); + append(">\n"); + append("/Parent "); + append(parent); + append(" 0 R\n"); + if (prev > 0) { + append("/Prev "); + append(prev); + append(" 0 R\n"); + } + if (next > 0) { + append("/Next "); + append(next); + append(" 0 R\n"); + } + if (first > 0) { + append("/First "); + append(first); + append(" 0 R\n"); + } + if (last > 0) { + append("/Last "); + append(last); + append(" 0 R\n"); + } + if (count != 0) { + append("/Count "); + append(count); + append("\n"); + } + append("/F 4\n"); // No Zoom + append("/Dest ["); + append(bm1.getDestination().pageObjNumber); + append(" 0 R /XYZ 0 "); + append(bm1.getDestination().yPosition); + append(" 0]\n"); + append(">>\n"); + endobj(); + } + + + private int getNumOfChildren(int numOfChildren, Bookmark bm1) { + List children = bm1.getChildren(); + if (children != null) { + for (Bookmark bm2 : children) { + numOfChildren = getNumOfChildren(++numOfChildren, bm2); + } + } + return numOfChildren; + } + + + public void removePages( + Set pageNumbers, + Map objects) throws Exception { + Set pageObjectNumbers = new HashSet(); + List temp = new ArrayList(); + PDFobj pages = getPagesObject(objects); + List dict = pages.getDict(); + for (int i = 0; i < dict.size(); i++) { + if (dict.get(i).equals("/Kids")) { + temp.add(dict.get(i++)); + temp.add(dict.get(i++)); + int pageNumber = 1; + while (!dict.get(i).equals("]")) { + if (!pageNumbers.contains(pageNumber)) { + temp.add(dict.get(i++)); + temp.add(dict.get(i++)); + temp.add(dict.get(i++)); + } + else { + pageObjectNumbers.add( + Integer.valueOf(dict.get(i++))); + i++; + i++; + } + pageNumber++; + } + temp.add(dict.get(i)); + } + else if (dict.get(i).equals("/Count")) { + temp.add(dict.get(i++)); + int count = Integer.valueOf(dict.get(i)) - pageNumbers.size(); + temp.add(String.valueOf(count)); + } + else { + temp.add(dict.get(i)); + } + } + pages.setDict(temp); + Iterator iter = pageObjectNumbers.iterator(); + while (iter.hasNext()) { + objects.remove(iter.next()); + } + } + + + public void addObjects(Map objects) throws Exception { + this.pagesObjNumber = Integer.valueOf(getPagesObject(objects).dict.get(0)); + addObjectsToPDF(objects); + } + + + public PDFobj getPagesObject( + Map objects) throws Exception { + for (PDFobj obj : objects.values()) { + if (obj.getValue("/Type").equals("/Pages") && + obj.getValue("/Parent").equals("")) { + return obj; + } + } + return null; + } + + + public List getPageObjects( + Map objects) throws Exception { + List pages = new ArrayList(); + getPageObjects(getPagesObject(objects), objects, pages); + return pages; + } + + + private void getPageObjects( + PDFobj pdfObj, + Map objects, + List pages) throws Exception { + List kids = pdfObj.getObjectNumbers("/Kids"); + for (Integer number : kids) { + PDFobj obj = objects.get(number); + if (isPageObject(obj)) { + pages.add(obj); + } + else { + getPageObjects(obj, objects, pages); + } + } + } + + + private boolean isPageObject(PDFobj obj) { + boolean isPage = false; + for (int i = 0; i < obj.dict.size(); i++) { + if (obj.dict.get(i).equals("/Type") && + obj.dict.get(i + 1).equals("/Page")) { + isPage = true; + } + } + return isPage; + } + + + private String getExtGState( + PDFobj resources, Map objects) { + StringBuilder buf = new StringBuilder(); + List dict = resources.getDict(); + int level = 0; + for (int i = 0; i < dict.size(); i++) { + if (dict.get(i).equals("/ExtGState")) { + buf.append("/ExtGState << "); + ++i; + ++level; + while (level > 0) { + String token = dict.get(++i); + if (token.equals("<<")) { + ++level; + } + else if (token.equals(">>")) { + --level; + } + buf.append(token); + if (level > 0) { + buf.append(' '); + } + else { + buf.append('\n'); + } + } + break; + } + } + return buf.toString(); + } + + + private List removeTheNameEntry(List dict) { + List cleanDict = new ArrayList(); + for (int i = 0; i < dict.size(); i++) { + if (dict.get(i).equals("/Name")) { + i += 1; + } + else { + cleanDict.add(dict.get(i)); + } + } + return cleanDict; + } + + + private List getFontObjects( + PDFobj resources, Map objects) { + List fonts = new ArrayList(); + List dict = resources.getDict(); + for (int i = 0; i < dict.size(); i++) { + if (dict.get(i).equals("/Font")) { + if (!dict.get(i + 2).equals(">>")) { + PDFobj fontObj = objects.get(Integer.valueOf(dict.get(i + 3))); + fontObj.setDict(removeTheNameEntry(fontObj.getDict())); + fonts.add(fontObj); + } + } + } + + if (fonts.size() == 0) { + return null; + } + + int i = 4; + while (true) { + if (dict.get(i).equals("/Font")) { + i += 2; + break; + } + i += 1; + } + while (!dict.get(i).equals(">>")) { + importedFonts.add(dict.get(i)); + i += 1; + } + + return fonts; + } + + + private List getDescendantFonts( + PDFobj font, Map objects) { + List descendantFonts = new ArrayList(); + List dict = font.getDict(); + for (int i = 0; i < dict.size(); i++) { + if (dict.get(i).equals("/DescendantFonts")) { + if (!dict.get(i + 2).equals("]")) { + descendantFonts.add(objects.get(Integer.valueOf(dict.get(i + 2)))); + } + } + } + return descendantFonts; + } + + + private PDFobj getObject( + String name, PDFobj obj, Map objects) { + List dict = obj.getDict(); + for (int i = 0; i < dict.size(); i++) { + if (dict.get(i).equals(name)) { + return objects.get(Integer.valueOf(dict.get(i + 1))); + } + } + return null; + } + + + public void addResourceObjects(Map objects) throws Exception { + Map resources = new TreeMap(); + + List pages = getPageObjects(objects); + for (PDFobj page : pages) { + PDFobj resObj = page.getResourcesObject(objects); + List fonts = getFontObjects(resObj, objects); + if (fonts != null) { + for (PDFobj font : fonts) { + resources.put(font.getNumber(), font); + PDFobj obj = getObject("/ToUnicode", font, objects); + if (obj != null) { + resources.put(obj.getNumber(), obj); + } + List descendantFonts = getDescendantFonts(font, objects); + for (PDFobj descendantFont : descendantFonts) { + resources.put(descendantFont.getNumber(), descendantFont); + obj = getObject("/FontDescriptor", descendantFont, objects); + resources.put(obj.getNumber(), obj); + obj = getObject("/FontFile2", obj, objects); + resources.put(obj.getNumber(), obj); + } + } + } + extGState = getExtGState(resObj, objects); + } + + if (resources.size() > 0) { + addObjectsToPDF(resources); + } + } + + + private void addObjectsToPDF(Map objects) throws Exception { + + int maxObjNumber = Collections.max(objects.keySet()); + for (int i = 1; i <= maxObjNumber; i++) { + if (objects.get(i) == null) { + PDFobj obj = new PDFobj(); + obj.setNumber(i); + objects.put(obj.number, obj); + } + } + + for (PDFobj obj : objects.values()) { + objNumber = obj.number; + objOffset.add(byte_count); + + if (obj.offset == 0) { + append(obj.number); + append(" 0 obj\n"); + if (obj.dict != null) { + for (int i = 0; i < obj.dict.size(); i++) { + append(obj.dict.get(i)); + append(' '); + } + } + if (obj.stream != null) { + if (obj.dict.size() == 0) { + append("<< /Length "); + append(obj.stream.length); + append(" >>"); + } + append("\nstream\n"); + for (int i = 0; i < obj.stream.length; i++) { + append(obj.stream[i]); + } + append("\nendstream\n"); + } + append("endobj\n"); + } + else { + boolean link = false; + int n = obj.dict.size(); + String token = null; + for (int i = 0; i < n; i++) { + token = obj.dict.get(i); + append(token); + if (token.startsWith("(http:")) { + link = true; + } + else if (link == true && token.endsWith(")")) { + link = false; + } + if (i < (n - 1)) { + if (!link) { + append(' '); + } + } + else { + append('\n'); + } + } + if (obj.stream != null) { + for (int i = 0; i < obj.stream.length; i++) { + append(obj.stream[i]); + } + append("\nendstream\n"); + } + if (!token.equals("endobj")) { + append("endobj\n"); + } + } + } + + } + +} // End of PDF.java diff --git a/PDFJet/src/main/java/com/pdfjet/PDFobj.java b/PDFJet/src/main/java/com/pdfjet/PDFobj.java new file mode 100644 index 0000000..b3e21c8 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/PDFobj.java @@ -0,0 +1,633 @@ +/** + * PDFobj.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + +import java.io.*; +import java.util.*; + + +/** + * Used to create Java or .NET objects that represent the objects in PDF document. + * See the PDF specification for more information. + * + */ +public class PDFobj { + + protected int number; // The object number + protected int offset; // The object offset + protected List dict; + protected int stream_offset; + protected byte[] stream; // The compressed stream + protected byte[] data; // The decompressed data + protected int gsNumber = -1; + + + /** + * Used to create Java or .NET objects that represent the objects in PDF document. + * See the PDF specification for more information. + * Also see Example_19. + * + * @param offset the object offset in the offsets table. + */ + public PDFobj(int offset) { + this.offset = offset; + this.dict = new ArrayList(); + } + + + protected PDFobj() { + this.dict = new ArrayList(); + } + + + public int getNumber() { + return this.number; + } + + + /** + * Returns the object dictionary. + * + * @return the object dictionary. + */ + public List getDict() { + return this.dict; + } + + + public void setDict(List dict) { + this.dict = dict; + } + + + /** + * Returns the uncompressed stream data. + * + * @return the uncompressed stream data. + */ + public byte[] getData() { + return this.data; + } + + + protected void setStream(byte[] pdf, int length) { + stream = new byte[length]; + System.arraycopy(pdf, this.stream_offset, stream, 0, length); + } + + + protected void setStream(byte[] stream) { + this.stream = stream; + } + + + protected void setNumber(int number) { + this.number = number; + } + + + /** + * Returns the dictionary value for the specified key. + * + * @param key the specified key. + * + * @return the value. + */ + public String getValue(String key) { + for (int i = 0; i < dict.size(); i++) { + String token = dict.get(i); + if (token.equals(key)) { + if (dict.get(i + 1).equals("<<")) { + StringBuilder buffer = new StringBuilder(); + buffer.append("<<"); + buffer.append(" "); + i += 2; + while (!dict.get(i).equals(">>")) { + buffer.append(dict.get(i)); + buffer.append(" "); + i += 1; + } + buffer.append(">>"); + return buffer.toString(); + } + if (dict.get(i + 1).equals("[")) { + StringBuilder buffer = new StringBuilder(); + buffer.append("["); + buffer.append(" "); + i += 2; + while (!dict.get(i).equals("]")) { + buffer.append(dict.get(i)); + buffer.append(" "); + i += 1; + } + buffer.append("]"); + return buffer.toString(); + } + return dict.get(i + 1); + } + } + return ""; + } + + + protected List getObjectNumbers(String key) { + List numbers = new ArrayList(); + for (int i = 0; i < dict.size(); i++) { + String token = dict.get(i); + if (token.equals(key)) { + String str = dict.get(++i); + if (str.equals("[")) { + while (true) { + str = dict.get(++i); + if (str.equals("]")) { + break; + } + numbers.add(Integer.valueOf(str)); + ++i; // 0 + ++i; // R + } + } + else { + numbers.add(Integer.valueOf(str)); + } + break; + } + } + return numbers; + } + + + public float[] getPageSize() { + for (int i = 0; i < dict.size(); i++) { + if (dict.get(i).equals("/MediaBox")) { + return new float[] { + Float.valueOf(dict.get(i + 4)), + Float.valueOf(dict.get(i + 5)) }; + } + } + return Letter.PORTRAIT; + } + + + protected int getLength(List objects) { + for (int i = 0; i < dict.size(); i++) { + String token = dict.get(i); + if (token.equals("/Length")) { + int number = Integer.valueOf(dict.get(i + 1)); + if (dict.get(i + 2).equals("0") && + dict.get(i + 3).equals("R")) { + return getLength(objects, number); + } + else { + return number; + } + } + } + return 0; + } + + + protected int getLength(List objects, int number) { + for (PDFobj obj : objects) { + if (obj.number == number) { + return Integer.valueOf(obj.dict.get(3)); + } + } + return 0; + } + + + public PDFobj getContentsObject(Map objects) { + for (int i = 0; i < dict.size(); i++) { + if (dict.get(i).equals("/Contents")) { + if (dict.get(i + 1).equals("[")) { + return objects.get(Integer.valueOf(dict.get(i + 2))); + } + return objects.get(Integer.valueOf(dict.get(i + 1))); + } + } + return null; + } + + + public PDFobj getResourcesObject(Map objects) { + for (int i = 0; i < dict.size(); i++) { + if (dict.get(i).equals("/Resources")) { + String token = dict.get(i + 1); + if (token.equals("<<")) { + PDFobj obj = new PDFobj(); + obj.dict.add("0"); + obj.dict.add("0"); + obj.dict.add("obj"); + obj.dict.add(token); + int level = 1; + i++; + while (i < dict.size() && level > 0) { + token = dict.get(i); + obj.dict.add(token); + if (token.equals("<<")) { + level++; + } + else if (token.equals(">>")) { + level--; + } + i++; + } + return obj; + } + return objects.get(Integer.valueOf(token)); + } + } + return null; + } + +/* +TODO: Test well this method and use instead of the method above. + public PDFobj getResourcesObject(Map objects) { + for (int i = 0; i < dict.size(); i++) { + if (dict.get(i).equals("/Resources")) { + String token = dict.get(i + 1); + if (token.equals("<<")) { + return this; + } + return objects.get(Integer.valueOf(token)); + } + } + return null; + } +*/ + + public Font addResource(CoreFont coreFont, Map objects) { + Font font = new Font(coreFont); + font.fontID = font.name.replace('-', '_').toUpperCase(); + + PDFobj obj = new PDFobj(); + obj.number = Collections.max(objects.keySet()) + 1; + obj.dict.add("<<"); + obj.dict.add("/Type"); + obj.dict.add("/Font"); + obj.dict.add("/Subtype"); + obj.dict.add("/Type1"); + obj.dict.add("/BaseFont"); + obj.dict.add("/" + font.name); + if (!font.name.equals("Symbol") && !font.name.equals("ZapfDingbats")) { + obj.dict.add("/Encoding"); + obj.dict.add("/WinAnsiEncoding"); + } + obj.dict.add(">>"); + + objects.put(obj.number, obj); + + for (int i = 0; i < dict.size(); i++) { + if (dict.get(i).equals("/Resources")) { + String token = dict.get(++i); + if (token.equals("<<")) { // Direct resources object + addFontResource(this, objects, font.fontID, obj.number); + } + else if (Character.isDigit(token.charAt(0))) { // Indirect resources object + addFontResource(objects.get(Integer.valueOf(token)), objects, font.fontID, obj.number); + } + } + } + + return font; + } + + + private void addFontResource( + PDFobj obj, Map objects, String fontID, int number) { + + boolean fonts = false; + for (int i = 0; i < obj.dict.size(); i++) { + if (obj.dict.get(i).equals("/Font")) { + fonts = true; + } + } + if (!fonts) { + for (int i = 0; i < obj.dict.size(); i++) { + if (obj.dict.get(i).equals("/Resources")) { + obj.dict.add(i + 2, "/Font"); + obj.dict.add(i + 3, "<<"); + obj.dict.add(i + 4, ">>"); + break; + } + } + } + + for (int i = 0; i < obj.dict.size(); i++) { + if (obj.dict.get(i).equals("/Font")) { + String token = obj.dict.get(i + 1); + if (token.equals("<<")) { + obj.dict.add(i + 2, "/" + fontID); + obj.dict.add(i + 3, String.valueOf(number)); + obj.dict.add(i + 4, "0"); + obj.dict.add(i + 5, "R"); + return; + } + else if (Character.isDigit(token.charAt(0))) { + PDFobj o2 = objects.get(Integer.valueOf(token)); + for (int j = 0; j < o2.dict.size(); j++) { + if (o2.dict.get(j).equals("<<")) { + o2.dict.add(j + 1, "/" + fontID); + o2.dict.add(j + 2, String.valueOf(number)); + o2.dict.add(j + 3, "0"); + o2.dict.add(j + 4, "R"); + return; + } + } + } + } + } + } + + + private void insertNewObject( + List dict, List list, String type) { + for (String token : dict) { + if (token.equals(list.get(0))) { + return; + } + } + for (int i = 0; i < dict.size(); i++) { + if (dict.get(i).equals(type)) { + dict.addAll(i + 2, list); + return; + } + } + if (dict.get(3).equals("<<")) { + dict.addAll(4, list); + return; + } + } + + + private void addResource( + String type, PDFobj obj, Map objects, int objNumber) { + String tag = type.equals("/Font") ? "/F" : "/Im"; + String number = String.valueOf(objNumber); + List list = Arrays.asList(tag + number, number, "0", "R"); + for (int i = 0; i < obj.dict.size(); i++) { + if (obj.dict.get(i).equals(type)) { + String token = obj.dict.get(i + 1); + if (token.equals("<<")) { + insertNewObject(obj.dict, list, type); + } + else { + insertNewObject(objects.get(Integer.valueOf(token)).dict, list, type); + } + return; + } + } + + // Handle the case where the page originally does not have any font resources. + list = Arrays.asList(type, "<<", tag + number, number, "0", "R", ">>"); + for (int i = 0; i < obj.dict.size(); i++) { + if (obj.dict.get(i).equals("/Resources")) { + obj.dict.addAll(i + 2, list); + return; + } + } + for (int i = 0; i < obj.dict.size(); i++) { + if (obj.dict.get(i).equals("<<")) { + obj.dict.addAll(i + 1, list); + return; + } + } + } + + + public void addResource(Image image, Map objects) { + for (int i = 0; i < dict.size(); i++) { + if (dict.get(i).equals("/Resources")) { + String token = dict.get(i + 1); + if (token.equals("<<")) { // Direct resources object + addResource("/XObject", this, objects, image.objNumber); + } + else { // Indirect resources object + addResource("/XObject", objects.get(Integer.valueOf(token)), objects, image.objNumber); + } + return; + } + } + } + + + public void addResource(Font font, Map objects) { + for (int i = 0; i < dict.size(); i++) { + if (dict.get(i).equals("/Resources")) { + String token = dict.get(i + 1); + if (token.equals("<<")) { // Direct resources object + addResource("/Font", this, objects, font.objNumber); + } + else { // Indirect resources object + addResource("/Font", objects.get(Integer.valueOf(token)), objects, font.objNumber); + } + return; + } + } + } + + + public void addContent(byte[] content, Map objects) { + PDFobj obj = new PDFobj(); + obj.setNumber(Collections.max(objects.keySet()) + 1); + obj.setStream(content); + objects.put(obj.getNumber(), obj); + + String objNumber = String.valueOf(obj.number); + for (int i = 0; i < dict.size(); i++) { + if (dict.get(i).equals("/Contents")) { + i += 1; + String token = dict.get(i); + if (token.equals("[")) { + // Array of content objects + while (true) { + i += 1; + token = dict.get(i); + if (token.equals("]")) { + dict.add(i, "R"); + dict.add(i, "0"); + dict.add(i, objNumber); + return; + } + i += 2; // Skip the 0 and R + } + } + else { + // Single content object + PDFobj obj2 = objects.get(Integer.valueOf(token)); + if (obj2.data == null && obj2.stream == null) { + // This is not a stream object! + for (int j = 0; j < obj2.dict.size(); j++) { + if (obj2.dict.get(j).equals("]")) { + obj2.dict.add(j, "R"); + obj2.dict.add(j, "0"); + obj2.dict.add(j, objNumber); + return; + } + } + } + dict.add(i, "["); + dict.add(i + 4, "]"); + dict.add(i + 4, "R"); + dict.add(i + 4, "0"); + dict.add(i + 4, objNumber); + return; + } + } + } + } + + + /** + * Adds new content object before the existing content objects. + * The original code was provided by Stefan Ostermann author of ScribMaster and HandWrite Pro. + * Additional code to handle PDFs with indirect array of stream objects was written by EDragoev. + * + * @param content + * @param objects + */ + public void addPrefixContent(byte[] content, Map objects) { + PDFobj obj = new PDFobj(); + obj.setNumber(Collections.max(objects.keySet()) + 1); + obj.setStream(content); + objects.put(obj.getNumber(), obj); + + String objNumber = String.valueOf(obj.number); + for (int i = 0; i < dict.size(); i++) { + if (dict.get(i).equals("/Contents")) { + i += 1; + String token = dict.get(i); + if (token.equals("[")) { + // Array of content object streams + i += 1; + dict.add(i, "R"); + dict.add(i, "0"); + dict.add(i, objNumber); + return; + } + else { + // Single content object + PDFobj obj2 = objects.get(Integer.valueOf(token)); + if (obj2.data == null && obj2.stream == null) { + // This is not a stream object! + for (int j = 0; j < obj2.dict.size(); j++) { + if (obj2.dict.get(j).equals("[")) { + j += 1; + obj2.dict.add(j, "R"); + obj2.dict.add(j, "0"); + obj2.dict.add(j, objNumber); + return; + } + } + } + dict.add(i, "["); + dict.add(i + 4, "]"); + i += 1; + dict.add(i, "R"); + dict.add(i, "0"); + dict.add(i, objNumber); + return; + } + } + } + } + + + private int getMaxGSNumber(PDFobj obj) { + List numbers = new ArrayList(); + for (String token : obj.dict) { + if (token.startsWith("/GS")) { + numbers.add(Integer.valueOf(token.substring(3))); + } + } + if (numbers.isEmpty()) { + return 0; + } + return Collections.max(numbers); + } + + + public void setGraphicsState(GraphicsState gs, Map objects) { + PDFobj obj = null; + int index = -1; + for (int i = 0; i < dict.size(); i++) { + if (dict.get(i).equals("/Resources")) { + String token = dict.get(i + 1); + if (token.equals("<<")) { + obj = this; + index = i + 2; + } + else { + obj = objects.get(Integer.valueOf(token)); + for (int j = 0; j < obj.dict.size(); j++) { + if (obj.dict.get(j).equals("<<")) { + index = j + 1; + break; + } + } + } + break; + } + } + + gsNumber = getMaxGSNumber(obj); + if (gsNumber == 0) { // No existing ExtGState dictionary + obj.dict.add(index, "/ExtGState"); // Add ExtGState dictionary + obj.dict.add(++index, "<<"); + } + else { + while (index < obj.dict.size()) { + String token = obj.dict.get(index); + if (token.equals("/ExtGState")) { + index += 1; + break; + } + index += 1; + } + } + obj.dict.add(++index, "/GS" + String.valueOf(gsNumber + 1)); + obj.dict.add(++index, "<<"); + obj.dict.add(++index, "/CA"); + obj.dict.add(++index, String.valueOf(gs.get_CA())); + obj.dict.add(++index, "/ca"); + obj.dict.add(++index, String.valueOf(gs.get_ca())); + obj.dict.add(++index, ">>"); + if (gsNumber == 0) { + obj.dict.add(++index, ">>"); + } + + StringBuilder buf = new StringBuilder(); + buf.append("q\n"); + buf.append("/GS" + String.valueOf(gsNumber + 1) + " gs\n"); + addPrefixContent(buf.toString().getBytes(), objects); + } + +} diff --git a/PDFJet/src/main/java/com/pdfjet/PNGImage.java b/PDFJet/src/main/java/com/pdfjet/PNGImage.java new file mode 100644 index 0000000..f0c71c9 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/PNGImage.java @@ -0,0 +1,948 @@ +/** + * PNGImage.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + +import java.io.*; +import java.util.*; + + +/** + * Used to embed PNG images in the PDF document. + *

+ * Please note: + *

+ * Interlaced images are not supported. + *

+ * To convert interlaced image to non-interlaced image use OptiPNG: + *

+ * optipng -i0 -o7 myimage.png + */ +public class PNGImage { + + int w; // Image width in pixels + int h; // Image height in pixels + + byte[] data; // The compressed data in the IDAT chunk + byte[] inflated; // The decompressed image data + byte[] image; // The reconstructed image data + byte[] deflated; // The deflated reconstructed image data + byte[] rgb; // The palette data + byte[] alphaForPalette; // The alpha for the palette data + byte[] deflatedAlpha; // The deflated alpha channel data + + private byte bitDepth = 8; + private byte colorType = 0; + + + /** + * Used to embed PNG images in the PDF document. + * + */ + public PNGImage(InputStream inputStream) throws Exception { + validatePNG(inputStream); + + List chunks = new ArrayList(); + processPNG(chunks, inputStream); + + for (int i = 0; i < chunks.size(); i++) { + Chunk chunk = chunks.get(i); + if (chunk.type[0] == 'I' + && chunk.type[1] == 'H' + && chunk.type[2] == 'D' + && chunk.type[3] == 'R') { + + this.w = toIntValue(chunk.getData(), 0); // Width + this.h = toIntValue(chunk.getData(), 4); // Height + this.bitDepth = chunk.getData()[8]; // Bit Depth + this.colorType = chunk.getData()[9]; // Color Type + + // System.out.println( + // "Bit Depth == " + chunk.getData()[8]); + // System.out.println( + // "Color Type == " + chunk.getData()[9]); + // System.out.println(chunk.getData()[10]); + // System.out.println(chunk.getData()[11]); + // System.out.println(chunk.getData()[12]); + + if (chunk.getData()[12] == 1) { + System.out.println("Interlaced PNG images are not supported.\nConvert the image using OptiPNG:\noptipng -i0 -o7 myimage.png\n"); + } + } + else if (chunk.type[0] == 'I' + && chunk.type[1] == 'D' + && chunk.type[2] == 'A' + && chunk.type[3] == 'T') { + data = appendIdatChunk(data, chunk.getData()); + } + else if (chunk.type[0] == 'P' + && chunk.type[1] == 'L' + && chunk.type[2] == 'T' + && chunk.type[3] == 'E') { + rgb = chunk.getData(); + if (rgb.length % 3 != 0) { + throw new Exception("Incorrect palette length."); + } + } + else if (chunk.type[0] == 'g' + && chunk.type[1] == 'A' + && chunk.type[2] == 'M' + && chunk.type[3] == 'A') { + // TODO: + // System.out.println("gAMA chunk found!"); + } + else if (chunk.type[0] == 't' + && chunk.type[1] == 'R' + && chunk.type[2] == 'N' + && chunk.type[3] == 'S') { + // System.out.println("tRNS chunk found!"); + if (colorType == 3) { + alphaForPalette = new byte[this.w * this.h]; + Arrays.fill(alphaForPalette, (byte) 0xff); + byte[] alpha = chunk.getData(); + for (int j = 0; j < alpha.length; j++) { + alphaForPalette[j] = alpha[j]; + } + } + } + else if (chunk.type[0] == 'c' + && chunk.type[1] == 'H' + && chunk.type[2] == 'R' + && chunk.type[3] == 'M') { + // TODO: + // System.out.println("cHRM chunk found!"); + } + else if (chunk.type[0] == 's' + && chunk.type[1] == 'B' + && chunk.type[2] == 'I' + && chunk.type[3] == 'T') { + // TODO: + // System.out.println("sBIT chunk found!"); + } + else if (chunk.type[0] == 'b' + && chunk.type[1] == 'K' + && chunk.type[2] == 'G' + && chunk.type[3] == 'D') { + // TODO: + // System.out.println("bKGD chunk found!"); + } + + } + + inflated = getDecompressedData(); + + if (colorType == 0) { + // Grayscale Image + if (bitDepth == 16) { + image = getImageColorType0BitDepth16(); + } + else if (bitDepth == 8) { + image = getImageColorType0BitDepth8(); + } + else if (bitDepth == 4) { + image = getImageColorType0BitDepth4(); + } + else if (bitDepth == 2) { + image = getImageColorType0BitDepth2(); + } + else if (bitDepth == 1) { + image = getImageColorType0BitDepth1(); + } + else { + throw new Exception("Image with unsupported bit depth == " + bitDepth); + } + } + else if (colorType == 6) { + if (bitDepth == 8) { + image = getImageColorType6BitDepth8(); + } + else { + throw new Exception("Image with unsupported bit depth == " + bitDepth); + } + } + else { + // Color Image + if (rgb == null) { + // Trucolor Image + if (bitDepth == 16) { + image = getImageColorType2BitDepth16(); + } + else { + image = getImageColorType2BitDepth8(); + } + } + else { + // Indexed Image + if (bitDepth == 8) { + image = getImageColorType3BitDepth8(); + } + else if (bitDepth == 4) { + image = getImageColorType3BitDepth4(); + } + else if (bitDepth == 2) { + image = getImageColorType3BitDepth2(); + } + else if (bitDepth == 1) { + image = getImageColorType3BitDepth1(); + } + else { + throw new Exception("Image with unsupported bit depth == " + bitDepth); + } + } + } + + deflated = deflateReconstructedData(); + } + + + public int getWidth() { + return this.w; + } + + + public int getHeight() { + return this.h; + } + + + public int getColorType() { + return this.colorType; + } + + + public int getBitDepth() { + return this.bitDepth; + } + + + public byte[] getData() { + return this.deflated; + } + + + public byte[] getAlpha() { + return this.deflatedAlpha; + } + + + private void processPNG( + List< Chunk> chunks, InputStream inputStream) + throws Exception { + + while (true) { + Chunk chunk = getChunk(inputStream); + chunks.add(chunk); + if (chunk.type[0] == 'I' + && chunk.type[1] == 'E' + && chunk.type[2] == 'N' + && chunk.type[3] == 'D') { + break; + } + } + + } + + + private void validatePNG(InputStream inputStream) throws Exception { + byte[] buf = new byte[8]; + if (inputStream.read(buf, 0, buf.length) == -1) { + throw new Exception("File is too short!"); + } + + if ((buf[0] & 0xFF) == 0x89 && + buf[1] == 0x50 && + buf[2] == 0x4E && + buf[3] == 0x47 && + buf[4] == 0x0D && + buf[5] == 0x0A && + buf[6] == 0x1A && + buf[7] == 0x0A) { + // The PNG signature is correct. + } + else { + throw new Exception("Wrong PNG signature."); + } + } + + + private Chunk getChunk(InputStream inputStream) throws Exception { + Chunk chunk = new Chunk(); + chunk.setLength(getLong(inputStream)); // The length of the data chunk. + chunk.setType(getBytes(inputStream, 4)); // The chunk type. + chunk.setData(getBytes(inputStream, chunk.getLength())); // The chunk data. + chunk.setCrc(getLong(inputStream)); // CRC of the type and data chunks. + if (!chunk.hasGoodCRC()) { + throw new Exception("Chunk has bad CRC."); + } + return chunk; + } + + + private long getLong(InputStream inputStream) throws Exception { + byte[] buf = getBytes(inputStream, 4); + return (toIntValue(buf, 0) & 0x00000000ffffffffL); + } + + + private byte[] getBytes(InputStream inputStream, long length) throws Exception { + byte[] buf = new byte[(int) length]; + if (inputStream.read(buf, 0, buf.length) == -1) { + throw new Exception("Error reading input stream!"); + } + return buf; + } + + + private int toIntValue(byte[] buf, int off) { +/* + long val = 0L; + + val |= (long) buf[off] & 0xff; + val <<= 8; + val |= (long) buf[1 + off] & 0xff; + val <<= 8; + val |= (long) buf[2 + off] & 0xff; + val <<= 8; + val |= (long) buf[3 + off] & 0xff; + + return (int) val; +*/ + int val = 0; + + val |= buf[off] & 0xff; + val <<= 8; + val |= buf[off + 1] & 0xff; + val <<= 8; + val |= buf[off + 2] & 0xff; + val <<= 8; + val |= buf[off + 3] & 0xff; + + return val; + } + + + // Truecolor Image with Bit Depth == 16 + private byte[] getImageColorType2BitDepth16() { + + int j = 0; + byte[] image = new byte[inflated.length - this.h]; + + byte filter = 0x00; + int scanLineLength = 6 * this.w; + + for (int i = 0; i < inflated.length; i++) { + + if (i % (scanLineLength + 1) == 0) { + filter = inflated[i]; + continue; + } + + image[j] = inflated[i]; + + int a = 0; + int b = 0; + int c = 0; + + if (j % scanLineLength >= 6) { + a = (image[j - 6] & 0x000000ff); + } + + if (j >= scanLineLength) { + b = (image[j - scanLineLength] & 0x000000ff); + } + + if (j % scanLineLength >= 6 && j >= scanLineLength) { + c = (image[j - (scanLineLength + 6)] & 0x000000ff); + } + + applyFilters(filter, image, j, a, b, c); + + j++; + } + + return image; + } + + + // Truecolor Image with Bit Depth == 8 + private byte[] getImageColorType2BitDepth8() { + + int j = 0; + byte[] image = new byte[inflated.length - this.h]; + + byte filter = 0x00; + int scanLineLength = 3 * this.w; + + for (int i = 0; i < inflated.length; i++) { + + if (i % (scanLineLength + 1) == 0) { + filter = inflated[i]; + continue; + } + + image[j] = inflated[i]; + + int a = 0; + int b = 0; + int c = 0; + + if (j % scanLineLength >= 3) { + a = (image[j - 3] & 0x000000ff); + } + + if (j >= scanLineLength) { + b = (image[j - scanLineLength] & 0x000000ff); + } + + if (j % scanLineLength >= 3 && j >= scanLineLength) { + c = (image[j - (scanLineLength + 3)] & 0x000000ff); + } + + applyFilters(filter, image, j, a, b, c); + + j++; + } + + return image; + } + + + // Truecolor Image with Alpha Transparency + private byte[] getImageColorType6BitDepth8() throws Exception { + int j = 0; + byte[] image = new byte[4 * this.w * this.h]; + + byte filter = 0x00; + int scanLineLength = 4 * this.w; + + for (int i = 0; i < inflated.length; i++) { + if (i % (scanLineLength + 1) == 0) { + filter = inflated[i]; + continue; + } + + image[j] = inflated[i]; + + int a = 0; + int b = 0; + int c = 0; + + if (j % scanLineLength >= 4) { + a = (image[j - 4] & 0x000000ff); + } + if (j >= scanLineLength) { + b = (image[j - scanLineLength] & 0x000000ff); + } + if (j % scanLineLength >= 4 && j >= scanLineLength) { + c = (image[j - (scanLineLength + 4)] & 0x000000ff); + } + + applyFilters(filter, image, j, a, b, c); + j++; + } + + byte[] idata = new byte[3 * this.w * this.h]; // Image data + byte[] alpha = new byte[this.w * this.h]; // Alpha values + + int k = 0; + int n = 0; + for (int i = 0; i < image.length; i += 4) { + idata[k] = image[i]; + idata[k + 1] = image[i + 1]; + idata[k + 2] = image[i + 2]; + alpha[n] = image[i + 3]; + + k += 3; + n += 1; + } + + Compressor compressor = new Compressor(alpha); + deflatedAlpha = compressor.getCompressedData(); + + return idata; + } + + + // Indexed Image with Bit Depth == 8 + private byte[] getImageColorType3BitDepth8() { + int j = 0; + int n = 0; + + byte[] alpha = null; + if (alphaForPalette != null) { + alpha = new byte[this.w * this.h]; + } + + byte[] image = new byte[3*(inflated.length - this.h)]; + int scanLineLength = this.w + 1; + for (int i = 0; i < inflated.length; i++) { + if (i % scanLineLength != 0) { + int k = ((int) inflated[i] & 0x000000ff); + image[j++] = rgb[3*k]; + image[j++] = rgb[3*k + 1]; + image[j++] = rgb[3*k + 2]; + + if (alphaForPalette != null) { + alpha[n++] = alphaForPalette[k]; + } + } + } + + if (alphaForPalette != null) { + deflatedAlpha = (new Compressor(alpha)).getCompressedData(); + } + + return image; + } + + + // Indexed Image with Bit Depth == 4 + private byte[] getImageColorType3BitDepth4() { + + int j = 0; + int k; + + byte[] image = new byte[6 * (inflated.length - this.h)]; + int scanLineLength = this.w / 2 + 1; + if (this.w % 2 > 0) { + scanLineLength += 1; + } + + for (int i = 0; i < inflated.length; i++) { + + if (i % scanLineLength == 0) { + // Skip the filter byte. + continue; + } + + int l = (int) inflated[i]; + + k = 3 * ((l >> 4) & 0x0000000f); + image[j++] = rgb[k]; + image[j++] = rgb[k + 1]; + image[j++] = rgb[k + 2]; + + if (j % (3 * this.w) == 0) continue; + + k = 3 * (l & 0x0000000f); + image[j++] = rgb[k]; + image[j++] = rgb[k + 1]; + image[j++] = rgb[k + 2]; + + } + + return image; + } + + + // Indexed Image with Bit Depth == 2 + private byte[] getImageColorType3BitDepth2() { + int j = 0; + int k; + + byte[] image = new byte[12 * (inflated.length - this.h)]; + int scanLineLength = this.w / 4 + 1; + if (this.w % 4 > 0) { + scanLineLength += 1; + } + + for (int i = 0; i < inflated.length; i++) { + + if (i % scanLineLength == 0) { + // Skip the filter byte. + continue; + } + + int l = (int) inflated[i]; + + k = 3 * ((l >> 6) & 0x00000003); + image[j++] = rgb[k]; + image[j++] = rgb[k + 1]; + image[j++] = rgb[k + 2]; + + if (j % (3 * this.w) == 0) continue; + + k = 3 * ((l >> 4) & 0x00000003); + image[j++] = rgb[k]; + image[j++] = rgb[k + 1]; + image[j++] = rgb[k + 2]; + + if (j % (3 * this.w) == 0) continue; + + k = 3 * ((l >> 2) & 0x00000003); + image[j++] = rgb[k]; + image[j++] = rgb[k + 1]; + image[j++] = rgb[k + 2]; + + if (j % (3 * this.w) == 0) continue; + + k = 3 * (l & 0x00000003); + image[j++] = rgb[k]; + image[j++] = rgb[k + 1]; + image[j++] = rgb[k + 2]; + + } + + return image; + } + + + // Indexed Image with Bit Depth == 1 + private byte[] getImageColorType3BitDepth1() { + int j = 0; + int k; + + byte[] image = new byte[24 * (inflated.length - this.h)]; + int scanLineLength = this.w / 8 + 1; + if (this.w % 8 > 0) { + scanLineLength += 1; + } + + for (int i = 0; i < inflated.length; i++) { + + if (i % scanLineLength == 0) { + // Skip the filter byte. + continue; + } + + int l = (int) inflated[i]; + + k = 3 * ((l >> 7) & 0x00000001); + image[j++] = rgb[k]; + image[j++] = rgb[k + 1]; + image[j++] = rgb[k + 2]; + + if (j % (3 * this.w) == 0) continue; + + k = 3 * ((l >> 6) & 0x00000001); + image[j++] = rgb[k]; + image[j++] = rgb[k + 1]; + image[j++] = rgb[k + 2]; + + if (j % (3 * this.w) == 0) continue; + + k = 3 * ((l >> 5) & 0x00000001); + image[j++] = rgb[k]; + image[j++] = rgb[k + 1]; + image[j++] = rgb[k + 2]; + + if (j % (3 * this.w) == 0) continue; + + k = 3 * ((l >> 4) & 0x00000001); + image[j++] = rgb[k]; + image[j++] = rgb[k + 1]; + image[j++] = rgb[k + 2]; + + if (j % (3 * this.w) == 0) continue; + + k = 3 * ((l >> 3) & 0x00000001); + image[j++] = rgb[k]; + image[j++] = rgb[k + 1]; + image[j++] = rgb[k + 2]; + + if (j % (3 * this.w) == 0) continue; + + k = 3 * ((l >> 2) & 0x00000001); + image[j++] = rgb[k]; + image[j++] = rgb[k + 1]; + image[j++] = rgb[k + 2]; + + if (j % (3 * this.w) == 0) continue; + + k = 3 * ((l >> 1) & 0x00000001); + image[j++] = rgb[k]; + image[j++] = rgb[k + 1]; + image[j++] = rgb[k + 2]; + + if (j % (3 * this.w) == 0) continue; + + k = 3 * (l & 0x00000001); + image[j++] = rgb[k]; + image[j++] = rgb[k + 1]; + image[j++] = rgb[k + 2]; + + } + + return image; + } + + + // Grayscale Image with Bit Depth == 16 + private byte[] getImageColorType0BitDepth16() { + + int j = 0; + byte[] image = new byte[inflated.length - this.h]; + + byte filter = 0x00; + int scanLineLength = 2 * this.w; + + for (int i = 0; i < inflated.length; i++) { + + if (i % (scanLineLength + 1) == 0) { + filter = inflated[i]; + continue; + } + + image[j] = inflated[i]; + + int a = 0; + int b = 0; + int c = 0; + + if (j % scanLineLength >= 2) { + a = (image[j - 2] & 0x000000ff); + } + + if (j >= scanLineLength) { + b = (image[j - scanLineLength] & 0x000000ff); + } + + if (j % scanLineLength >= 2 && j >= scanLineLength) { + c = (image[j - (scanLineLength + 2)] & 0x000000ff); + } + + applyFilters(filter, image, j, a, b, c); + + j++; + } + + return image; + } + + + // Grayscale Image with Bit Depth == 8 + private byte[] getImageColorType0BitDepth8() { + + int j = 0; + byte[] image = new byte[inflated.length - this.h]; + + byte filter = 0x00; + int scanLineLength = this.w; + + for (int i = 0; i < inflated.length; i++) { + + if (i % (scanLineLength + 1) == 0) { + filter = inflated[i]; + continue; + } + + image[j] = inflated[i]; + + int a = 0; + int b = 0; + int c = 0; + + if (j % scanLineLength >= 1) { + a = (image[j - 1] & 0x000000ff); + } + + if (j >= scanLineLength) { + b = (image[j - scanLineLength] & 0x000000ff); + } + + if (j % scanLineLength >= 1 && j >= scanLineLength) { + c = (image[j - (scanLineLength + 1)] & 0x000000ff); + } + + applyFilters(filter, image, j, a, b, c); + + j++; + } + + return image; + } + + + // Grayscale Image with Bit Depth == 4 + private byte[] getImageColorType0BitDepth4() { + + int j = 0; + byte[] image = new byte[inflated.length - this.h]; + + int scanLineLength = this.w / 2 + 1; + if (this.w % 2 > 0) { + scanLineLength += 1; + } + + for (int i = 0; i < inflated.length; i++) { + + if (i % scanLineLength == 0) { + continue; + } + + image[j++] = inflated[i]; + } + + return image; + } + + + // Grayscale Image with Bit Depth == 2 + private byte[] getImageColorType0BitDepth2() { + + int j = 0; + byte[] image = new byte[inflated.length - this.h]; + + int scanLineLength = this.w / 4 + 1; + if (this.w % 4 > 0) { + scanLineLength += 1; + } + + for (int i = 0; i < inflated.length; i++) { + + if (i % scanLineLength == 0) { + continue; + } + + image[j++] = inflated[i]; + } + + return image; + } + + + // Grayscale Image with Bit Depth == 1 + private byte[] getImageColorType0BitDepth1() { + + int j = 0; + byte[] image = new byte[inflated.length - this.h]; + + int scanLineLength = this.w / 8 + 1; + if (this.w % 8 > 0) { + scanLineLength += 1; + } + + for (int i = 0; i < inflated.length; i++) { + if (i % scanLineLength != 0) { + image[j++] = inflated[i]; + } + } + + return image; + } + + + private void applyFilters(byte filter, byte[] image, int j, int a, int b, int c) { + + if (filter == 0x00) { // None + // Nothing to do. + } + else if (filter == 0x01) { // Sub + image[j] += (byte) a; + } + else if (filter == 0x02) { // Up + image[j] += (byte) b; + } + else if (filter == 0x03) { // Average + image[j] += (byte) Math.floor((double) (a + b) / 2); + } + else if (filter == 0x04) { // Paeth + int pr = c; + int p = a + b - c; + int pa = Math.abs(p - a); + int pb = Math.abs(p - b); + int pc = Math.abs(p - c); + if (pa <= pb && pa <= pc) { + pr = a; + } + else if (pb <= pc) { + pr = b; + } + image[j] += (byte) (pr & 0x000000ff); + } + + } + + + private byte[] getDecompressedData() throws Exception { + Decompressor decompressor = new Decompressor(data); + return decompressor.getDecompressedData(); + } + + + private byte[] deflateReconstructedData() throws Exception { + Compressor compressor = new Compressor(image); + return compressor.getCompressedData(); + } + + + private byte[] appendIdatChunk(byte[] array1, byte[] array2) { + if (array1 == null) { + return array2; + } + else if (array2 == null) { + return array1; + } + byte[] joinedArray = new byte[array1.length + array2.length]; + System.arraycopy(array1, 0, joinedArray, 0, array1.length); + System.arraycopy(array2, 0, joinedArray, array1.length, array2.length); + return joinedArray; + } + +/* + public static void main(String[] args) throws Exception { + FileInputStream fis = new FileInputStream(args[0]); + PNGImage png = new PNGImage(fis); + byte[] image = png.getData(); + byte[] alpha = png.getAlpha(); + int w = png.getWidth(); + int h = png.getHeight(); + int c = png.getColorType(); + fis.close(); + + String fileName = args[0].substring(0, args[0].lastIndexOf(".")); + FileOutputStream fos = new FileOutputStream(fileName + ".jet"); + BufferedOutputStream bos = new BufferedOutputStream(fos); + writeInt(w, bos); // Width + writeInt(h, bos); // Height + bos.write(c); // Color Space + if (alpha != null) { + bos.write(1); + writeInt(alpha.length, bos); + bos.write(alpha); + } + else { + bos.write(0); + } + writeInt(image.length, bos); + bos.write(image); + bos.flush(); + bos.close(); + } + + + private static void writeInt(int i, OutputStream os) throws IOException { + os.write((i >> 24) & 0xff); + os.write((i >> 16) & 0xff); + os.write((i >> 8) & 0xff); + os.write((i >> 0) & 0xff); + } +*/ + +} // End of PNGImage.java diff --git a/PDFJet/src/main/java/com/pdfjet/Page.java b/PDFJet/src/main/java/com/pdfjet/Page.java new file mode 100644 index 0000000..77c5b51 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Page.java @@ -0,0 +1,1814 @@ +/** + * Page.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + +import java.io.*; +import java.text.*; +import java.util.*; + + +/** + * Used to create PDF page objects. + * + * Please note: + *

+ *  The coordinate (0f, 0f) is the top left corner of the page.
+ *  The size of the pages are represented in points.
+ *  1 point is 1/72 inches.
+ *  
+ * + */ +public class Page { + + protected PDF pdf; + protected PDFobj pageObj; + protected int objNumber; + protected ByteArrayOutputStream buf; + protected float[] tm = new float[] {1f, 0f, 0f, 1f}; + protected int renderingMode = 0; + protected float width; + protected float height; + protected List contents; + protected List annots; + protected List destinations; + protected float[] cropBox = null; + protected float[] bleedBox = null; + protected float[] trimBox = null; + protected float[] artBox = null; + protected List structures = new ArrayList(); + + private float[] pen = {0f, 0f, 0f}; + private float[] brush = {0f, 0f, 0f}; + private float pen_width = -1.0f; + private int line_cap_style = 0; + private int line_join_style = 0; + private String linePattern = "[] 0"; + private Font font; + private List savedStates = new ArrayList(); + private int mcid = 0; + + protected float savedHeight = Float.MAX_VALUE; + + /* + * From Android's Matrix object: + */ + public static final int MSCALE_X = 0; + public static final int MSKEW_X = 1; + public static final int MTRANS_X = 2; + public static final int MSKEW_Y = 3; + public static final int MSCALE_Y = 4; + public static final int MTRANS_Y = 5; + + + /** + * Creates page object and add it to the PDF document. + * + * Please note: + *
+     *  The coordinate (0f, 0f) is the top left corner of the page.
+     *  The size of the pages are represented in points.
+     *  1 point is 1/72 inches.
+     *  
+ * + * @param pdf the pdf object. + * @param pageSize the page size of this page. + */ + public Page(PDF pdf, float[] pageSize) throws Exception { + this(pdf, pageSize, true); + } + + + /** + * Creates page object and add it to the PDF document. + * + * Please note: + *
+     *  The coordinate (0f, 0f) is the top left corner of the page.
+     *  The size of the pages are represented in points.
+     *  1 point is 1/72 inches.
+     *  
+ * + * @param pdf the pdf object. + * @param pageSize the page size of this page. + * @param addPageToPDF boolean flag. + */ + public Page(PDF pdf, float[] pageSize, boolean addPageToPDF) throws Exception { + this.pdf = pdf; + contents = new ArrayList(); + annots = new ArrayList(); + destinations = new ArrayList(); + width = pageSize[0]; + height = pageSize[1]; + buf = new ByteArrayOutputStream(8192); + if (addPageToPDF) { + pdf.addPage(this); + } + } + + + public Page(PDF pdf, PDFobj pageObj) throws Exception { + this.pdf = pdf; + this.pageObj = pageObj; + width = pageObj.getPageSize()[0]; + height = pageObj.getPageSize()[1]; + buf = new ByteArrayOutputStream(8192); + append("Q\n"); + append("q\n"); + if (pageObj.gsNumber != -1) { + append("/GS"); + append(pageObj.gsNumber + 1); + append(" gs\n"); + } + } + + + public Font addResource(CoreFont coreFont, Map objects) { + return pageObj.addResource(coreFont, objects); + } + + + public void addResource(Image image, Map objects) { + pageObj.addResource(image, objects); + } + + + public void addResource(Font font, Map objects) { + pageObj.addResource(font, objects); + } + + + public void complete(Map objects) throws Exception { + append("Q\n"); + pageObj.addContent(getContent(), objects); + } + + + public byte[] getContent() { + return buf.toByteArray(); + } + + + /** + * Adds destination to this page. + * + * @param name The destination name. + * @param yPosition The vertical position of the destination on this page. + * + * @return the destination. + */ + public Destination addDestination(String name, float yPosition) { + Destination dest = new Destination(name, height - yPosition); + destinations.add(dest); + return dest; + } + + + /** + * Returns the width of this page. + * + * @return the width of the page. + */ + public float getWidth() { + return width; + } + + + /** + * Returns the height of this page. + * + * @return the height of the page. + */ + public float getHeight() { + return height; + } + + + /** + * Draws a line on the page, using the current color, between the points (x1, y1) and (x2, y2). + * + * @param x1 the first point's x coordinate. + * @param y1 the first point's y coordinate. + * @param x2 the second point's x coordinate. + * @param y2 the second point's y coordinate. + */ + public void drawLine( + double x1, + double y1, + double x2, + double y2) throws IOException { + drawLine((float) x1, (float) y1, (float) x2, (float) y2); + } + + + /** + * Draws a line on the page, using the current color, between the points (x1, y1) and (x2, y2). + * + * @param x1 the first point's x coordinate. + * @param y1 the first point's y coordinate. + * @param x2 the second point's x coordinate. + * @param y2 the second point's y coordinate. + */ + public void drawLine( + float x1, + float y1, + float x2, + float y2) throws IOException { + moveTo(x1, y1); + lineTo(x2, y2); + strokePath(); + } + + + /** + * Draws the text given by the specified string, + * using the specified main font and the current brush color. + * If the main font is missing some glyphs - the fallback font is used. + * The baseline of the leftmost character is at position (x, y) on the page. + * + * @param font1 the main font. + * @param font2 the fallback font. + * @param str the string to be drawn. + * @param x the x coordinate. + * @param y the y coordinate. + */ + public void drawString( + Font font1, + Font font2, + String str, + float x, + float y) throws IOException { + if (font2 == null) { + drawString(font1, str, x, y); + } + else { + Font activeFont = font1; + StringBuilder buf = new StringBuilder(); + for (int i = 0; i < str.length(); i++) { + int ch = str.charAt(i); + if ((font1.isCJK && ch >= 0x4E00 && ch <= 0x9FCC) + || (!font1.isCJK && font1.unicodeToGID[ch] != 0)) { + if (font1 != activeFont) { + String str2 = buf.toString(); + drawString(activeFont, str2, x, y); + x += activeFont.stringWidth(str2); + buf.setLength(0); + activeFont = font1; + } + } + else { + if (font2 != activeFont) { + String str2 = buf.toString(); + drawString(activeFont, str2, x, y); + x += activeFont.stringWidth(str2); + buf.setLength(0); + activeFont = font2; + } + } + buf.append((char) ch); + } + drawString(activeFont, buf.toString(), x, y); + } + } + + + /** + * Draws the text given by the specified string, + * using the specified font and the current brush color. + * The baseline of the leftmost character is at position (x, y) on the page. + * + * @param font the font to use. + * @param str the string to be drawn. + * @param x the x coordinate. + * @param y the y coordinate. + */ + public void drawString( + Font font, + String str, + double x, + double y) throws IOException { + drawString(font, str, (float) x, (float) y); + } + + + /** + * Draws the text given by the specified string, + * using the specified font and the current brush color. + * The baseline of the leftmost character is at position (x, y) on the page. + * + * @param font the font to use. + * @param str the string to be drawn. + * @param x the x coordinate. + * @param y the y coordinate. + */ + public void drawString( + Font font, + String str, + float x, + float y) throws IOException { + + if (str == null || str.equals("")) { + return; + } + + append("BT\n"); + + if (font.fontID == null) { + setTextFont(font); + } + else { + append('/'); + append(font.fontID); + append(' '); + append(font.size); + append(" Tf\n"); + } + + if (renderingMode != 0) { + append(renderingMode); + append(" Tr\n"); + } + + float skew = 0f; + if (font.skew15 && + tm[0] == 1f && + tm[1] == 0f && + tm[2] == 0f && + tm[3] == 1f) { + skew = 0.26f; + } + + append(tm[0]); + append(' '); + append(tm[1]); + append(' '); + append(tm[2] + skew); + append(' '); + append(tm[3]); + append(' '); + append(x); + append(' '); + append(height - y); + append(" Tm\n"); + + append("[<"); + drawString(font, str); + append(">] TJ\n"); + + append("ET\n"); + } + + + private void drawString(Font font, String str) throws IOException { + int len = str.length(); + for (int i = 0; i < len; i++) { + if (font.isCoreFont) { + drawOneByteChar(str.charAt(i), font, str, i); + } + else { + drawTwoByteChar(str.charAt(i), font); + } + } + } + + + private void drawOneByteChar( + int c1, Font font, String str, int i) throws IOException { + if (c1 < font.firstChar || c1 > font.lastChar) { + append(String.format("%02X", 0x20)); + return; + } + append(String.format("%02X", c1)); + + if (font.isCoreFont && font.kernPairs && i < (str.length() - 1)) { + c1 -= 32; + int c2 = str.charAt(i + 1); + if (c2 < font.firstChar || c2 > font.lastChar) { + c2 = 32; + } + for (int j = 2; j < font.metrics[c1].length; j += 2) { + if (font.metrics[c1][j] == c2) { + append(">"); + append(-font.metrics[c1][j + 1]); + append("<"); + break; + } + } + } + } + + + private void drawTwoByteChar(int c1, Font font) throws IOException { + if (c1 < font.firstChar || c1 > font.lastChar) { + if (font.isCJK) { + append(String.format("%04X", 0x0020)); + } + else { + append(String.format("%04X", font.unicodeToGID[0x0020])); + } + } + else { + if (font.isCJK) { + append(String.format("%04X", c1)); + } + else { + append(String.format("%04X", font.unicodeToGID[c1])); + } + } + } + + + /** + * Sets the graphics state. Please see Example_31. + * + * @param gs the graphics state to use. + */ + public void setGraphicsState(GraphicsState gs) throws IOException { + StringBuilder buf = new StringBuilder(); + buf.append("/CA "); + buf.append(gs.get_CA()); + buf.append(" "); + buf.append("/ca "); + buf.append(gs.get_ca()); + setGraphicsState(buf.toString()); + } + + + // String state = "/CA 0.5 /ca 0.5"; + private void setGraphicsState(String state) throws IOException { + Integer n = pdf.states.get(state); + if (n == null) { + n = pdf.states.size() + 1; + pdf.states.put(state, n); + } + append("/GS"); + append(n); + append(" gs\n"); + } + + + /** + * Sets the color for stroking operations. + * The pen color is used when drawing lines and splines. + * + * @param r the red component is float value from 0.0 to 1.0. + * @param g the green component is float value from 0.0 to 1.0. + * @param b the blue component is float value from 0.0 to 1.0. + */ + public void setPenColor( + double r, double g, double b) throws IOException { + setPenColor((float) r, (float) g, (float) b); + } + + + /** + * Sets the color for stroking operations. + * The pen color is used when drawing lines and splines. + * + * @param r the red component is float value from 0.0f to 1.0f. + * @param g the green component is float value from 0.0f to 1.0f. + * @param b the blue component is float value from 0.0f to 1.0f. + */ + public void setPenColor( + float r, float g, float b) throws IOException { + if (pen[0] != r || + pen[1] != g || + pen[2] != b) { + setColor(r, g, b); + append(" RG\n"); + pen[0] = r; + pen[1] = g; + pen[2] = b; + } + } + + + /** + * Sets the color for brush operations. + * This is the color used when drawing regular text and filling shapes. + * + * @param r the red component is float value from 0.0 to 1.0. + * @param g the green component is float value from 0.0 to 1.0. + * @param b the blue component is float value from 0.0 to 1.0. + */ + public void setBrushColor( + double r, double g, double b) throws IOException { + setBrushColor((float) r, (float) g, (float) b); + } + + + /** + * Sets the color for brush operations. + * This is the color used when drawing regular text and filling shapes. + * + * @param r the red component is float value from 0.0f to 1.0f. + * @param g the green component is float value from 0.0f to 1.0f. + * @param b the blue component is float value from 0.0f to 1.0f. + */ + public void setBrushColor( + float r, float g, float b) throws IOException { + if (brush[0] != r || + brush[1] != g || + brush[2] != b) { + setColor(r, g, b); + append(" rg\n"); + brush[0] = r; + brush[1] = g; + brush[2] = b; + } + } + + + /** + * Sets the color for brush operations. + * + * @param color the color. + * @throws IOException + */ + public void setBrushColor(float[] color) throws IOException { + setBrushColor(color[0], color[1], color[2]); + } + + + /** + * Returns the brush color. + * + * @return the brush color. + */ + public float[] getBrushColor() { + return brush; + } + + + private void setColor( + float r, float g, float b) throws IOException { + append(r); + append(' '); + append(g); + append(' '); + append(b); + } + + + /** + * Sets the pen color. + * + * @param color the color. See the Color class for predefined values or define your own using 0x00RRGGBB packed integers. + * @throws IOException + */ + public void setPenColor(int color) throws IOException { + float r = ((color >> 16) & 0xff)/255f; + float g = ((color >> 8) & 0xff)/255f; + float b = ((color) & 0xff)/255f; + setPenColor(r, g, b); + } + + + /** + * Sets the brush color. + * + * @param color the color. See the Color class for predefined values or define your own using 0x00RRGGBB packed integers. + * @throws IOException + */ + public void setBrushColor(int color) throws IOException { + float r = ((color >> 16) & 0xff)/255f; + float g = ((color >> 8) & 0xff)/255f; + float b = ((color) & 0xff)/255f; + setBrushColor(r, g, b); + } + + + /** + * Sets the line width to the default. + * The default is the finest line width. + */ + public void setDefaultLineWidth() throws IOException { + if (pen_width != 0f) { + pen_width = 0f; + append(pen_width); + append(" w\n"); + } + } + + + /** + * The line dash pattern controls the pattern of dashes and gaps used to stroke paths. + * It is specified by a dash array and a dash phase. + * The elements of the dash array are positive numbers that specify the lengths of + * alternating dashes and gaps. + * The dash phase specifies the distance into the dash pattern at which to start the dash. + * The elements of both the dash array and the dash phase are expressed in user space units. + *
+     *  Examples of line dash patterns:
+     *
+     *      "[Array] Phase"     Appearance          Description
+     *      _______________     _________________   ____________________________________
+     *
+     *      "[] 0"              -----------------   Solid line
+     *      "[3] 0"             ---   ---   ---     3 units on, 3 units off, ...
+     *      "[2] 1"             -  --  --  --  --   1 on, 2 off, 2 on, 2 off, ...
+     *      "[2 1] 0"           -- -- -- -- -- --   2 on, 1 off, 2 on, 1 off, ...
+     *      "[3 5] 6"             ---     ---       2 off, 3 on, 5 off, 3 on, 5 off, ...
+     *      "[2 3] 11"          -   --   --   --    1 on, 3 off, 2 on, 3 off, 2 on, ...
+     *  
+ * + * @param pattern the line dash pattern. + */ + public void setLinePattern(String pattern) throws IOException { + if (!pattern.equals(linePattern)) { + linePattern = pattern; + append(linePattern); + append(" d\n"); + } + } + + + /** + * Sets the default line dash pattern - solid line. + */ + public void setDefaultLinePattern() throws IOException { + append("[] 0"); + append(" d\n"); + } + + + /** + * Sets the pen width that will be used to draw lines and splines on this page. + * + * @param width the pen width. + */ + public void setPenWidth(double width) throws IOException { + setPenWidth((float) width); + } + + + /** + * Sets the pen width that will be used to draw lines and splines on this page. + * + * @param width the pen width. + */ + public void setPenWidth(float width) throws IOException { + if (pen_width != width) { + pen_width = width; + append(pen_width); + append(" w\n"); + } + } + + + /** + * Sets the current line cap style. + * + * @param style the cap style of the current line. Supported values: Cap.BUTT, Cap.ROUND and Cap.PROJECTING_SQUARE + */ + public void setLineCapStyle(int style) throws IOException { + if (line_cap_style != style) { + line_cap_style = style; + append(line_cap_style); + append(" J\n"); + } + } + + + /** + * Sets the line join style. + * + * @param style the line join style code. Supported values: Join.MITER, Join.ROUND and Join.BEVEL + */ + public void setLineJoinStyle(int style) throws IOException { + if (line_join_style != style) { + line_join_style = style; + append(line_join_style); + append(" j\n"); + } + } + + + /** + * Moves the pen to the point with coordinates (x, y) on the page. + * + * @param x the x coordinate of new pen position. + * @param y the y coordinate of new pen position. + */ + public void moveTo(double x, double y) throws IOException { + moveTo((float) x, (float) y); + } + + + /** + * Moves the pen to the point with coordinates (x, y) on the page. + * + * @param x the x coordinate of new pen position. + * @param y the y coordinate of new pen position. + */ + public void moveTo(float x, float y) throws IOException { + append(x); + append(' '); + append(height - y); + append(" m\n"); + } + + + /** + * Draws a line from the current pen position to the point with coordinates (x, y), + * using the current pen width and stroke color. + * Make sure you call strokePath(), closePath() or fillPath() after the last call to this method. + */ + public void lineTo(double x, double y) throws IOException { + lineTo((float) x, (float) y); + } + + + /** + * Draws a line from the current pen position to the point with coordinates (x, y), + * using the current pen width and stroke color. + * Make sure you call strokePath(), closePath() or fillPath() after the last call to this method. + */ + public void lineTo(float x, float y) throws IOException { + append(x); + append(' '); + append(height - y); + append(" l\n"); + } + + + /** + * Draws the path using the current pen color. + */ + public void strokePath() throws IOException { + append("S\n"); + } + + + /** + * Closes the path and draws it using the current pen color. + */ + public void closePath() throws IOException { + append("s\n"); + } + + + /** + * Closes and fills the path with the current brush color. + */ + public void fillPath() throws IOException { + append("f\n"); + } + + + /** + * Draws the outline of the specified rectangle on the page. + * The left and right edges of the rectangle are at x and x + w. + * The top and bottom edges are at y and y + h. + * The rectangle is drawn using the current pen color. + * + * @param x the x coordinate of the rectangle to be drawn. + * @param y the y coordinate of the rectangle to be drawn. + * @param w the width of the rectangle to be drawn. + * @param h the height of the rectangle to be drawn. + */ + public void drawRect(double x, double y, double w, double h) + throws IOException { + drawRect((float) x, (float) y, (float) w, (float) h); + } + + + /** + * Draws the outline of the specified rectangle on the page. + * The left and right edges of the rectangle are at x and x + w. + * The top and bottom edges are at y and y + h. + * The rectangle is drawn using the current pen color. + * + * @param x the x coordinate of the rectangle to be drawn. + * @param y the y coordinate of the rectangle to be drawn. + * @param w the width of the rectangle to be drawn. + * @param h the height of the rectangle to be drawn. + */ + public void drawRect(float x, float y, float w, float h) + throws IOException { + moveTo(x, y); + lineTo(x+w, y); + lineTo(x+w, y+h); + lineTo(x, y+h); + closePath(); + } + + + /** + * Fills the specified rectangle on the page. + * The left and right edges of the rectangle are at x and x + w. + * The top and bottom edges are at y and y + h. + * The rectangle is drawn using the current pen color. + * + * @param x the x coordinate of the rectangle to be drawn. + * @param y the y coordinate of the rectangle to be drawn. + * @param w the width of the rectangle to be drawn. + * @param h the height of the rectangle to be drawn. + */ + public void fillRect(double x, double y, double w, double h) + throws IOException { + fillRect((float) x, (float) y, (float) w, (float) h); + } + + + /** + * Fills the specified rectangle on the page. + * The left and right edges of the rectangle are at x and x + w. + * The top and bottom edges are at y and y + h. + * The rectangle is drawn using the current pen color. + * + * @param x the x coordinate of the rectangle to be drawn. + * @param y the y coordinate of the rectangle to be drawn. + * @param w the width of the rectangle to be drawn. + * @param h the height of the rectangle to be drawn. + */ + public void fillRect(float x, float y, float w, float h) + throws IOException { + moveTo(x, y); + lineTo(x+w, y); + lineTo(x+w, y+h); + lineTo(x, y+h); + fillPath(); + } + + + /** + * Draws or fills the specified path using the current pen or brush. + * + * @param path the path. + * @param operation specifies 'stroke' or 'fill' operation. + */ + public void drawPath( + List path, char operation) throws Exception { + if (path.size() < 2) { + throw new Exception( + "The Path object must contain at least 2 points"); + } + Point point = path.get(0); + moveTo(point.x, point.y); + boolean curve = false; + for (int i = 1; i < path.size(); i++) { + point = path.get(i); + if (point.isControlPoint) { + curve = true; + append(point); + } + else { + if (curve) { + curve = false; + append(point); + append("c\n"); + } + else { + lineTo(point.x, point.y); + } + } + } + + append(operation); + append('\n'); + } + + + /** + * Draws a circle on the page. + * + * The outline of the circle is drawn using the current pen color. + * + * @param x the x coordinate of the center of the circle to be drawn. + * @param y the y coordinate of the center of the circle to be drawn. + * @param r the radius of the circle to be drawn. + */ + public void drawCircle( + double x, + double y, + double r) throws Exception { + drawEllipse((float) x, (float) y, (float) r, (float) r, Operation.STROKE); + } + + + /** + * Draws a circle on the page. + * + * The outline of the circle is drawn using the current pen color. + * + * @param x the x coordinate of the center of the circle to be drawn. + * @param y the y coordinate of the center of the circle to be drawn. + * @param r the radius of the circle to be drawn. + */ + public void drawCircle( + float x, + float y, + float r) throws Exception { + drawEllipse(x, y, r, r, Operation.STROKE); + } + + + /** + * Draws the specified circle on the page and fills it with the current brush color. + * + * @param x the x coordinate of the center of the circle to be drawn. + * @param y the y coordinate of the center of the circle to be drawn. + * @param r the radius of the circle to be drawn. + * @param operation must be Operation.STROKE, Operation.CLOSE or Operation.FILL. + */ + public void drawCircle( + double x, + double y, + double r, + char operation) throws Exception { + drawEllipse((float) x, (float) y, (float) r, (float) r, operation); + } + + + /** + * Draws the specified circle on the page and fills it with the current brush color. + * + * @param x the x coordinate of the center of the circle to be drawn. + * @param y the y coordinate of the center of the circle to be drawn. + * @param r the radius of the circle to be drawn. + * @param operation must be Operation.STROKE, Operation.CLOSE or Operation.FILL. + */ + public void drawCircle( + float x, + float y, + float r, + char operation) throws Exception { + drawEllipse(x, y, r, r, operation); + } + + + /** + * Draws an ellipse on the page using the current pen color. + * + * @param x the x coordinate of the center of the ellipse to be drawn. + * @param y the y coordinate of the center of the ellipse to be drawn. + * @param r1 the horizontal radius of the ellipse to be drawn. + * @param r2 the vertical radius of the ellipse to be drawn. + */ + public void drawEllipse( + double x, + double y, + double r1, + double r2) throws Exception { + drawEllipse((float) x, (float) y, (float) r1, (float) r2, Operation.STROKE); + } + + + /** + * Draws an ellipse on the page using the current pen color. + * + * @param x the x coordinate of the center of the ellipse to be drawn. + * @param y the y coordinate of the center of the ellipse to be drawn. + * @param r1 the horizontal radius of the ellipse to be drawn. + * @param r2 the vertical radius of the ellipse to be drawn. + */ + public void drawEllipse( + float x, + float y, + float r1, + float r2) throws Exception { + drawEllipse(x, y, r1, r2, Operation.STROKE); + } + + + /** + * Fills an ellipse on the page using the current pen color. + * + * @param x the x coordinate of the center of the ellipse to be drawn. + * @param y the y coordinate of the center of the ellipse to be drawn. + * @param r1 the horizontal radius of the ellipse to be drawn. + * @param r2 the vertical radius of the ellipse to be drawn. + */ + public void fillEllipse( + double x, + double y, + double r1, + double r2) throws Exception { + drawEllipse((float) x, (float) y, (float) r1, (float) r2, Operation.FILL); + } + + + /** + * Fills an ellipse on the page using the current pen color. + * + * @param x the x coordinate of the center of the ellipse to be drawn. + * @param y the y coordinate of the center of the ellipse to be drawn. + * @param r1 the horizontal radius of the ellipse to be drawn. + * @param r2 the vertical radius of the ellipse to be drawn. + */ + public void fillEllipse( + float x, + float y, + float r1, + float r2) throws Exception { + drawEllipse(x, y, r1, r2, Operation.FILL); + } + + + /** + * Draws an ellipse on the page and fills it using the current brush color. + * + * @param x the x coordinate of the center of the ellipse to be drawn. + * @param y the y coordinate of the center of the ellipse to be drawn. + * @param r1 the horizontal radius of the ellipse to be drawn. + * @param r2 the vertical radius of the ellipse to be drawn. + * @param operation the operation. + */ + private void drawEllipse( + float x, + float y, + float r1, + float r2, + char operation) throws Exception { + // The best 4-spline magic number + float m4 = 0.551784f; + + // Starting point + moveTo(x, y - r2); + + appendPointXY(x + m4*r1, y - r2); + appendPointXY(x + r1, y - m4*r2); + appendPointXY(x + r1, y); + append("c\n"); + + appendPointXY(x + r1, y + m4*r2); + appendPointXY(x + m4*r1, y + r2); + appendPointXY(x, y + r2); + append("c\n"); + + appendPointXY(x - m4*r1, y + r2); + appendPointXY(x - r1, y + m4*r2); + appendPointXY(x - r1, y); + append("c\n"); + + appendPointXY(x - r1, y - m4*r2); + appendPointXY(x - m4*r1, y - r2); + appendPointXY(x, y - r2); + append("c\n"); + + append(operation); + append('\n'); + } + + + /** + * Draws a point on the page using the current pen color. + * + * @param p the point. + */ + public void drawPoint(Point p) throws Exception { + if (p.shape != Point.INVISIBLE) { + List list; + if (p.shape == Point.CIRCLE) { + if (p.fillShape) { + drawCircle(p.x, p.y, p.r, 'f'); + } + else { + drawCircle(p.x, p.y, p.r, 'S'); + } + } + else if (p.shape == Point.DIAMOND) { + list = new ArrayList(); + list.add(new Point(p.x, p.y - p.r)); + list.add(new Point(p.x + p.r, p.y)); + list.add(new Point(p.x, p.y + p.r)); + list.add(new Point(p.x - p.r, p.y)); + if (p.fillShape) { + drawPath(list, 'f'); + } + else { + drawPath(list, 's'); + } + } + else if (p.shape == Point.BOX) { + list = new ArrayList(); + list.add(new Point(p.x - p.r, p.y - p.r)); + list.add(new Point(p.x + p.r, p.y - p.r)); + list.add(new Point(p.x + p.r, p.y + p.r)); + list.add(new Point(p.x - p.r, p.y + p.r)); + if (p.fillShape) { + drawPath(list, 'f'); + } + else { + drawPath(list, 's'); + } + } + else if (p.shape == Point.PLUS) { + drawLine(p.x - p.r, p.y, p.x + p.r, p.y); + drawLine(p.x, p.y - p.r, p.x, p.y + p.r); + } + else if (p.shape == Point.UP_ARROW) { + list = new ArrayList(); + list.add(new Point(p.x, p.y - p.r)); + list.add(new Point(p.x + p.r, p.y + p.r)); + list.add(new Point(p.x - p.r, p.y + p.r)); + if (p.fillShape) { + drawPath(list, 'f'); + } + else { + drawPath(list, 's'); + } + } + else if (p.shape == Point.DOWN_ARROW) { + list = new ArrayList(); + list.add(new Point(p.x - p.r, p.y - p.r)); + list.add(new Point(p.x + p.r, p.y - p.r)); + list.add(new Point(p.x, p.y + p.r)); + if (p.fillShape) { + drawPath(list, 'f'); + } + else { + drawPath(list, 's'); + } + } + else if (p.shape == Point.LEFT_ARROW) { + list = new ArrayList(); + list.add(new Point(p.x + p.r, p.y + p.r)); + list.add(new Point(p.x - p.r, p.y)); + list.add(new Point(p.x + p.r, p.y - p.r)); + if (p.fillShape) { + drawPath(list, 'f'); + } + else { + drawPath(list, 's'); + } + } + else if (p.shape == Point.RIGHT_ARROW) { + list = new ArrayList(); + list.add(new Point(p.x - p.r, p.y - p.r)); + list.add(new Point(p.x + p.r, p.y)); + list.add(new Point(p.x - p.r, p.y + p.r)); + if (p.fillShape) { + drawPath(list, 'f'); + } + else { + drawPath(list, 's'); + } + } + else if (p.shape == Point.H_DASH) { + drawLine(p.x - p.r, p.y, p.x + p.r, p.y); + } + else if (p.shape == Point.V_DASH) { + drawLine(p.x, p.y - p.r, p.x, p.y + p.r); + } + else if (p.shape == Point.X_MARK) { + drawLine(p.x - p.r, p.y - p.r, p.x + p.r, p.y + p.r); + drawLine(p.x - p.r, p.y + p.r, p.x + p.r, p.y - p.r); + } + else if (p.shape == Point.MULTIPLY) { + drawLine(p.x - p.r, p.y - p.r, p.x + p.r, p.y + p.r); + drawLine(p.x - p.r, p.y + p.r, p.x + p.r, p.y - p.r); + drawLine(p.x - p.r, p.y, p.x + p.r, p.y); + drawLine(p.x, p.y - p.r, p.x, p.y + p.r); + } + else if (p.shape == Point.STAR) { + float angle = (float) Math.PI / 10; + float sin18 = (float) Math.sin(angle); + float cos18 = (float) Math.cos(angle); + float a = p.r * cos18; + float b = p.r * sin18; + float c = 2 * a * sin18; + float d = 2 * a * cos18 - p.r; + list = new ArrayList(); + list.add(new Point(p.x, p.y - p.r)); + list.add(new Point(p.x + c, p.y + d)); + list.add(new Point(p.x - a, p.y - b)); + list.add(new Point(p.x + a, p.y - b)); + list.add(new Point(p.x - c, p.y + d)); + if (p.fillShape) { + drawPath(list, 'f'); + } + else { + drawPath(list, 's'); + } + } + } + } + + + /** + * Sets the text rendering mode. + * + * @param mode the rendering mode. + */ + public void setTextRenderingMode(int mode) throws Exception { + if (mode >= 0 && mode <= 7) { + this.renderingMode = mode; + } + else { + throw new Exception("Invalid text rendering mode: " + mode); + } + } + + + /** + * Sets the text direction. + * + * @param degrees the angle. + */ + public void setTextDirection(int degrees) throws Exception { + if (degrees > 360) degrees %= 360; + if (degrees == 0) { + tm = new float[] { 1f, 0f, 0f, 1f}; + } + else if (degrees == 90) { + tm = new float[] { 0f, 1f, -1f, 0f}; + } + else if (degrees == 180) { + tm = new float[] {-1f, 0f, 0f, -1f}; + } + else if (degrees == 270) { + tm = new float[] { 0f, -1f, 1f, 0f}; + } + else if (degrees == 360) { + tm = new float[] { 1f, 0f, 0f, 1f}; + } + else { + float sinOfAngle = (float) Math.sin(degrees * (Math.PI / 180)); + float cosOfAngle = (float) Math.cos(degrees * (Math.PI / 180)); + tm = new float[] {cosOfAngle, sinOfAngle, -sinOfAngle, cosOfAngle}; + } + } + + + /** + * Draws a bezier curve starting from the current point. + * Please note: You must call the fillPath, closePath or strokePath method after the last bezierCurveTo call. + *

Author: Pieter Libin, pieter@emweb.be

+ * + * @param p1 first control point + * @param p2 second control point + * @param p3 end point + */ + public void bezierCurveTo(Point p1, Point p2, Point p3) throws IOException { + append(p1); + append(p2); + append(p3); + append("c\n"); + } + + + /** + * Sets the start of text block. + * Please see Example_32. This method must have matching call to setTextEnd(). + */ + public void setTextStart() throws IOException { + append("BT\n"); + } + + + /** + * Sets the text location. + * Please see Example_32. + * + * @param x the x coordinate of new text location. + * @param y the y coordinate of new text location. + */ + public void setTextLocation(float x, float y) throws IOException { + append(x); + append(' '); + append(height - y); + append(" Td\n"); + } + + + public void setTextBegin(float x, float y) throws IOException { + append("BT\n"); + append(x); + append(' '); + append(height - y); + append(" Td\n"); + } + + + /** + * Sets the text leading. + * Please see Example_32. + * + * @param leading the leading. + */ + public void setTextLeading(float leading) throws IOException { + append(leading); + append(" TL\n"); + } + + + public void setCharSpacing(float spacing) throws IOException { + append(spacing); + append(" Tc\n"); + } + + + public void setWordSpacing(float spacing) throws IOException { + append(spacing); + append(" Tw\n"); + } + + + public void setTextScaling(float scaling) throws IOException { + append(scaling); + append(" Tz\n"); + } + + + public void setTextRise(float rise) throws IOException { + append(rise); + append(" Ts\n"); + } + + + public void setTextFont(Font font) throws IOException { + this.font = font; + append("/F"); + append(font.objNumber); + append(' '); + append(font.size); + append(" Tf\n"); + } + + + /** + * Prints a line of text and moves to the next line. + * Please see Example_32. + */ + public void println(String str) throws IOException { + print(str); + println(); + } + + + /** + * Prints a line of text. + * Please see Example_32. + */ + public void print(String str) throws IOException { + if (font == null) { + return; + } + append("[<"); + drawString(font, str); + append(">] TJ\n"); + } + + + /** + * Move to the next line. + * Please see Example_32. + */ + public void println() throws IOException { + append("T*\n"); + } + + + /** + * Sets the end of text block. + * Please see Example_32. + */ + public void setTextEnd() throws IOException { + append("ET\n"); + } + + + // Code provided by: + // Dominique Andre Gunia + // << + public void drawRectRoundCorners( + float x, float y, float w, float h, float r1, float r2, char operation) + throws Exception { + + // The best 4-spline magic number + float m4 = 0.551784f; + + List list = new ArrayList(); + + // Starting point + list.add(new Point(x + w - r1, y)); + list.add(new Point(x + w - r1 + m4*r1, y, Point.CONTROL_POINT)); + list.add(new Point(x + w, y + r2 - m4*r2, Point.CONTROL_POINT)); + list.add(new Point(x + w, y + r2)); + + list.add(new Point(x + w, y + h - r2)); + list.add(new Point(x + w, y + h - r2 + m4*r2, Point.CONTROL_POINT)); + list.add(new Point(x + w - m4*r1, y + h, Point.CONTROL_POINT)); + list.add(new Point(x + w - r1, y + h)); + + list.add(new Point(x + r1, y + h)); + list.add(new Point(x + r1 - m4*r1, y + h, Point.CONTROL_POINT)); + list.add(new Point(x, y + h - m4*r2, Point.CONTROL_POINT)); + list.add(new Point(x, y + h - r2)); + + list.add(new Point(x, y + r2)); + list.add(new Point(x, y + r2 - m4*r2, Point.CONTROL_POINT)); + list.add(new Point(x + m4*r1, y, Point.CONTROL_POINT)); + list.add(new Point(x + r1, y)); + list.add(new Point(x + w - r1, y)); + + drawPath(list, operation); + } + + + /** + * Clips the path. + */ + public void clipPath() throws IOException { + append("W\n"); + append("n\n"); // Close the path without painting it. + } + + + public void clipRect(float x, float y, float w, float h) + throws IOException { + moveTo(x, y); + lineTo(x + w, y); + lineTo(x + w, y + h); + lineTo(x, y + h); + clipPath(); + } + + + public void save() throws IOException { + append("q\n"); + savedStates.add(new State( + pen, brush, pen_width, line_cap_style, line_join_style, linePattern)); + savedHeight = height; + } + + + public void restore() throws IOException { + append("Q\n"); + if (savedStates.size() > 0) { + State savedState = savedStates.remove(savedStates.size() - 1); + pen = savedState.getPen(); + brush = savedState.getBrush(); + pen_width = savedState.getPenWidth(); + line_cap_style = savedState.getLineCapStyle(); + line_join_style = savedState.getLineJoinStyle(); + linePattern = savedState.getLinePattern(); + } + if (savedHeight != Float.MAX_VALUE) { + height = savedHeight; + savedHeight = Float.MAX_VALUE; + } + } + // << + + + /** + * Sets the page CropBox. + * See page 77 of the PDF32000_2008.pdf specification. + * + * @param upperLeftX the top left X coordinate of the CropBox. + * @param upperLeftY the top left Y coordinate of the CropBox. + * @param lowerRightX the bottom right X coordinate of the CropBox. + * @param lowerRightY the bottom right Y coordinate of the CropBox. + */ + public void setCropBox( + float upperLeftX, float upperLeftY, float lowerRightX, float lowerRightY) { + this.cropBox = new float[] {upperLeftX, upperLeftY, lowerRightX, lowerRightY}; + } + + + /** + * Sets the page BleedBox. + * See page 77 of the PDF32000_2008.pdf specification. + * + * @param upperLeftX the top left X coordinate of the BleedBox. + * @param upperLeftY the top left Y coordinate of the BleedBox. + * @param lowerRightX the bottom right X coordinate of the BleedBox. + * @param lowerRightY the bottom right Y coordinate of the BleedBox. + */ + public void setBleedBox( + float upperLeftX, float upperLeftY, float lowerRightX, float lowerRightY) { + this.bleedBox = new float[] {upperLeftX, upperLeftY, lowerRightX, lowerRightY}; + } + + + /** + * Sets the page TrimBox. + * See page 77 of the PDF32000_2008.pdf specification. + * + * @param upperLeftX the top left X coordinate of the TrimBox. + * @param upperLeftY the top left Y coordinate of the TrimBox. + * @param lowerRightX the bottom right X coordinate of the TrimBox. + * @param lowerRightY the bottom right Y coordinate of the TrimBox. + */ + public void setTrimBox( + float upperLeftX, float upperLeftY, float lowerRightX, float lowerRightY) { + this.trimBox = new float[] {upperLeftX, upperLeftY, lowerRightX, lowerRightY}; + } + + + /** + * Sets the page ArtBox. + * See page 77 of the PDF32000_2008.pdf specification. + * + * @param upperLeftX the top left X coordinate of the ArtBox. + * @param upperLeftY the top left Y coordinate of the ArtBox. + * @param lowerRightX the bottom right X coordinate of the ArtBox. + * @param lowerRightY the bottom right Y coordinate of the ArtBox. + */ + public void setArtBox( + float upperLeftX, float upperLeftY, float lowerRightX, float lowerRightY) { + this.artBox = new float[] {upperLeftX, upperLeftY, lowerRightX, lowerRightY}; + } + + + private void appendPointXY(float x, float y) throws IOException { + append(x); + append(' '); + append(height - y); + append(' '); + } + + + private void append(Point point) throws IOException { + append(point.x); + append(' '); + append(height - point.y); + append(' '); + } + + + protected void append(String str) throws IOException { + int len = str.length(); + for (int i = 0; i < len; i++) { + buf.write((byte) str.charAt(i)); + } + } + + + protected void append(int num) throws IOException { + append(Integer.toString(num)); + } + + + protected void append(float val) throws IOException { + append(PDF.df.format(val)); + } + + + protected void append(char ch) throws IOException { + buf.write((byte) ch); + } + + + protected void append(byte b) throws IOException { + buf.write(b); + } + + + /** + * Appends the specified array of bytes to the page. + */ + public void append(byte[] buffer) throws IOException { + buf.write(buffer); + } + + + protected void drawString( + Font font, + String str, + float x, + float y, + Map colors) throws Exception { + setTextBegin(x, y); + setTextFont(font); + + StringBuilder buf1 = new StringBuilder(); + StringBuilder buf2 = new StringBuilder(); + for (int i = 0; i < str.length(); i++) { + char ch = str.charAt(i); + if (Character.isLetterOrDigit(ch)) { + printBuffer(buf2, colors); + buf1.append(ch); + } + else { + printBuffer(buf1, colors); + buf2.append(ch); + } + } + printBuffer(buf1, colors); + printBuffer(buf2, colors); + + setTextEnd(); + } + + + private void printBuffer( + StringBuilder buf, + Map colors) throws Exception { + String str = buf.toString(); + if (str.length() > 0) { + if (colors.containsKey(str)) { + setBrushColor(colors.get(str)); + } + else { + setBrushColor(Color.black); + } + } + print(str); + buf.setLength(0); + } + + + protected void setStructElementsPageObjNumber( + int pageObjNumber) throws Exception { + for (StructElem element : structures) { + element.pageObjNumber = pageObjNumber; + } + } + + + public void addBMC( + String structure, + String altDescription, + String actualText) throws Exception { + addBMC(structure, null, altDescription, actualText); + } + + + public void addBMC( + String structure, + String language, + String altDescription, + String actualText) throws Exception { + if (pdf.compliance == Compliance.PDF_UA) { + StructElem element = new StructElem(); + element.structure = structure; + element.mcid = mcid; + element.language = language; + element.altDescription = altDescription; + element.actualText = actualText; + structures.add(element); + + append("/"); + append(structure); + append(" <>\n"); + append("BDC\n"); + } + } + + + public void addEMC() throws Exception { + if (pdf.compliance == Compliance.PDF_UA) { + append("EMC\n"); + } + } + + + protected void addAnnotation(Annotation annotation) { + annots.add(annotation); + if (pdf.compliance == Compliance.PDF_UA) { + StructElem element = new StructElem(); + element.structure = StructElem.LINK; + element.language = annotation.language; + element.altDescription = annotation.altDescription; + element.actualText = annotation.actualText; + element.annotation = annotation; + structures.add(element); + } + } + + + protected void beginTransform( + float x, float y, float xScale, float yScale) throws Exception { + append("q\n"); + + append(xScale); + append(" 0 0 "); + append(yScale); + append(' '); + append(x); + append(' '); + append(y); + append(" cm\n"); + + append(xScale); + append(" 0 0 "); + append(yScale); + append(' '); + append(x); + append(' '); + append(y); + append(" Tm\n"); + } + + + protected void endTransform() throws Exception { + append("Q\n"); + } + + + public void drawContents( + byte[] content, + float h, // The height of the graphics object in points. + float x, + float y, + float xScale, + float yScale) throws Exception { + beginTransform(x, (this.height - yScale * h) - y, xScale, yScale); + append(content); + endTransform(); + } + + + public void drawString( + Font font, String str, float x, float y, float dx) throws Exception { + float x1 = x; + for (int i = 0; i < str.length(); i++) { + drawString(font, str.substring(i, i + 1), x1, y); + x1 += dx; + } + } + + + public void addWatermark( + Font font, String text) throws Exception { + float hypotenuse = (float) + Math.sqrt(this.height * this.height + this.width * this.width); + float stringWidth = font.stringWidth(text); + float offset = (hypotenuse - stringWidth) / 2f; + double angle = Math.atan(this.height / this.width); + TextLine watermark = new TextLine(font); + watermark.setColor(Color.lightgrey); + watermark.setText(text); + watermark.setLocation( + (float) (offset * Math.cos(angle)), + (this.height - (float) (offset * Math.sin(angle)))); + watermark.setTextDirection((int) (angle * (180.0 / Math.PI))); + watermark.drawOn(this); + } + + + public void invertYAxis() throws Exception { + append("1 0 0 -1 0 "); + append(this.height); + append(" cm\n"); + } + + + /** + * Transformation matrix. + * Use save before, restore afterwards! + * 9 value array like generated by androids Matrix.getValues() + * + * @throws IOException + */ + public void transform(float[] values) throws IOException { + float scalex = (values[MSCALE_X]); + float scaley = (values[MSCALE_Y]); + float transx = values[MTRANS_X]; + float transy = values[MTRANS_Y]; + + append(scalex); + append(" "); + append(values[MSKEW_X]); + append(" "); + append(values[MSKEW_Y]); + append(" "); + append(scaley); + append(" "); + + if (Math.asin(values[MSKEW_Y]) != 0f) { + transx -= values[MSKEW_Y] * height / scaley; + } + + append(transx); + append(" "); + append(-transy); + append(" cm\n"); + + // Weil mit der Hoehe immer die Y-Koordinate im PDF-Koordinatensystem berechnet wird: + height = height / scaley; + } + +} // End of Page.java diff --git a/PDFJet/src/main/java/com/pdfjet/PageLayout.java b/PDFJet/src/main/java/com/pdfjet/PageLayout.java new file mode 100644 index 0000000..6dd924b --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/PageLayout.java @@ -0,0 +1,44 @@ +/** + * PageLayout.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + + +/** + * Used to specify the PDF page layout. + * + */ +public class PageLayout { + public static final String SINGLE_PAGE = "SinglePage"; // Display one page at a time + public static final String ONE_COLUMN = "OneColumn"; // Display the pages in one column + public static final String TWO_COLUMN_LEFT = "TwoColumnLeft"; // Odd-numbered pages on the left + public static final String TWO_COLUMN_RIGTH = "TwoColumnRight"; // Odd-numbered pages on the right + public static final String TWO_PAGE_LEFT = "TwoPageLeft"; // Odd-numbered pages on the left + public static final String TWO_PAGE_RIGTH = "TwoPageRight"; // Odd-numbered pages on the right +} diff --git a/PDFJet/src/main/java/com/pdfjet/PageMode.java b/PDFJet/src/main/java/com/pdfjet/PageMode.java new file mode 100644 index 0000000..d9f4247 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/PageMode.java @@ -0,0 +1,44 @@ +/** + * PageMode.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + + +/** + * Used to specify the PDF page mode. + * + */ +public class PageMode { + public static final String USE_NONE = "UseNone"; // Neither document outline nor thumbnail images visible + public static final String USE_OUTLINES = "UseOutlines"; // Document outline visible + public static final String USE_THUMBS = "UseThumbs"; // Thumbnail images visible + public static final String FULL_SCREEN = "FullScreen"; // Full-screen mode + public static final String USE_OC = "UseOC"; // (PDF 1.5) Optional content group panel visible + public static final String USE_ATTACHMENTS = "UseAttachements"; +} diff --git a/PDFJet/src/main/java/com/pdfjet/Paragraph.java b/PDFJet/src/main/java/com/pdfjet/Paragraph.java new file mode 100644 index 0000000..738efac --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Paragraph.java @@ -0,0 +1,75 @@ +/** + * Paragraph.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. +*/ + +package com.pdfjet; + +import java.util.*; + + +/** + * Used to create paragraph objects. + * See the TextColumn class for more information. + * + */ +public class Paragraph { + + protected List list = null; + protected int alignment = Align.LEFT; + + + /** + * Constructor for creating paragraph objects. + * + */ + public Paragraph() { + list = new ArrayList(); + } + + + public Paragraph(TextLine text) { + list = new ArrayList(); + list.add(text); + } + + + /** + * Adds a text line to this paragraph. + * + * @param text the text line to add to this paragraph. + * @return this paragraph. + */ + public Paragraph add(TextLine text) { + list.add(text); + return this; + } + + + /** + * Removes the last text line added to this paragraph. + * + */ + public void removeLastTextLine() { + if (list.size() >= 1) { + list.remove(list.size() - 1); + } + } + + + /** + * Sets the alignment of the text in this paragraph. + * + * @param alignment the alignment code. + * @return this paragraph. + * + *
Supported values: Align.LEFT, Align.RIGHT, Align.CENTER and Align.JUSTIFY.
+ */ + public Paragraph setAlignment(int alignment) { + this.alignment = alignment; + return this; + } + +} // End of Paragraph.java diff --git a/PDFJet/src/main/java/com/pdfjet/Path.java b/PDFJet/src/main/java/com/pdfjet/Path.java new file mode 100644 index 0000000..b8499a1 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Path.java @@ -0,0 +1,370 @@ +/** + * Path.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + +import java.util.*; + + +/** + * Used to create path objects. + * The path objects may consist of lines, splines or both. + * + * Please see Example_02. + */ +public class Path implements Drawable { + + private int color = Color.black; + private float width = 0.3f; + private String pattern = "[] 0"; + private boolean fill_shape = false; + private boolean close_path = false; + + private List points = null; + + private float box_x; + private float box_y; + + private int lineCapStyle = 0; + private int lineJoinStyle = 0; + + + /** + * The default constructor. + * + * + */ + public Path() { + points = new ArrayList(); + } + + + /** + * Adds a point to this path. + * + * @param point the point to add. + */ + public void add(Point point) { + points.add(point); + } + + + /** + * Sets the line dash pattern for this path. + * + * The line dash pattern controls the pattern of dashes and gaps used to stroke paths. + * It is specified by a dash array and a dash phase. + * The elements of the dash array are positive numbers that specify the lengths of + * alternating dashes and gaps. + * The dash phase specifies the distance into the dash pattern at which to start the dash. + * The elements of both the dash array and the dash phase are expressed in user space units. + *
+     *  Examples of line dash patterns:
+     *
+     *      "[Array] Phase"     Appearance          Description
+     *      _______________     _________________   ____________________________________
+     *
+     *      "[] 0"              -----------------   Solid line
+     *      "[3] 0"             ---   ---   ---     3 units on, 3 units off, ...
+     *      "[2] 1"             -  --  --  --  --   1 on, 2 off, 2 on, 2 off, ...
+     *      "[2 1] 0"           -- -- -- -- -- --   2 on, 1 off, 2 on, 1 off, ...
+     *      "[3 5] 6"             ---     ---       2 off, 3 on, 5 off, 3 on, 5 off, ...
+     *      "[2 3] 11"          -   --   --   --    1 on, 3 off, 2 on, 3 off, 2 on, ...
+     *  
+ * + * @param pattern the line dash pattern. + */ + public void setPattern(String pattern) { + this.pattern = pattern; + } + + + /** + * Sets the pen width that will be used to draw the lines and splines that are part of this path. + * + * @param width the pen width. + */ + public void setWidth(double width) { + this.width = (float) width; + } + + + /** + * Sets the pen width that will be used to draw the lines and splines that are part of this path. + * + * @param width the pen width. + */ + public void setWidth(float width) { + this.width = width; + } + + + /** + * Sets the pen color that will be used to draw this path. + * + * @param color the color is specified as an integer. + */ + public void setColor(int color) { + this.color = color; + } + + + /** + * Sets the close_path variable. + * + * @param close_path if close_path is true a line will be draw between the first and last point of this path. + */ + public void setClosePath(boolean close_path) { + this.close_path = close_path; + } + + + /** + * Sets the fill_shape private variable. If fill_shape is true - the shape of the path will be filled with the current brush color. + * + * @param fill_shape the fill_shape flag. + */ + public void setFillShape(boolean fill_shape) { + this.fill_shape = fill_shape; + } + + + /** + * Sets the line cap style. + * + * @param style the cap style of this path. Supported values: Cap.BUTT, Cap.ROUND and Cap.PROJECTING_SQUARE + */ + public void setLineCapStyle(int style) { + this.lineCapStyle = style; + } + + + /** + * Returns the line cap style for this path. + * + * @return the line cap style for this path. + */ + public int getLineCapStyle() { + return this.lineCapStyle; + } + + + /** + * Sets the line join style. + * + * @param style the line join style code. Supported values: Join.MITER, Join.ROUND and Join.BEVEL + */ + public void setLineJoinStyle(int style) { + this.lineJoinStyle = style; + } + + + /** + * Returns the line join style. + * + * @return the line join style. + */ + public int getLineJoinStyle() { + return this.lineJoinStyle; + } + + + /** + * Places this path in the specified box at position (0.0, 0.0). + * + * @param box the specified box. + */ + public void placeIn(Box box) throws Exception { + placeIn(box, 0.0f, 0.0f); + } + + + /** + * Places the path inside the spacified box at coordinates (x_offset, y_offset) of the top left corner. + * + * @param box the specified box. + * @param x_offset the x_offset. + * @param y_offset the y_offset. + */ + public void placeIn( + Box box, + double x_offset, + double y_offset) throws Exception { + placeIn(box, (float) x_offset, (float) y_offset); + } + + + /** + * Places the path inside the spacified box at coordinates (x_offset, y_offset) of the top left corner. + * + * @param box the specified box. + * @param x_offset the x_offset. + * @param y_offset the y_offset. + */ + public void placeIn( + Box box, + float x_offset, + float y_offset) throws Exception { + box_x = box.x + x_offset; + box_y = box.y + y_offset; + } + + + public void setLocation(float x, float y) { + box_x += x; + box_y += y; + } + + + /** + * Scales the path using the specified factor. + * + * @param factor the specified factor. + */ + public void scaleBy(double factor) throws Exception { + scaleBy((float) factor); + } + + + /** + * Scales the path using the specified factor. + * + * @param factor the specified factor. + */ + public void scaleBy(float factor) throws Exception { + for (int i = 0; i < points.size(); i++) { + Point point = points.get(i); + point.x *= factor; + point.y *= factor; + } + } + + + /** + * Returns a list containing the start point, first control point, second control point and the end point of elliptical curve segment. + * Please see Example_18. + * + * @param x the x coordinate of the center of the ellipse. + * @param y the y coordinate of the center of the ellipse. + * @param r1 the horizontal radius of the ellipse. + * @param r2 the vertical radius of the ellipse. + * @param segment the segment to draw - please see the Segment class. + * @return a list of the curve points. + * @throws Exception + */ + public static List getCurvePoints( + float x, + float y, + float r1, + float r2, + int segment) throws Exception { + // The best 4-spline magic number + float m4 = 0.551784f; + List list = new ArrayList(); + + if (segment == 0) { + list.add(new Point(x, y - r2)); + list.add(new Point(x + m4*r1, y - r2, Point.CONTROL_POINT)); + list.add(new Point(x + r1, y - m4*r2, Point.CONTROL_POINT)); + list.add(new Point(x + r1, y)); + } + else if (segment == 1) { + list.add(new Point(x + r1, y)); + list.add(new Point(x + r1, y + m4*r2, Point.CONTROL_POINT)); + list.add(new Point(x + m4*r1, y + r2, Point.CONTROL_POINT)); + list.add(new Point(x, y + r2)); + } + else if (segment == 2) { + list.add(new Point(x, y + r2)); + list.add(new Point(x - m4*r1, y + r2, Point.CONTROL_POINT)); + list.add(new Point(x - r1, y + m4*r2, Point.CONTROL_POINT)); + list.add(new Point(x - r1, y)); + } + else if (segment == 3) { + list.add(new Point(x - r1, y)); + list.add(new Point(x - r1, y - m4*r2, Point.CONTROL_POINT)); + list.add(new Point(x - m4*r1, y - r2, Point.CONTROL_POINT)); + list.add(new Point(x, y - r2)); + } + + return list; + } + + + /** + * Draws this path on the page using the current selected color, pen width, line pattern and line join style. + * + * @param page the page to draw this path on. + * @return x and y coordinates of the bottom right corner of this component. + * @throws Exception + */ + public float[] drawOn(Page page) throws Exception { + if (fill_shape) { + page.setBrushColor(color); + } + else { + page.setPenColor(color); + } + page.setPenWidth(width); + page.setLinePattern(pattern); + page.setLineCapStyle(lineCapStyle); + page.setLineJoinStyle(lineJoinStyle); + + for (int i = 0; i < points.size(); i++) { + Point point = points.get(i); + point.x += box_x; + point.y += box_y; + } + + if (fill_shape) { + page.drawPath(points, 'f'); + } + else { + if (close_path) { + page.drawPath(points, 's'); + } + else { + page.drawPath(points, 'S'); + } + } + + float x_max = 0f; + float y_max = 0f; + for (int i = 0; i < points.size(); i++) { + Point point = points.get(i); + if (point.x > x_max) { x_max = point.x; } + if (point.y > y_max) { y_max = point.y; } + point.x -= box_x; + point.y -= box_y; + } + + return new float[] {x_max, y_max}; + } + +} // End of Path.java diff --git a/PDFJet/src/main/java/com/pdfjet/PlainText.java b/PDFJet/src/main/java/com/pdfjet/PlainText.java new file mode 100644 index 0000000..5f59cf4 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/PlainText.java @@ -0,0 +1,180 @@ +/** + * PlainText.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + +import java.util.*; + +/** + * Please see Example_45 + */ +public class PlainText implements Drawable { + + private Font font; + private String[] textLines; + private float fontSize; + private float x; + private float y; + private float w = 500f; + private float leading; + private int backgroundColor = Color.white; + private int borderColor = Color.white; + private int textColor = Color.black; + private List endOfLinePoints = null; + + private String language = null; + private String altDescription = null; + private String actualText = null; + + + public PlainText(Font font, String[] textLines) { + this.font = font; + this.fontSize = font.getSize(); + this.textLines = textLines; + this.endOfLinePoints = new ArrayList(); + StringBuilder buf = new StringBuilder(); + for (String str : textLines) { + buf.append(str); + buf.append(' '); + } + this.altDescription = buf.toString(); + this.actualText = buf.toString(); + } + + + public PlainText setFontSize(float fontSize) { + this.fontSize = fontSize; + return this; + } + + + public PlainText setLocation(float x, float y) { + this.x = x; + this.y = y; + return this; + } + + + public PlainText setWidth(float w) { + this.w = w; + return this; + } + + + public PlainText setLeading(float leading) { + this.leading = leading; + return this; + } + + + public PlainText setBackgroundColor(int backgroundColor) { + this.backgroundColor = backgroundColor; + return this; + } + + + public PlainText setBorderColor(int borderColor) { + this.borderColor = borderColor; + return this; + } + + + public PlainText setTextColor(int textColor) { + this.textColor = textColor; + return this; + } + + + public List getEndOfLinePoints() { + return endOfLinePoints; + } + + + /** + * Draws this PlainText on the specified page. + * + * @param page the page to draw this PlainText on. + * @return x and y coordinates of the bottom right corner of this component. + * @throws Exception + */ + public float[] drawOn(Page page) throws Exception { + float originalSize = font.getSize(); + font.setSize(fontSize); + float y_text = y + font.getAscent(); + + page.addBMC(StructElem.SPAN, language, Single.space, Single.space); + page.setBrushColor(backgroundColor); + leading = font.getBodyHeight(); + float h = font.getBodyHeight() * textLines.length; + page.fillRect(x, y, w, h); + page.setPenColor(borderColor); + page.setPenWidth(0f); + page.drawRect(x, y, w, h); + page.addEMC(); + + page.addBMC(StructElem.SPAN, language, altDescription, actualText); + page.setTextStart(); + page.setTextFont(font); + page.setBrushColor(textColor); + page.setTextLeading(leading); + page.setTextLocation(x, y_text); + for (String str : textLines) { + if (font.skew15) { + setTextSkew(page, 0.26f, x, y_text); + } + page.println(str); + endOfLinePoints.add(new float[] { x + font.stringWidth(str), y_text }); + y_text += leading; + } + page.setTextEnd(); + page.addEMC(); + + font.setSize(originalSize); + + return new float[] { x + w, y + h }; + } + + + private void setTextSkew( + Page page, float skew, float x, float y) throws Exception { + page.append(1f); + page.append(' '); + page.append(0f); + page.append(' '); + page.append(skew); + page.append(' '); + page.append(1f); + page.append(' '); + page.append(x); + page.append(' '); + page.append(page.height - y); + page.append(" Tm\n"); + } + +} // End of PlainText.java diff --git a/PDFJet/src/main/java/com/pdfjet/Point.java b/PDFJet/src/main/java/com/pdfjet/Point.java new file mode 100644 index 0000000..7354fe2 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Point.java @@ -0,0 +1,592 @@ +/** + * Point.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + + +/** + * Used to create point objects with different shapes and draw them on a page. + * Please note: When we are mentioning (x, y) coordinates of a point - we are talking about the coordinates of the center of the point. + * + * Please see Example_05. + */ +public class Point implements Drawable { + + public static final int INVISIBLE = -1; + public static final int CIRCLE = 0; + public static final int DIAMOND = 1; + public static final int BOX = 2; + public static final int PLUS = 3; + public static final int H_DASH = 4; + public static final int V_DASH = 5; + public static final int MULTIPLY = 6; + public static final int STAR = 7; + public static final int X_MARK = 8; + public static final int UP_ARROW = 9; + public static final int DOWN_ARROW = 10; + public static final int LEFT_ARROW = 11; + public static final int RIGHT_ARROW = 12; + + public static final boolean CONTROL_POINT = true; + + protected float x; + protected float y; + protected float r = 2f; + protected int shape = Point.CIRCLE; + protected int color = Color.black; + protected int align = Align.RIGHT; + protected float lineWidth = 0.3f; + protected String linePattern = "[] 0"; + protected boolean fillShape = false; + protected boolean isControlPoint = false; + protected boolean isStartOfPath = false; + + private String text; + private int textColor; + private int textDirection; + private String uri; + private float box_x; + private float box_y; + + /** + * The default constructor. + */ + public Point() { + } + + + /** + * Constructor for creating point objects. + * + * @param x the x coordinate of this point when drawn on the page. + * @param y the y coordinate of this point when drawn on the page. + */ + public Point(double x, double y) { + this((float) x, (float) y); + } + + + /** + * Constructor for creating point objects. + * + * @param x the x coordinate of this point when drawn on the page. + * @param y the y coordinate of this point when drawn on the page. + */ + public Point(float x, float y) { + this.x = x; + this.y = y; + } + + + /** + * Constructor for creating point objects. + * + * @param x the x coordinate of this point when drawn on the page. + * @param y the y coordinate of this point when drawn on the page. + * @param isControlPoint true if this point is one of the points specifying a curve. + */ + public Point(double x, double y, boolean isControlPoint) { + this((float) x, (float) y, isControlPoint); + } + + + /** + * Constructor for creating point objects. + * + * @param x the x coordinate of this point when drawn on the page. + * @param y the y coordinate of this point when drawn on the page. + * @param isControlPoint true if this point is one of the points specifying a curve. + */ + public Point(float x, float y, boolean isControlPoint) { + this.x = x; + this.y = y; + this.isControlPoint = isControlPoint; + } + + + /** + * Sets the position (x, y) of this point. + * + * @param x the x coordinate of this point when drawn on the page. + * @param y the y coordinate of this point when drawn on the page. + */ + public void setPosition(double x, double y) { + setPosition((float) x, (float) y); + } + + + /** + * Sets the position (x, y) of this point. + * + * @param x the x coordinate of this point when drawn on the page. + * @param y the y coordinate of this point when drawn on the page. + */ + public void setPosition(float x, float y) { + setLocation(x, y); + } + + + /** + * Sets the location (x, y) of this point. + * + * @param x the x coordinate of this point when drawn on the page. + * @param y the y coordinate of this point when drawn on the page. + */ + public void setLocation(float x, float y) { + this.x = x; + this.y = y; + } + + + /** + * Sets the x coordinate of this point. + * + * @param x the x coordinate of this point when drawn on the page. + */ + public void setX(double x) { + this.x = (float) x; + } + + + /** + * Sets the x coordinate of this point. + * + * @param x the x coordinate of this point when drawn on the page. + */ + public void setX(float x) { + this.x = x; + } + + + /** + * Returns the x coordinate of this point. + * + * @return the x coordinate of this point. + */ + public float getX() { + return x; + } + + + /** + * Sets the y coordinate of this point. + * + * @param y the y coordinate of this point when drawn on the page. + */ + public void setY(double y) { + this.y = (float) y; + } + + + /** + * Sets the y coordinate of this point. + * + * @param y the y coordinate of this point when drawn on the page. + */ + public void setY(float y) { + this.y = y; + } + + + /** + * Returns the y coordinate of this point. + * + * @return the y coordinate of this point. + */ + public float getY() { + return y; + } + + + /** + * Sets the radius of this point. + * + * @param r the radius. + */ + public void setRadius(double r) { + this.r = (float) r; + } + + + /** + * Sets the radius of this point. + * + * @param r the radius. + */ + public void setRadius(float r) { + this.r = r; + } + + + /** + * Returns the radius of this point. + * + * @return the radius of this point. + */ + public float getRadius() { + return r; + } + + + /** + * Sets the shape of this point. + * + * @param shape the shape of this point. Supported values: + *
+     *  Point.INVISIBLE
+     *  Point.CIRCLE
+     *  Point.DIAMOND
+     *  Point.BOX
+     *  Point.PLUS
+     *  Point.H_DASH
+     *  Point.V_DASH
+     *  Point.MULTIPLY
+     *  Point.STAR
+     *  Point.X_MARK
+     *  Point.UP_ARROW
+     *  Point.DOWN_ARROW
+     *  Point.LEFT_ARROW
+     *  Point.RIGHT_ARROW
+     *  
+ */ + public void setShape(int shape) { + this.shape = shape; + } + + + /** + * Returns the point shape code value. + * + * @return the shape code value. + */ + public int getShape() { + return shape; + } + + + /** + * Sets the private fillShape variable. + * + * @param fillShape if true - fill the point with the specified brush color. + */ + public void setFillShape(boolean fillShape) { + this.fillShape = fillShape; + } + + + /** + * Returns the value of the fillShape private variable. + * + * @return the value of the private fillShape variable. + */ + public boolean getFillShape() { + return this.fillShape; + } + + + /** + * Sets the pen color for this point. + * + * @param color the color specified as an integer. + */ + public void setColor(int color) { + this.color = color; + } + + + /** + * Returns the point color as an integer. + * + * @return the color. + */ + public int getColor() { + return this.color; + } + + + /** + * Sets the width of the lines of this point. + * + * @param lineWidth the line width. + */ + public void setLineWidth(double lineWidth) { + this.lineWidth = (float) lineWidth; + } + + + /** + * Sets the width of the lines of this point. + * + * @param lineWidth the line width. + */ + public void setLineWidth(float lineWidth) { + this.lineWidth = lineWidth; + } + + + /** + * Returns the width of the lines used to draw this point. + * + * @return the width of the lines used to draw this point. + */ + public float getLineWidth() { + return lineWidth; + } + + + /** + * + * The line dash pattern controls the pattern of dashes and gaps used to stroke paths. + * It is specified by a dash array and a dash phase. + * The elements of the dash array are positive numbers that specify the lengths of + * alternating dashes and gaps. + * The dash phase specifies the distance into the dash pattern at which to start the dash. + * The elements of both the dash array and the dash phase are expressed in user space units. + *
+     *  Examples of line dash patterns:
+     *
+     *      "[Array] Phase"     Appearance          Description
+     *      _______________     _________________   ____________________________________
+     *
+     *      "[] 0"              -----------------   Solid line
+     *      "[3] 0"             ---   ---   ---     3 units on, 3 units off, ...
+     *      "[2] 1"             -  --  --  --  --   1 on, 2 off, 2 on, 2 off, ...
+     *      "[2 1] 0"           -- -- -- -- -- --   2 on, 1 off, 2 on, 1 off, ...
+     *      "[3 5] 6"             ---     ---       2 off, 3 on, 5 off, 3 on, 5 off, ...
+     *      "[2 3] 11"          -   --   --   --    1 on, 3 off, 2 on, 3 off, 2 on, ...
+     *  
+ * + * @param linePattern the line dash pattern. + */ + public void setLinePattern(String linePattern) { + this.linePattern = linePattern; + } + + + /** + * Returns the line dash pattern. + * + * @return the line dash pattern. + */ + public String getLinePattern() { + return linePattern; + } + + + /** + * @deprecated + * Please use the setStartOfPath method. + * See Example_40. + * + * @param drawLineTo the boolean value. + */ + @Deprecated + public void setDrawLineTo(boolean drawLineTo) { + this.isStartOfPath = drawLineTo; + } + + + /** + * Sets this point as the start of a path that will be drawn on the chart. + * + */ + public void setStartOfPath() { + this.isStartOfPath = true; + } + + + /** + * Sets the URI for the "click point" action. + * + * @param uri the URI + */ + public void setURIAction(String uri) { + this.uri = uri; + } + + + /** + * Returns the URI for the "click point" action. + * + * @return the URI for the "click point" action. + */ + public String getURIAction() { + return uri; + } + + + /** + * Sets the point text. + * + * @param text the text. + */ + public void setText(String text) { + this.text = text; + } + + + /** + * Returns the text associated with this point. + * + * @return the text. + */ + public String getText() { + return this.text; + } + + + /** + * Sets the point's text color. + * + * @param textColor the text color. + */ + public void setTextColor(int textColor) { + this.textColor = textColor; + } + + + /** + * Returns the point's text color. + * + * @return the text color. + */ + public int getTextColor() { + return this.textColor; + } + + + /** + * Sets the point's text direction. + * + * @param textDirection the text direction. + */ + public void setTextDirection(int textDirection) { + this.textDirection = textDirection; + } + + + /** + * Returns the point's text direction. + * + * @return the text direction. + */ + public int getTextDirection() { + return this.textDirection; + } + + + /** + * Sets the point alignment inside table cell. + * + * @param align the alignment value. + */ + public void setAlignment(int align) { + this.align = align; + } + + + /** + * Returns the point alignment. + * + * @return align the alignment value. + */ + public int getAlignment() { + return this.align; + } + + + /** + * Places this point in the specified box at position (0f, 0f). + * + * @param box the specified box. + */ + public void placeIn(Box box) throws Exception { + placeIn(box, 0f, 0f); + } + + + /** + * Places this point in the specified box. + * + * @param box the specified box. + * @param x_offset the x offset from the top left corner of the box. + * @param y_offset the y offset from the top left corner of the box. + */ + public void placeIn( + Box box, + double x_offset, + double y_offset) throws Exception { + placeIn(box, (float) x_offset, (float) y_offset); + } + + + /** + * Places this point in the specified box. + * + * @param box the specified box. + * @param x_offset the x offset from the top left corner of the box. + * @param y_offset the y offset from the top left corner of the box. + */ + public void placeIn( + Box box, + float x_offset, + float y_offset) throws Exception { + box_x = box.x + x_offset; + box_y = box.y + y_offset; + } + + + /** + * Draws this point on the specified page. + * + * @param page the page to draw this point on. + * @return x and y coordinates of the bottom right corner of this component. + * @throws Exception + */ + public float[] drawOn(Page page) throws Exception { + page.setPenWidth(lineWidth); + page.setLinePattern(linePattern); + + if (fillShape) { + page.setBrushColor(color); + } + else { + page.setPenColor(color); + } + + x += box_x; + y += box_y; + page.drawPoint(this); + x -= box_x; + y -= box_y; + + return new float[] {x + box_x + r, y + box_y + r}; + } + +} // End of Point.java diff --git a/PDFJet/src/main/java/com/pdfjet/Polynomial.java b/PDFJet/src/main/java/com/pdfjet/Polynomial.java new file mode 100644 index 0000000..488daea --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Polynomial.java @@ -0,0 +1,79 @@ +/** + * +Copyright (c) 2009 Kazuhiko Arase + +URL: http://www.d-project.com/ + +Licensed under the MIT license: + http://www.opensource.org/licenses/mit-license.php + +The word "QR Code" is registered trademark of +DENSO WAVE INCORPORATED + http://www.denso-wave.com/qrcode/faqpatent-e.html +*/ + +package com.pdfjet; + + +/** + * Polynomial + * @author Kazuhiko Arase + */ +class Polynomial { + + private final int[] num; + + + public Polynomial(int[] num) { + this(num, 0); + } + + public Polynomial(int[] num, int shift) { + int offset = 0; + + while (offset < num.length && num[offset] == 0) { + offset++; + } + + this.num = new int[num.length - offset + shift]; + System.arraycopy(num, offset, this.num, 0, num.length - offset); + } + + public int get(int index) { + return num[index]; + } + + public int getLength() { + return num.length; + } + + public Polynomial multiply(Polynomial e) { + int[] num = new int[getLength() + e.getLength() - 1]; + + for (int i = 0; i < getLength(); i++) { + for (int j = 0; j < e.getLength(); j++) { + num[i + j] ^= QRMath.gexp(QRMath.glog(get(i)) + QRMath.glog(e.get(j))); + } + } + + return new Polynomial(num); + } + + public Polynomial mod(Polynomial e) { + if (getLength() - e.getLength() < 0) { + return this; + } + + int ratio = QRMath.glog(get(0)) - QRMath.glog(e.get(0)); + int[] num = new int[getLength()]; + for (int i = 0; i < getLength(); i++) { + num[i] = get(i); + } + + for (int i = 0; i < e.getLength(); i++) { + num[i] ^= QRMath.gexp(QRMath.glog(e.get(i)) + ratio); + } + + return new Polynomial(num).mod(e); + } +} diff --git a/PDFJet/src/main/java/com/pdfjet/QRCode.java b/PDFJet/src/main/java/com/pdfjet/QRCode.java new file mode 100644 index 0000000..8f1533d --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/QRCode.java @@ -0,0 +1,409 @@ +/** + * +Copyright (c) 2009 Kazuhiko Arase + +URL: http://www.d-project.com/ + +Licensed under the MIT license: + http://www.opensource.org/licenses/mit-license.php + +The word "QR Code" is registered trademark of +DENSO WAVE INCORPORATED + http://www.denso-wave.com/qrcode/faqpatent-e.html +*/ + +package com.pdfjet; + +import java.io.UnsupportedEncodingException; + + +/** + * Used to create 2D QR Code barcodes. Please see Example_20. + * + * @author Kazuhiko Arase + */ +public class QRCode implements Drawable { + + private static final int PAD0 = 0xEC; + private static final int PAD1 = 0x11; + private Boolean[][] modules; + private int moduleCount = 33; // Magic Number + private int errorCorrectLevel = ErrorCorrectLevel.M; + + private float x; + private float y; + + private byte[] qrData; + private float m1 = 2.0f; // Module length + + + /** + * Used to create 2D QR Code barcodes. + * + * @param str the string to encode. + * @param errorCorrectLevel the desired error correction level. + * @throws UnsupportedEncodingException + */ + public QRCode(String str, int errorCorrectLevel) throws UnsupportedEncodingException { + this.qrData = str.getBytes("UTF-8"); + this.errorCorrectLevel = errorCorrectLevel; + this.make(false, getBestMaskPattern()); + } + + /** + * Sets the position where this barcode will be drawn on the page. + * + * @param x the x coordinate of the top left corner of the barcode. + * @param y the y coordinate of the top left corner of the barcode. + */ + public void setPosition(double x, double y) { + setPosition((float) x, (float) y); + } + + /** + * Sets the position where this barcode will be drawn on the page. + * + * @param x the x coordinate of the top left corner of the barcode. + * @param y the y coordinate of the top left corner of the barcode. + */ + public void setPosition(float x, float y) { + setLocation(x, y); + } + + /** + * Sets the location where this barcode will be drawn on the page. + * + * @param x the x coordinate of the top left corner of the barcode. + * @param y the y coordinate of the top left corner of the barcode. + */ + public void setLocation(float x, float y) { + this.x = x; + this.y = y; + } + + /** + * Sets the module length of this barcode. + * The default value is 2.0f + * + * @param moduleLength the specified module length. + */ + public void setModuleLength(double moduleLength) { + this.m1 = (float) moduleLength; + } + + + /** + * Sets the module length of this barcode. + * The default value is 2.0f + * + * @param moduleLength the specified module length. + */ + public void setModuleLength(float moduleLength) { + this.m1 = moduleLength; + } + + /** + * Draws this barcode on the specified page. + * + * @param page the specified page. + * @return x and y coordinates of the bottom right corner of this component. + * @throws Exception + */ + public float[] drawOn(Page page) throws Exception { + for (int row = 0; row < modules.length; row++) { + for (int col = 0; col < modules.length; col++) { + if (isDark(row, col)) { + page.fillRect(x + col*m1, y + row*m1, m1, m1); + } + } + } + + float w = m1*modules.length; + float h = m1*modules.length; + return new float[] {x + w, y + h}; + } + + public Boolean[][] getData() { + return modules; + } + + /** + * @param row the row. + * @param col the column. + */ + protected boolean isDark(int row, int col) { + if (modules[row][col] != null) { + return modules[row][col]; + } + else { + return false; + } + } + + protected int getModuleCount() { + return moduleCount; + } + + protected int getBestMaskPattern() { + int minLostPoint = 0; + int pattern = 0; + + for (int i = 0; i < 8; i++) { + make(true, i); + int lostPoint = QRUtil.getLostPoint(this); + if (i == 0 || minLostPoint > lostPoint) { + minLostPoint = lostPoint; + pattern = i; + } + } + + return pattern; + } + + protected void make(boolean test, int maskPattern) { + modules = new Boolean[moduleCount][moduleCount]; + + setupPositionProbePattern(0, 0); + setupPositionProbePattern(moduleCount - 7, 0); + setupPositionProbePattern(0, moduleCount - 7); + + setupPositionAdjustPattern(); + setupTimingPattern(); + setupTypeInfo(test, maskPattern); + + mapData(createData(errorCorrectLevel), maskPattern); + } + + private void mapData(byte[] data, int maskPattern) { + int inc = -1; + int row = moduleCount - 1; + int bitIndex = 7; + int byteIndex = 0; + + for (int col = moduleCount - 1; col > 0; col -= 2) { + if (col == 6) col--; + while (true) { + for (int c = 0; c < 2; c++) { + if (modules[row][col - c] == null) { + boolean dark = false; + + if (byteIndex < data.length) { + dark = (((data[byteIndex] >>> bitIndex) & 1) == 1); + } + + boolean mask = QRUtil.getMask(maskPattern, row, col - c); + if (mask) { + dark = !dark; + } + + modules[row][col - c] = dark; + bitIndex--; + if (bitIndex == -1) { + byteIndex++; + bitIndex = 7; + } + } + } + + row += inc; + if (row < 0 || moduleCount <= row) { + row -= inc; + inc = -inc; + break; + } + } + } + } + + private void setupPositionAdjustPattern() { + int[] pos = {6, 26}; // Magic Numbers + for (int i = 0; i < pos.length; i++) { + for (int j = 0; j < pos.length; j++) { + int row = pos[i]; + int col = pos[j]; + + if (modules[row][col] != null) { + continue; + } + + for (int r = -2; r <= 2; r++) { + for (int c = -2; c <= 2; c++) { + modules[row + r][col + c] = + r == -2 || r == 2 || c == -2 || c == 2 || (r == 0 && c == 0); + } + } + } + } + } + + private void setupPositionProbePattern(int row, int col) { + for (int r = -1; r <= 7; r++) { + for (int c = -1; c <= 7; c++) { + if (row + r <= -1 || moduleCount <= row + r + || col + c <= -1 || moduleCount <= col + c) { + continue; + } + + modules[row + r][col + c] = + (0 <= r && r <= 6 && (c == 0 || c == 6)) || + (0 <= c && c <= 6 && (r == 0 || r == 6)) || + (2 <= r && r <= 4 && 2 <= c && c <= 4); + } + } + } + + private void setupTimingPattern() { + for (int r = 8; r < moduleCount - 8; r++) { + if (modules[r][6] != null) { + continue; + } + modules[r][6] = (r % 2 == 0); + } + for (int c = 8; c < moduleCount - 8; c++) { + if (modules[6][c] != null) { + continue; + } + modules[6][c] = (c % 2 == 0); + } + } + + private void setupTypeInfo(boolean test, int maskPattern) { + int data = (errorCorrectLevel << 3) | maskPattern; + int bits = QRUtil.getBCHTypeInfo(data); + + for (int i = 0; i < 15; i++) { + Boolean mod = (!test && ((bits >> i) & 1) == 1); + if (i < 6) { + modules[i][8] = mod; + } + else if (i < 8) { + modules[i + 1][8] = mod; + } + else { + modules[moduleCount - 15 + i][8] = mod; + } + } + + for (int i = 0; i < 15; i++) { + Boolean mod = (!test && ((bits >> i) & 1) == 1); + if (i < 8) { + modules[8][moduleCount - i - 1] = mod; + } + else if (i < 9) { + modules[8][15 - i - 1 + 1] = mod; + } + else { + modules[8][15 - i - 1] = mod; + } + } + + modules[moduleCount - 8][8] = !test; + } + + private byte[] createData(int errorCorrectLevel) { + RSBlock[] rsBlocks = RSBlock.getRSBlocks(errorCorrectLevel); + + BitBuffer buffer = new BitBuffer(); + buffer.put(4, 4); + buffer.put(qrData.length, 8); + for (int i = 0; i < qrData.length; i++) { + buffer.put(qrData[i], 8); + } + + int totalDataCount = 0; + for (int i = 0; i < rsBlocks.length; i++) { + totalDataCount += rsBlocks[i].getDataCount(); + } + + if (buffer.getLengthInBits() > totalDataCount * 8) { + throw new IllegalArgumentException("String length overflow. (" + + buffer.getLengthInBits() + + ">" + + totalDataCount * 8 + + ")"); + } + + if (buffer.getLengthInBits() + 4 <= totalDataCount * 8) { + buffer.put(0, 4); + } + + // padding + while (buffer.getLengthInBits() % 8 != 0) { + buffer.put(false); + } + + // padding + while (true) { + if (buffer.getLengthInBits() >= totalDataCount * 8) { + break; + } + buffer.put(PAD0, 8); + + if (buffer.getLengthInBits() >= totalDataCount * 8) { + break; + } + buffer.put(PAD1, 8); + } + + return createBytes(buffer, rsBlocks); + } + + private byte[] createBytes(BitBuffer buffer, RSBlock[] rsBlocks) { + int offset = 0; + int maxDcCount = 0; + int maxEcCount = 0; + + int[][] dcdata = new int[rsBlocks.length][]; + int[][] ecdata = new int[rsBlocks.length][]; + + for (int r = 0; r < rsBlocks.length; r++) { + int dcCount = rsBlocks[r].getDataCount(); + int ecCount = rsBlocks[r].getTotalCount() - dcCount; + + maxDcCount = Math.max(maxDcCount, dcCount); + maxEcCount = Math.max(maxEcCount, ecCount); + + dcdata[r] = new int[dcCount]; + for (int i = 0; i < dcdata[r].length; i++) { + dcdata[r][i] = 0xff & buffer.getBuffer()[i + offset]; + } + offset += dcCount; + + Polynomial rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount); + Polynomial rawPoly = new Polynomial(dcdata[r], rsPoly.getLength() - 1); + + Polynomial modPoly = rawPoly.mod(rsPoly); + ecdata[r] = new int[rsPoly.getLength() - 1]; + for (int i = 0; i < ecdata[r].length; i++) { + int modIndex = i + modPoly.getLength() - ecdata[r].length; + ecdata[r][i] = (modIndex >= 0) ? modPoly.get(modIndex) : 0; + } + } + + int totalCodeCount = 0; + for (int i = 0; i < rsBlocks.length; i++) { + totalCodeCount += rsBlocks[i].getTotalCount(); + } + + byte[] data = new byte[totalCodeCount]; + int index = 0; + for (int i = 0; i < maxDcCount; i++) { + for (int r = 0; r < rsBlocks.length; r++) { + if (i < dcdata[r].length) { + data[index++] = (byte) dcdata[r][i]; + } + } + } + + for (int i = 0; i < maxEcCount; i++) { + for (int r = 0; r < rsBlocks.length; r++) { + if (i < ecdata[r].length) { + data[index++] = (byte) ecdata[r][i]; + } + } + } + + return data; + } + +} diff --git a/PDFJet/src/main/java/com/pdfjet/QRMath.java b/PDFJet/src/main/java/com/pdfjet/QRMath.java new file mode 100644 index 0000000..4a88150 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/QRMath.java @@ -0,0 +1,64 @@ +/** + * +Copyright (c) 2009 Kazuhiko Arase + +URL: http://www.d-project.com/ + +Licensed under the MIT license: + http://www.opensource.org/licenses/mit-license.php + +The word "QR Code" is registered trademark of +DENSO WAVE INCORPORATED + http://www.denso-wave.com/qrcode/faqpatent-e.html +*/ + +package com.pdfjet; + + +/** + * QRMath + * @author Kazuhiko Arase + */ +class QRMath { + + private static final int[] EXP_TABLE = new int[256]; + private static final int[] LOG_TABLE = new int[256]; + + static { + for (int i = 0; i < 8; i++) { + EXP_TABLE[i] = 1 << i; + } + + for (int i = 8; i < 256; i++) { + EXP_TABLE[i] = EXP_TABLE[i - 4] + ^ EXP_TABLE[i - 5] + ^ EXP_TABLE[i - 6] + ^ EXP_TABLE[i - 8]; + } + + for (int i = 0; i < 255; i++) { + LOG_TABLE[EXP_TABLE[i]] = i; + } + } + + public static int glog(int n) { + if (n < 1) { + throw new ArithmeticException("log(" + n + ")"); + } + + return LOG_TABLE[n]; + } + + public static int gexp(int n) { + while (n < 0) { + n += 255; + } + + while (n >= 256) { + n -= 255; + } + + return EXP_TABLE[n]; + } + +} diff --git a/PDFJet/src/main/java/com/pdfjet/QRUtil.java b/PDFJet/src/main/java/com/pdfjet/QRUtil.java new file mode 100644 index 0000000..0db2074 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/QRUtil.java @@ -0,0 +1,165 @@ +/** + * +Copyright (c) 2009 Kazuhiko Arase + +URL: http://www.d-project.com/ + +Licensed under the MIT license: + http://www.opensource.org/licenses/mit-license.php + +The word "QR Code" is registered trademark of +DENSO WAVE INCORPORATED + http://www.denso-wave.com/qrcode/faqpatent-e.html +*/ + +package com.pdfjet; + + +/** + * QRUtil + * @author Kazuhiko Arase + */ +class QRUtil { + + protected static Polynomial getErrorCorrectPolynomial(int errorCorrectLength) { + Polynomial a = new Polynomial(new int[] {1}); + for (int i = 0; i < errorCorrectLength; i++) { + a = a.multiply(new Polynomial(new int[] { 1, QRMath.gexp(i) })); + } + return a; + } + + protected static boolean getMask(int maskPattern, int i, int j) { + switch (maskPattern) { + + case MaskPattern.PATTERN000 : return (i + j) % 2 == 0; + case MaskPattern.PATTERN001 : return (i % 2) == 0; + case MaskPattern.PATTERN010 : return (j % 3) == 0; + case MaskPattern.PATTERN011 : return (i + j) % 3 == 0; + case MaskPattern.PATTERN100 : return (i / 2 + j / 3) % 2 == 0; + case MaskPattern.PATTERN101 : return (i * j) % 2 + (i * j) % 3 == 0; + case MaskPattern.PATTERN110 : return ((i * j) % 2 + (i * j) % 3) % 2 == 0; + case MaskPattern.PATTERN111 : return ((i * j) % 3 + (i + j) % 2) % 2 == 0; + + default : + throw new IllegalArgumentException("mask: " + maskPattern); + } + } + + protected static int getLostPoint(QRCode qrCode) { + int moduleCount = qrCode.getModuleCount(); + int lostPoint = 0; + + // LEVEL1 + for (int row = 0; row < moduleCount; row++) { + for (int col = 0; col < moduleCount; col++) { + int sameCount = 0; + boolean dark = qrCode.isDark(row, col); + + for (int r = -1; r <= 1; r++) { + if (row + r < 0 || moduleCount <= row + r) { + continue; + } + + for (int c = -1; c <= 1; c++) { + if (col + c < 0 || moduleCount <= col + c) { + continue; + } + + if (r == 0 && c == 0) { + continue; + } + + if (dark == qrCode.isDark(row + r, col + c)) { + sameCount++; + } + } + } + + if (sameCount > 5) { + lostPoint += (3 + sameCount - 5); + } + } + } + + // LEVEL2 + for (int row = 0; row < moduleCount - 1; row++) { + for (int col = 0; col < moduleCount - 1; col++) { + int count = 0; + if (qrCode.isDark(row, col )) count++; + if (qrCode.isDark(row + 1, col )) count++; + if (qrCode.isDark(row, col + 1)) count++; + if (qrCode.isDark(row + 1, col + 1)) count++; + if (count == 0 || count == 4) { + lostPoint += 3; + } + } + } + + // LEVEL3 + for (int row = 0; row < moduleCount; row++) { + for (int col = 0; col < moduleCount - 6; col++) { + if (qrCode.isDark(row, col) + && !qrCode.isDark(row, col + 1) + && qrCode.isDark(row, col + 2) + && qrCode.isDark(row, col + 3) + && qrCode.isDark(row, col + 4) + && !qrCode.isDark(row, col + 5) + && qrCode.isDark(row, col + 6)) { + lostPoint += 40; + } + } + } + + for (int col = 0; col < moduleCount; col++) { + for (int row = 0; row < moduleCount - 6; row++) { + if (qrCode.isDark(row, col) + && !qrCode.isDark(row + 1, col) + && qrCode.isDark(row + 2, col) + && qrCode.isDark(row + 3, col) + && qrCode.isDark(row + 4, col) + && !qrCode.isDark(row + 5, col) + && qrCode.isDark(row + 6, col)) { + lostPoint += 40; + } + } + } + + // LEVEL4 + int darkCount = 0; + for (int col = 0; col < moduleCount; col++) { + for (int row = 0; row < moduleCount; row++) { + if (qrCode.isDark(row, col)) { + darkCount++; + } + } + } + + int ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5; + lostPoint += ratio * 10; + + return lostPoint; + } + + private static final int G15 = (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0); + + private static final int G15_MASK = (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1); + + public static int getBCHTypeInfo(int data) { + int d = data << 10; + while (getBCHDigit(d) - getBCHDigit(G15) >= 0) { + d ^= (G15 << (getBCHDigit(d) - getBCHDigit(G15))); + } + return ((data << 10) | d) ^ G15_MASK; + } + + private static int getBCHDigit(int data) { + int digit = 0; + while (data != 0) { + digit++; + data >>>= 1; + } + return digit; + } + +} diff --git a/PDFJet/src/main/java/com/pdfjet/RSBlock.java b/PDFJet/src/main/java/com/pdfjet/RSBlock.java new file mode 100644 index 0000000..b17cd2f --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/RSBlock.java @@ -0,0 +1,76 @@ +/** + * +Copyright (c) 2009 Kazuhiko Arase + +URL: http://www.d-project.com/ + +Licensed under the MIT license: + http://www.opensource.org/licenses/mit-license.php + +The word "QR Code" is registered trademark of +DENSO WAVE INCORPORATED + http://www.denso-wave.com/qrcode/faqpatent-e.html +*/ + +package com.pdfjet; + +import java.util.ArrayList; +import java.util.List; + + +/** + * RSBlock + * @author Kazuhiko Arase + */ +class RSBlock { + + private int totalCount; + private int dataCount; + + + private RSBlock(int totalCount, int dataCount) { + this.totalCount = totalCount; + this.dataCount = dataCount; + } + + public int getDataCount() { + return dataCount; + } + + public int getTotalCount() { + return totalCount; + } + + public static RSBlock[] getRSBlocks(int errorCorrectLevel) { + int[] rsBlock = getRsBlockTable(errorCorrectLevel); + int length = rsBlock.length / 3; + + List list = new ArrayList(); + for (int i = 0; i < length; i++) { + int count = rsBlock[3*i]; + int totalCount = rsBlock[3*i + 1]; + int dataCount = rsBlock[3*i + 2]; + + for (int j = 0; j < count; j++) { + list.add(new RSBlock(totalCount, dataCount)); + } + } + + return list.toArray(new RSBlock[list.size()]); + } + + private static int[] getRsBlockTable(int errorCorrectLevel) { + switch(errorCorrectLevel) { + case ErrorCorrectLevel.L : + return new int[] {1, 100, 80}; + case ErrorCorrectLevel.M : + return new int[] {2, 50, 32}; + case ErrorCorrectLevel.Q : + return new int[] {2, 50, 24}; + case ErrorCorrectLevel.H : + return new int[] {4, 25, 9}; + } + return null; + } + +} diff --git a/PDFJet/src/main/java/com/pdfjet/RadioButton.java b/PDFJet/src/main/java/com/pdfjet/RadioButton.java new file mode 100644 index 0000000..c30c2fe --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/RadioButton.java @@ -0,0 +1,201 @@ +/** + * RadioButton.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + + +/** + * Creates a RadioButton, which can be set selected or unselected. + * + */ +public class RadioButton implements Drawable { + + private boolean selected = false; + private float x; + private float y; + private float r1; + private float r2; + private float penWidth; + private Font font = null; + private String label = ""; + private String uri = null; + + private String language = null; + private String altDescription = Single.space; + private String actualText = Single.space; + + + /** + * Creates a RadioButton that is not selected. + * + */ + public RadioButton(Font font, String label) { + this.font = font; + this.label = label; + } + + + /** + * Sets the font size to use for this text line. + * + * @param fontSize the fontSize to use. + * @return this RadioButton. + */ + public RadioButton setFontSize(float fontSize) { + this.font.setSize(fontSize); + return this; + } + + + /** + * Set the x,y position on the Page. + * + * @param x the x coordinate on the Page. + * @param y the y coordinate on the Page. + * @return this RadioButton. + */ + public RadioButton setPosition(float x, float y) { + return setLocation(x, y); + } + + + /** + * Set the x,y location on the Page. + * + * @param x the x coordinate on the Page. + * @param y the y coordinate on the Page. + * @return this RadioButton. + */ + public RadioButton setLocation(float x, float y) { + this.x = x; + this.y = y; + return this; + } + + + /** + * Sets the URI for the "click text line" action. + * + * @param uri the URI. + * @return this RadioButton. + */ + public RadioButton setURIAction(String uri) { + this.uri = uri; + return this; + } + + + /** + * Selects or deselects this radio button. + * + * @param selected the selection flag. + * @return this RadioButton. + */ + public RadioButton select(boolean selected) { + this.selected = selected; + return this; + } + + + /** + * Sets the alternate description of this radio button. + * + * @param altDescription the alternate description of the radio button. + * @return this RadioButton. + */ + public RadioButton setAltDescription(String altDescription) { + this.altDescription = altDescription; + return this; + } + + + /** + * Sets the actual text for this radio button. + * + * @param actualText the actual text for the radio button. + * @return this RadioButton. + */ + public RadioButton setActualText(String actualText) { + this.actualText = actualText; + return this; + } + + + /** + * Draws this RadioButton on the specified Page. + * + * @param page the Page where the RadioButton is to be drawn. + * @return x and y coordinates of the bottom right corner of this component. + * @throws Exception + */ + public float[] drawOn(Page page) throws Exception { + page.addBMC(StructElem.SPAN, language, altDescription, actualText); + + this.r1 = font.getAscent()/2; + this.r2 = r1/2; + this.penWidth = r1/10; + + float y_box = y - font.getAscent(); + page.setPenWidth(1f); + page.setPenColor(Color.black); + page.setLinePattern("[] 0"); + page.setBrushColor(Color.black); + page.drawCircle(x + r1, y_box + r1, r1); + + if (this.selected) { + page.drawCircle(x + r1, y_box + r1, r2, Operation.FILL); + } + + if (uri != null) { + page.setBrushColor(Color.blue); + } + page.drawString(font, label, x + 3*r1, y); + page.setPenWidth(0f); + page.setBrushColor(Color.black); + + page.addEMC(); + + if (uri != null) { + // Please note: The font descent is a negative number. + page.addAnnotation(new Annotation( + uri, + null, + x + 3*r1, + page.height - y, + x + 3*r1 + font.stringWidth(label), + page.height - (y - font.getAscent()), + language, + altDescription, + actualText)); + } + + return new float[] { x + 6*r1 + font.stringWidth(label), y + font.getDescent() }; + } + +} // End of RadioButton.java diff --git a/PDFJet/src/main/java/com/pdfjet/Round.java b/PDFJet/src/main/java/com/pdfjet/Round.java new file mode 100644 index 0000000..d3f1a95 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Round.java @@ -0,0 +1,37 @@ +/** + * Round.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + + +class Round { + protected float min_value = 0f; + protected float max_value = 0f; + protected int num_of_grid_lines = 0; +} diff --git a/PDFJet/src/main/java/com/pdfjet/Salsa20.java b/PDFJet/src/main/java/com/pdfjet/Salsa20.java new file mode 100644 index 0000000..fb2af6d --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Salsa20.java @@ -0,0 +1,169 @@ +/** + * + * The Salsa20 encryption function was designed and originally implemented + * by Daniel J. Bernstein: + * + * http://cr.yp.to/salsa20.html + * http://cr.yp.to/snuffle/ip.pdf + * + * The following Java implementation encrypts the system time and returns + * the first 32 characters of the hash. + * + */ + +package com.pdfjet; + + +class Salsa20 { + + private String id = null; + + + public Salsa20() { + +/* +The Original Specification: + + #define R(a,b) (((a) << (b)) | ((a) >> (32 - (b)))) + void salsa20_word_specification(uint32 out[16],uint32 in[16]) { + int i; + uint32 x[16]; + for (i = 0;i < 16;++i) x[i] = in[i]; + for (i = 20;i > 0;i -= 2) { + x[ 4] ^= R(x[ 0]+x[12], 7); x[ 8] ^= R(x[ 4]+x[ 0], 9); + x[12] ^= R(x[ 8]+x[ 4],13); x[ 0] ^= R(x[12]+x[ 8],18); + x[ 9] ^= R(x[ 5]+x[ 1], 7); x[13] ^= R(x[ 9]+x[ 5], 9); + x[ 1] ^= R(x[13]+x[ 9],13); x[ 5] ^= R(x[ 1]+x[13],18); + x[14] ^= R(x[10]+x[ 6], 7); x[ 2] ^= R(x[14]+x[10], 9); + x[ 6] ^= R(x[ 2]+x[14],13); x[10] ^= R(x[ 6]+x[ 2],18); + x[ 3] ^= R(x[15]+x[11], 7); x[ 7] ^= R(x[ 3]+x[15], 9); + x[11] ^= R(x[ 7]+x[ 3],13); x[15] ^= R(x[11]+x[ 7],18); + x[ 1] ^= R(x[ 0]+x[ 3], 7); x[ 2] ^= R(x[ 1]+x[ 0], 9); + x[ 3] ^= R(x[ 2]+x[ 1],13); x[ 0] ^= R(x[ 3]+x[ 2],18); + x[ 6] ^= R(x[ 5]+x[ 4], 7); x[ 7] ^= R(x[ 6]+x[ 5], 9); + x[ 4] ^= R(x[ 7]+x[ 6],13); x[ 5] ^= R(x[ 4]+x[ 7],18); + x[11] ^= R(x[10]+x[ 9], 7); x[ 8] ^= R(x[11]+x[10], 9); + x[ 9] ^= R(x[ 8]+x[11],13); x[10] ^= R(x[ 9]+x[ 8],18); + x[12] ^= R(x[15]+x[14], 7); x[13] ^= R(x[12]+x[15], 9); + x[14] ^= R(x[13]+x[12],13); x[15] ^= R(x[14]+x[13],18); + } + for (i = 0;i < 16;++i) out[i] = x[i] + in[i]; + } + +Test input: + int[] a_in = new int[] { + 0x61707865, 0x04030201, 0x08070605, 0x0c0b0a09, + 0x100f0e0d, 0x3320646e, 0x01040103, 0x06020905, + 0x00000007, 0x00000000, 0x79622d32, 0x14131211, + 0x18171615, 0x1c1b1a19, 0x201f1e1d, 0x6b206574}; + +The expected output: +0xb9a205a3 +0x0695e150 +0xaa94881a +0xadb7b12c +0x798942d4 +0x26107016 +0x64edb1a4 +0x2d27173f +0xb1c7f1fa +0x62066edc +0xe035fa23 +0xc4496f04 +0x2131e6b3 +0x810bde28 +0xf62cb407 +0x6bdede3d +*/ + + int[] a_in = new int[16]; + + StringBuilder buf = new StringBuilder( + Long.toHexString(System.currentTimeMillis())); + int len = 128 - buf.length(); + for (int i = 0; i < len; i++) { + buf.append('0'); + } + + for (int i = 0; i < 128; i += 8) { + a_in[i/8] = (int) Long.parseLong(buf.substring(i, i + 8), 16); + } + + id = bin2hex(salsa20_word_specification(a_in)); + // System.out.println(id); + } + + + // Use unsigned right shift >>> ! + private int R(int a, int b) { + return (a << b) | (a >>> (32 - b)); + } + + + private int[] salsa20_word_specification(int[] a_in) { + + int[] a_out = new int[16]; + int[] x = new int[16]; + + for (int i = 0; i < 16; ++i) { + x[i] = a_in[i]; + } + + for (int i = 20; i > 0; i -= 2) { + x[ 4] ^= R(x[ 0]+x[12], 7); x[ 8] ^= R(x[ 4]+x[ 0], 9); + x[12] ^= R(x[ 8]+x[ 4],13); x[ 0] ^= R(x[12]+x[ 8],18); + x[ 9] ^= R(x[ 5]+x[ 1], 7); x[13] ^= R(x[ 9]+x[ 5], 9); + x[ 1] ^= R(x[13]+x[ 9],13); x[ 5] ^= R(x[ 1]+x[13],18); + x[14] ^= R(x[10]+x[ 6], 7); x[ 2] ^= R(x[14]+x[10], 9); + x[ 6] ^= R(x[ 2]+x[14],13); x[10] ^= R(x[ 6]+x[ 2],18); + x[ 3] ^= R(x[15]+x[11], 7); x[ 7] ^= R(x[ 3]+x[15], 9); + x[11] ^= R(x[ 7]+x[ 3],13); x[15] ^= R(x[11]+x[ 7],18); + x[ 1] ^= R(x[ 0]+x[ 3], 7); x[ 2] ^= R(x[ 1]+x[ 0], 9); + x[ 3] ^= R(x[ 2]+x[ 1],13); x[ 0] ^= R(x[ 3]+x[ 2],18); + x[ 6] ^= R(x[ 5]+x[ 4], 7); x[ 7] ^= R(x[ 6]+x[ 5], 9); + x[ 4] ^= R(x[ 7]+x[ 6],13); x[ 5] ^= R(x[ 4]+x[ 7],18); + x[11] ^= R(x[10]+x[ 9], 7); x[ 8] ^= R(x[11]+x[10], 9); + x[ 9] ^= R(x[ 8]+x[11],13); x[10] ^= R(x[ 9]+x[ 8],18); + x[12] ^= R(x[15]+x[14], 7); x[13] ^= R(x[12]+x[15], 9); + x[14] ^= R(x[13]+x[12],13); x[15] ^= R(x[14]+x[13],18); + } + + for (int i = 0; i < 16; ++i) { + a_out[i] = x[i] + a_in[i]; + } + + return a_out; + } + + + private String bin2hex(int[] binarray) { + + String table = "0123456789abcdef"; + StringBuilder buf = new StringBuilder(); + + for (int i = 0; i < binarray.length; i++) { + int a = binarray[i]; + buf.append(table.charAt(a>>28 & 0x0000000f)); + buf.append(table.charAt(a>>24 & 0x0000000f)); + buf.append(table.charAt(a>>20 & 0x0000000f)); + buf.append(table.charAt(a>>16 & 0x0000000f)); + buf.append(table.charAt(a>>12 & 0x0000000f)); + buf.append(table.charAt(a>> 8 & 0x0000000f)); + buf.append(table.charAt(a>> 4 & 0x0000000f)); + buf.append(table.charAt(a & 0x0000000f)); + } + + return buf.substring(0, 32); + } + + + public String getID() { + return id; + } + + + public static void main(String[] args) { + new Salsa20(); + } + +} diff --git a/PDFJet/src/main/java/com/pdfjet/Segment.java b/PDFJet/src/main/java/com/pdfjet/Segment.java new file mode 100644 index 0000000..819efb7 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Segment.java @@ -0,0 +1,42 @@ +/** + * Segment.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + + +/** + * Used to specify the segment of Ellipse or Circle to draw. + * See Example_18 + */ +public class Segment { + public static final int CLOCKWISE_00_03 = 0; + public static final int CLOCKWISE_03_06 = 1; + public static final int CLOCKWISE_06_09 = 2; + public static final int CLOCKWISE_09_12 = 3; +} diff --git a/PDFJet/src/main/java/com/pdfjet/Single.java b/PDFJet/src/main/java/com/pdfjet/Single.java new file mode 100644 index 0000000..3f0f1a9 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Single.java @@ -0,0 +1,38 @@ +/** + * Single.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + + +/** + * Please see Example_45 + */ +public class Single { + public static final String space = " "; +} diff --git a/PDFJet/src/main/java/com/pdfjet/Standard.java b/PDFJet/src/main/java/com/pdfjet/Standard.java new file mode 100644 index 0000000..2aae701 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Standard.java @@ -0,0 +1,427 @@ +/** + * Standard.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + + +class Standard { + public static String[] strings = { +".notdef", +"space", +"exclam", +"quotedbl", +"numbersign", +"dollar", +"percent", +"ampersand", +"quoteright", +"parenleft", +"parenright", +"asterisk", +"plus", +"comma", +"hyphen", +"period", +"slash", +"zero", +"one", +"two", +"three", +"four", +"five", +"six", +"seven", +"eight", +"nine", +"colon", +"semicolon", +"less", +"equal", +"greater", +"question", +"at", +"A", +"B", +"C", +"D", +"E", +"F", +"G", +"H", +"I", +"J", +"K", +"L", +"M", +"N", +"O", +"P", +"Q", +"R", +"S", +"T", +"U", +"V", +"W", +"X", +"Y", +"Z", +"bracketleft", +"backslash", +"bracketright", +"asciicircum", +"underscore", +"quoteleft", +"a", +"b", +"c", +"d", +"e", +"f", +"g", +"h", +"i", +"j", +"k", +"l", +"m", +"n", +"o", +"p", +"q", +"r", +"s", +"t", +"u", +"v", +"w", +"x", +"y", +"z", +"braceleft", +"bar", +"braceright", +"asciitilde", +"exclamdown", +"cent", +"sterling", +"fraction", +"yen", +"florin", +"section", +"currency", +"quotesingle", +"quotedblleft", +"guillemotleft", +"guilsinglleft", +"guilsinglright", +"fi", +"fl", +"endash", +"dagger", +"daggerdbl", +"periodcentered", +"paragraph", +"bullet", +"quotesinglbase", +"quotedblbase", +"quotedblright", +"guillemotright", +"ellipsis", +"perthousand", +"questiondown", +"grave", +"acute", +"circumflex", +"tilde", +"macron", +"breve", +"dotaccent", +"dieresis", +"ring", +"cedilla", +"hungarumlaut", +"ogonek", +"caron", +"emdash", +"AE", +"ordfeminine", +"Lslash", +"Oslash", +"OE", +"ordmasculine", +"ae", +"dotlessi", +"lslash", +"oslash", +"oe", +"germandbls", +"onesuperior", +"logicalnot", +"mu", +"trademark", +"Eth", +"onehalf", +"plusminus", +"Thorn", +"onequarter", +"divide", +"brokenbar", +"degree", +"thorn", +"threequarters", +"twosuperior", +"registered", +"minus", +"eth", +"multiply", +"threesuperior", +"copyright", +"Aacute", +"Acircumflex", +"Adieresis", +"Agrave", +"Aring", +"Atilde", +"Ccedilla", +"Eacute", +"Ecircumflex", +"Edieresis", +"Egrave", +"Iacute", +"Icircumflex", +"Idieresis", +"Igrave", +"Ntilde", +"Oacute", +"Ocircumflex", +"Odieresis", +"Ograve", +"Otilde", +"Scaron", +"Uacute", +"Ucircumflex", +"Udieresis", +"Ugrave", +"Yacute", +"Ydieresis", +"Zcaron", +"aacute", +"acircumflex", +"adieresis", +"agrave", +"aring", +"atilde", +"ccedilla", +"eacute", +"ecircumflex", +"edieresis", +"egrave", +"iacute", +"icircumflex", +"idieresis", +"igrave", +"ntilde", +"oacute", +"ocircumflex", +"odieresis", +"ograve", +"otilde", +"scaron", +"uacute", +"ucircumflex", +"udieresis", +"ugrave", +"yacute", +"ydieresis", +"zcaron", +"exclamsmall", +"Hungarumlautsmall", +"dollaroldstyle", +"dollarsuperior", +"ampersandsmall", +"Acutesmall", +"parenleftsuperior", +"parenrightsuperior", +"twodotenleader", +"onedotenleader", +"zerooldstyle", +"oneoldstyle", +"twooldstyle", +"threeoldstyle", +"fouroldstyle", +"fiveoldstyle", +"sixoldstyle", +"sevenoldstyle", +"eightoldstyle", +"nineoldstyle", +"commasuperior", +"threequartersemdash", +"periodsuperior", +"questionsmall", +"asuperior", +"bsuperior", +"centsuperior", +"dsuperior", +"esuperior", +"isuperior", +"lsuperior", +"msuperior", +"nsuperior", +"osuperior", +"rsuperior", +"ssuperior", +"tsuperior", +"ff", +"ffi", +"ffl", +"parenleftinferior", +"parenrightinferior", +"Circumflexsmall", +"hyphensuperior", +"Gravesmall", +"Asmall", +"Bsmall", +"Csmall", +"Dsmall", +"Esmall", +"Fsmall", +"Gsmall", +"Hsmall", +"Ismall", +"Jsmall", +"Ksmall", +"Lsmall", +"Msmall", +"Nsmall", +"Osmall", +"Psmall", +"Qsmall", +"Rsmall", +"Ssmall", +"Tsmall", +"Usmall", +"Vsmall", +"Wsmall", +"Xsmall", +"Ysmall", +"Zsmall", +"colonmonetary", +"onefitted", +"rupiah", +"Tildesmall", +"exclamdownsmall", +"centoldstyle", +"Lslashsmall", +"Scaronsmall", +"Zcaronsmall", +"Dieresissmall", +"Brevesmall", +"Caronsmall", +"Dotaccentsmall", +"Macronsmall", +"figuredash", +"hypheninferior", +"Ogoneksmall", +"Ringsmall", +"Cedillasmall", +"questiondownsmall", +"oneeighth", +"threeeighths", +"fiveeighths", +"seveneighths", +"onethird", +"twothirds", +"zerosuperior", +"foursuperior", +"fivesuperior", +"sixsuperior", +"sevensuperior", +"eightsuperior", +"ninesuperior", +"zeroinferior", +"oneinferior", +"twoinferior", +"threeinferior", +"fourinferior", +"fiveinferior", +"sixinferior", +"seveninferior", +"eightinferior", +"nineinferior", +"centinferior", +"dollarinferior", +"periodinferior", +"commainferior", +"Agravesmall", +"Aacutesmall", +"Acircumflexsmall", +"Atildesmall", +"Adieresissmall", +"Aringsmall", +"AEsmall", +"Ccedillasmall", +"Egravesmall", +"Eacutesmall", +"Ecircumflexsmall", +"Edieresissmall", +"Igravesmall", +"Iacutesmall", +"Icircumflexsmall", +"Idieresissmall", +"Ethsmall", +"Ntildesmall", +"Ogravesmall", +"Oacutesmall", +"Ocircumflexsmall", +"Otildesmall", +"Odieresissmall", +"OEsmall", +"Oslashsmall", +"Ugravesmall", +"Uacutesmall", +"Ucircumflexsmall", +"Udieresissmall", +"Yacutesmall", +"Thornsmall", +"Ydieresissmall", +"001.000", +"001.001", +"001.002", +"001.003", +"Black", +"Bold", +"Book", +"Light", +"Medium", +"Regular", +"Roman", +"Semibold", + }; +} diff --git a/PDFJet/src/main/java/com/pdfjet/StandardFont.java b/PDFJet/src/main/java/com/pdfjet/StandardFont.java new file mode 100644 index 0000000..936da45 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/StandardFont.java @@ -0,0 +1,176 @@ +package com.pdfjet; + + +class StandardFont { + + protected String name; + protected int bBoxLLx; + protected int bBoxLLy; + protected int bBoxURx; + protected int bBoxURy; + protected int underlinePosition; + protected int underlineThickness; + protected int[][] metrics; + + protected static StandardFont getInstance(CoreFont coreFont) { + StandardFont font = new StandardFont(); + switch (coreFont) { + case COURIER: + font.name = Courier.name; + font.bBoxLLx = Courier.bBoxLLx; + font.bBoxLLy = Courier.bBoxLLy; + font.bBoxURx = Courier.bBoxURx; + font.bBoxURy = Courier.bBoxURy; + font.underlinePosition = Courier.underlinePosition; + font.underlineThickness = Courier.underlineThickness; + font.metrics = Courier.metrics; + break; + + case COURIER_BOLD: + font.name = Courier_Bold.name; + font.bBoxLLx = Courier_Bold.bBoxLLx; + font.bBoxLLy = Courier_Bold.bBoxLLy; + font.bBoxURx = Courier_Bold.bBoxURx; + font.bBoxURy = Courier_Bold.bBoxURy; + font.underlinePosition = Courier_Bold.underlinePosition; + font.underlineThickness = Courier_Bold.underlineThickness; + font.metrics = Courier_Bold.metrics; + break; + + case COURIER_OBLIQUE: + font.name = Courier_Oblique.name; + font.bBoxLLx = Courier_Oblique.bBoxLLx; + font.bBoxLLy = Courier_Oblique.bBoxLLy; + font.bBoxURx = Courier_Oblique.bBoxURx; + font.bBoxURy = Courier_Oblique.bBoxURy; + font.underlinePosition = Courier_Oblique.underlinePosition; + font.underlineThickness = Courier_Oblique.underlineThickness; + font.metrics = Courier_Oblique.metrics; + break; + + case COURIER_BOLD_OBLIQUE: + font.name = Courier_BoldOblique.name; + font.bBoxLLx = Courier_BoldOblique.bBoxLLx; + font.bBoxLLy = Courier_BoldOblique.bBoxLLy; + font.bBoxURx = Courier_BoldOblique.bBoxURx; + font.bBoxURy = Courier_BoldOblique.bBoxURy; + font.underlinePosition = Courier_BoldOblique.underlinePosition; + font.underlineThickness = Courier_BoldOblique.underlineThickness; + font.metrics = Courier_BoldOblique.metrics; + break; + + case HELVETICA: + font.name = Helvetica.name; + font.bBoxLLx = Helvetica.bBoxLLx; + font.bBoxLLy = Helvetica.bBoxLLy; + font.bBoxURx = Helvetica.bBoxURx; + font.bBoxURy = Helvetica.bBoxURy; + font.underlinePosition = Helvetica.underlinePosition; + font.underlineThickness = Helvetica.underlineThickness; + font.metrics = Helvetica.metrics; + break; + + case HELVETICA_BOLD: + font.name = Helvetica_Bold.name; + font.bBoxLLx = Helvetica_Bold.bBoxLLx; + font.bBoxLLy = Helvetica_Bold.bBoxLLy; + font.bBoxURx = Helvetica_Bold.bBoxURx; + font.bBoxURy = Helvetica_Bold.bBoxURy; + font.underlinePosition = Helvetica_Bold.underlinePosition; + font.underlineThickness = Helvetica_Bold.underlineThickness; + font.metrics = Helvetica_Bold.metrics; + break; + + case HELVETICA_OBLIQUE: + font.name = Helvetica_Oblique.name; + font.bBoxLLx = Helvetica_Oblique.bBoxLLx; + font.bBoxLLy = Helvetica_Oblique.bBoxLLy; + font.bBoxURx = Helvetica_Oblique.bBoxURx; + font.bBoxURy = Helvetica_Oblique.bBoxURy; + font.underlinePosition = Helvetica_Oblique.underlinePosition; + font.underlineThickness = Helvetica_Oblique.underlineThickness; + font.metrics = Helvetica_Oblique.metrics; + break; + + case HELVETICA_BOLD_OBLIQUE: + font.name = Helvetica_BoldOblique.name; + font.bBoxLLx = Helvetica_BoldOblique.bBoxLLx; + font.bBoxLLy = Helvetica_BoldOblique.bBoxLLy; + font.bBoxURx = Helvetica_BoldOblique.bBoxURx; + font.bBoxURy = Helvetica_BoldOblique.bBoxURy; + font.underlinePosition = Helvetica_BoldOblique.underlinePosition; + font.underlineThickness = Helvetica_BoldOblique.underlineThickness; + font.metrics = Helvetica_BoldOblique.metrics; + break; + + case TIMES_ROMAN: + font.name = Times_Roman.name; + font.bBoxLLx = Times_Roman.bBoxLLx; + font.bBoxLLy = Times_Roman.bBoxLLy; + font.bBoxURx = Times_Roman.bBoxURx; + font.bBoxURy = Times_Roman.bBoxURy; + font.underlinePosition = Times_Roman.underlinePosition; + font.underlineThickness = Times_Roman.underlineThickness; + font.metrics = Times_Roman.metrics; + break; + + case TIMES_BOLD: + font.name = Times_Bold.name; + font.bBoxLLx = Times_Bold.bBoxLLx; + font.bBoxLLy = Times_Bold.bBoxLLy; + font.bBoxURx = Times_Bold.bBoxURx; + font.bBoxURy = Times_Bold.bBoxURy; + font.underlinePosition = Times_Bold.underlinePosition; + font.underlineThickness = Times_Bold.underlineThickness; + font.metrics = Times_Bold.metrics; + break; + + case TIMES_ITALIC: + font.name = Times_Italic.name; + font.bBoxLLx = Times_Italic.bBoxLLx; + font.bBoxLLy = Times_Italic.bBoxLLy; + font.bBoxURx = Times_Italic.bBoxURx; + font.bBoxURy = Times_Italic.bBoxURy; + font.underlinePosition = Times_Italic.underlinePosition; + font.underlineThickness = Times_Italic.underlineThickness; + font.metrics = Times_Italic.metrics; + break; + + case TIMES_BOLD_ITALIC: + font.name = Times_BoldItalic.name; + font.bBoxLLx = Times_BoldItalic.bBoxLLx; + font.bBoxLLy = Times_BoldItalic.bBoxLLy; + font.bBoxURx = Times_BoldItalic.bBoxURx; + font.bBoxURy = Times_BoldItalic.bBoxURy; + font.underlinePosition = Times_BoldItalic.underlinePosition; + font.underlineThickness = Times_BoldItalic.underlineThickness; + font.metrics = Times_BoldItalic.metrics; + break; + + case SYMBOL: + font.name = Symbol.name; + font.bBoxLLx = Symbol.bBoxLLx; + font.bBoxLLy = Symbol.bBoxLLy; + font.bBoxURx = Symbol.bBoxURx; + font.bBoxURy = Symbol.bBoxURy; + font.underlinePosition = Symbol.underlinePosition; + font.underlineThickness = Symbol.underlineThickness; + font.metrics = Symbol.metrics; + break; + + case ZAPF_DINGBATS: + font.name = ZapfDingbats.name; + font.bBoxLLx = ZapfDingbats.bBoxLLx; + font.bBoxLLy = ZapfDingbats.bBoxLLy; + font.bBoxURx = ZapfDingbats.bBoxURx; + font.bBoxURy = ZapfDingbats.bBoxURy; + font.underlinePosition = ZapfDingbats.underlinePosition; + font.underlineThickness = ZapfDingbats.underlineThickness; + font.metrics = ZapfDingbats.metrics; + break; + } + + return font; + } + +} diff --git a/PDFJet/src/main/java/com/pdfjet/State.java b/PDFJet/src/main/java/com/pdfjet/State.java new file mode 100644 index 0000000..0145f31 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/State.java @@ -0,0 +1,87 @@ +/** + * State.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +package com.pdfjet; + + +class State { + + private float[] pen; + private float[] brush; + private float pen_width; + private int line_cap_style; + private int line_join_style; + private String linePattern; + + + public State( + float[] pen, + float[] brush, + float pen_width, + int line_cap_style, + int line_join_style, + String linePattern) { + this.pen = new float[] { pen[0], pen[1], pen[2] }; + this.brush = new float[] { brush[0], brush[1], brush[2] }; + this.pen_width = pen_width; + this.line_cap_style = line_cap_style; + this.line_join_style = line_join_style; + this.linePattern = linePattern; + } + + + public float[] getPen() { + return pen; + } + + + public float[] getBrush() { + return brush; + } + + + public float getPenWidth() { + return pen_width; + } + + + public int getLineCapStyle() { + return line_cap_style; + } + + + public int getLineJoinStyle() { + return line_join_style; + } + + + public String getLinePattern() { + return linePattern; + } + +} // End of State.java diff --git a/PDFJet/src/main/java/com/pdfjet/StructElem.java b/PDFJet/src/main/java/com/pdfjet/StructElem.java new file mode 100644 index 0000000..bf77265 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/StructElem.java @@ -0,0 +1,51 @@ +/** + * StructElem.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + + +/** + * Used to specify PDF structure element objects. + * + * + */ +public class StructElem { + public static final String SPAN = "Span"; + public static final String P = "P"; + public static final String LINK = "Link"; + + protected int objNumber; + protected String structure = null; + protected int pageObjNumber; + protected int mcid = 0; + protected String language = null; + protected String altDescription = null; + protected String actualText = null; + protected Annotation annotation = null; +} diff --git a/PDFJet/src/main/java/com/pdfjet/Symbol.java b/PDFJet/src/main/java/com/pdfjet/Symbol.java new file mode 100644 index 0000000..5597768 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Symbol.java @@ -0,0 +1,238 @@ +package com.pdfjet; + +class Symbol { + protected static final String name = "Symbol"; + protected static final int bBoxLLx = -180; + protected static final int bBoxLLy = -293; + protected static final int bBoxURx = 1090; + protected static final int bBoxURy = 1010; + protected static final int underlinePosition = -100; + protected static final int underlineThickness = 50; + protected static final String notice = "Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated. All rights reserved."; + protected static final int[][] metrics = { + {32,250}, + {33,333}, + {34,713}, + {35,500}, + {36,549}, + {37,833}, + {38,778}, + {39,439}, + {40,333}, + {41,333}, + {42,500}, + {43,549}, + {44,250}, + {45,549}, + {46,250}, + {47,278}, + {48,500}, + {49,500}, + {50,500}, + {51,500}, + {52,500}, + {53,500}, + {54,500}, + {55,500}, + {56,500}, + {57,500}, + {58,278}, + {59,278}, + {60,549}, + {61,549}, + {62,549}, + {63,444}, + {64,549}, + {65,722}, + {66,667}, + {67,722}, + {68,612}, + {69,611}, + {70,763}, + {71,603}, + {72,722}, + {73,333}, + {74,631}, + {75,722}, + {76,686}, + {77,889}, + {78,722}, + {79,722}, + {80,768}, + {81,741}, + {82,556}, + {83,592}, + {84,611}, + {85,690}, + {86,439}, + {87,768}, + {88,645}, + {89,795}, + {90,611}, + {91,333}, + {92,863}, + {93,333}, + {94,658}, + {95,500}, + {96,500}, + {97,631}, + {98,549}, + {99,549}, + {100,494}, + {101,439}, + {102,521}, + {103,411}, + {104,603}, + {105,329}, + {106,603}, + {107,549}, + {108,549}, + {109,576}, + {110,521}, + {111,549}, + {112,549}, + {113,521}, + {114,549}, + {115,603}, + {116,439}, + {117,576}, + {118,713}, + {119,686}, + {120,493}, + {121,686}, + {122,494}, + {123,480}, + {124,200}, + {125,480}, + {126,549}, + {127,250}, + {128,250}, + {129,250}, + {130,250}, + {131,250}, + {132,250}, + {133,250}, + {134,250}, + {135,250}, + {136,250}, + {137,250}, + {138,250}, + {139,250}, + {140,250}, + {141,250}, + {142,250}, + {143,250}, + {144,250}, + {145,250}, + {146,250}, + {147,250}, + {148,250}, + {149,250}, + {150,250}, + {151,250}, + {152,250}, + {153,250}, + {154,250}, + {155,250}, + {156,250}, + {157,250}, + {158,250}, + {159,250}, + {160,750}, + {161,620}, + {162,247}, + {163,549}, + {164,167}, + {165,713}, + {166,500}, + {167,753}, + {168,753}, + {169,753}, + {170,753}, + {171,1042}, + {172,987}, + {173,603}, + {174,987}, + {175,603}, + {176,400}, + {177,549}, + {178,411}, + {179,549}, + {180,549}, + {181,713}, + {182,494}, + {183,460}, + {184,549}, + {185,549}, + {186,549}, + {187,549}, + {188,1000}, + {189,603}, + {190,1000}, + {191,658}, + {192,823}, + {193,686}, + {194,795}, + {195,987}, + {196,768}, + {197,768}, + {198,823}, + {199,768}, + {200,768}, + {201,713}, + {202,713}, + {203,713}, + {204,713}, + {205,713}, + {206,713}, + {207,713}, + {208,768}, + {209,713}, + {210,790}, + {211,790}, + {212,890}, + {213,823}, + {214,549}, + {215,250}, + {216,713}, + {217,603}, + {218,603}, + {219,1042}, + {220,987}, + {221,603}, + {222,987}, + {223,603}, + {224,494}, + {225,329}, + {226,790}, + {227,790}, + {228,786}, + {229,713}, + {230,384}, + {231,384}, + {232,384}, + {233,384}, + {234,384}, + {235,384}, + {236,494}, + {237,494}, + {238,494}, + {239,494}, + {240,250}, + {241,329}, + {242,274}, + {243,686}, + {244,686}, + {245,686}, + {246,384}, + {247,384}, + {248,384}, + {249,384}, + {250,384}, + {251,384}, + {252,494}, + {253,494}, + {254,494}, + {255,250}, + }; +} diff --git a/PDFJet/src/main/java/com/pdfjet/Table.java b/PDFJet/src/main/java/com/pdfjet/Table.java new file mode 100644 index 0000000..9fecdf7 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Table.java @@ -0,0 +1,819 @@ +/** + * Table.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + +import java.util.*; + + +/** + * Used to create table objects and draw them on a page. + * + * Please see Example_08. + */ +public class Table { + + public static final int DATA_HAS_0_HEADER_ROWS = 0; + public static final int DATA_HAS_1_HEADER_ROWS = 1; + public static final int DATA_HAS_2_HEADER_ROWS = 2; + public static final int DATA_HAS_3_HEADER_ROWS = 3; + public static final int DATA_HAS_4_HEADER_ROWS = 4; + public static final int DATA_HAS_5_HEADER_ROWS = 5; + public static final int DATA_HAS_6_HEADER_ROWS = 6; + public static final int DATA_HAS_7_HEADER_ROWS = 7; + public static final int DATA_HAS_8_HEADER_ROWS = 8; + public static final int DATA_HAS_9_HEADER_ROWS = 9; + + private int rendered = 0; + private int numOfPages; + + private List> tableData = null; + private int numOfHeaderRows = 0; + + private float x1; + private float y1; + + private float bottom_margin = 30f; + + + /** + * Create a table object. + * + */ + public Table() { + tableData = new ArrayList>(); + } + + + /** + * Sets the position (x, y) of the top left corner of this table on the page. + * + * @param x the x coordinate of the top left point of the table. + * @param y the y coordinate of the top left point of the table. + */ + public void setPosition(double x, double y) { + this.x1 = (float) x; + this.y1 = (float) y; + } + + + /** + * Sets the position (x, y) of the top left corner of this table on the page. + * + * @param x the x coordinate of the top left point of the table. + * @param y the y coordinate of the top left point of the table. + */ + public void setPosition(float x, float y) { + setLocation(x, y); + } + + + /** + * Sets the location (x, y) of the top left corner of this table on the page. + * + * @param x the x coordinate of the top left point of the table. + * @param y the y coordinate of the top left point of the table. + */ + public void setLocation(float x, float y) { + this.x1 = x; + this.y1 = y; + } + + + /** + * Sets the bottom margin for this table. + * + * @param bottom_margin the margin. + */ + public void setBottomMargin(double bottom_margin) { + this.bottom_margin = (float) bottom_margin; + } + + + /** + * Sets the bottom margin for this table. + * + * @param bottom_margin the margin. + */ + public void setBottomMargin(float bottom_margin) { + this.bottom_margin = bottom_margin; + } + + + /** + * Sets the table data. + * + * The table data is a perfect grid of cells. + * All cell should be an unique object and you can not reuse blank cell objects. + * Even if one or more cells have colspan bigger than zero the number of cells in the row will not change. + * + * @param tableData the table data. + */ + public void setData( + List> tableData) throws Exception { + this.tableData = tableData; + this.numOfHeaderRows = 0; + this.rendered = numOfHeaderRows; + } + + + /** + * Sets the table data and specifies the number of header rows in this data. + * + * @param tableData the table data. + * @param numOfHeaderRows the number of header rows in this data. + */ + public void setData( + List> tableData, int numOfHeaderRows) throws Exception { + this.tableData = tableData; + this.numOfHeaderRows = numOfHeaderRows; + this.rendered = numOfHeaderRows; + } + + + /** + * Auto adjusts the widths of all columns so that they are just wide enough to hold the text without truncation. + */ + public void autoAdjustColumnWidths() { + // Find the maximum text width for each column + float[] max_col_widths = new float[tableData.get(0).size()]; + for (int i = 0; i < tableData.size(); i++) { + List row = tableData.get(i); + for (int j = 0; j < row.size(); j++) { + Cell cell = row.get(j); + if (cell.getColSpan() == 1) { + float cellWidth = 0f; + if (cell.image != null) { + cellWidth = cell.image.getWidth(); + } + if (cell.text != null) { + if (cell.font.stringWidth(cell.fallbackFont, cell.text) > cellWidth) { + cellWidth = cell.font.stringWidth(cell.fallbackFont, cell.text); + } + } + cell.setWidth(cellWidth + cell.left_padding + cell.right_padding); + if (max_col_widths[j] == 0f || + cell.getWidth() > max_col_widths[j]) { + max_col_widths[j] = cell.getWidth(); + } + } + } + } + + for (int i = 0; i < tableData.size(); i++) { + List row = tableData.get(i); + for (int j = 0; j < row.size(); j++) { + Cell cell = row.get(j); + cell.setWidth(max_col_widths[j]); + } + } + } + + + /** + * Sets the alignment of the numbers to the right. + */ + public void rightAlignNumbers() { + for (int i = numOfHeaderRows; i < tableData.size(); i++) { + List row = tableData.get(i); + for (int j = 0; j < row.size(); j++) { + Cell cell = row.get(j); + if (cell.text != null) { + String str = cell.text; + int len = str.length(); + boolean isNumber = true; + int k = 0; + while (k < len) { + char ch = str.charAt(k++); + if (!Character.isDigit(ch) + && ch != '(' + && ch != ')' + && ch != '-' + && ch != '.' + && ch != ',' + && ch != '\'') { + isNumber = false; + } + } + if (isNumber) { + cell.setTextAlignment(Align.RIGHT); + } + } + } + } + } + + + /** + * Removes the horizontal lines between the rows from index1 to index2. + */ + public void removeLineBetweenRows( + int index1, int index2) throws Exception { + for (int j = index1; j < index2; j++) { + List row = tableData.get(j); + for (int i = 0; i < row.size(); i++) { + Cell cell = row.get(i); + cell.setBorder(Border.BOTTOM, false); + } + row = tableData.get(j + 1); + for (int i = 0; i < row.size(); i++) { + Cell cell = row.get(i); + cell.setBorder(Border.TOP, false); + } + } + } + + + /** + * Sets the text alignment in the specified column. + * + * @param index the index of the specified column. + * @param alignment the specified alignment. Supported values: Align.LEFT, Align.RIGHT, Align.CENTER and Align.JUSTIFY. + */ + public void setTextAlignInColumn( + int index, int alignment) throws Exception { + for (int i = 0; i < tableData.size(); i++) { + List row = tableData.get(i); + if (index < row.size()) { + row.get(index).setTextAlignment(alignment); + } + } + } + + + /** + * Sets the color of the text in the specified column. + * + * @param index the index of the specified column. + * @param color the color specified as an integer. + */ + public void setTextColorInColumn( + int index, int color) throws Exception { + for (int i = 0; i < tableData.size(); i++) { + List row = tableData.get(i); + if (index < row.size()) { + row.get(index).setBrushColor(color); + } + } + } + + + /** + * Sets the font for the specified column. + * + * @param index the column index. + * @param font the font. + */ + public void setFontInColumn(int index, Font font) throws Exception { + for (int i = 0; i < tableData.size(); i++) { + List row = tableData.get(i); + if (index < row.size()) { + row.get(index).font = font; + } + } + } + + + /** + * Sets the color of the text in the specified row. + * + * @param index the index of the specified row. + * @param color the color specified as an integer. + */ + public void setTextColorInRow( + int index, int color) throws Exception { + List row = tableData.get(index); + for (int i = 0; i < row.size(); i++) { + row.get(i).setBrushColor(color); + } + } + + + /** + * Sets the font for the specified row. + * + * @param index the row index. + * @param font the font. + */ + public void setFontInRow(int index, Font font) throws Exception { + List row = tableData.get(index); + for (int i = 0; i < row.size(); i++) { + row.get(i).font = font; + } + } + + + /** + * Sets the width of the column with the specified index. + * + * @param index the index of specified column. + * @param width the specified width. + */ + public void setColumnWidth( + int index, float width) throws Exception { + for (int i = 0; i < tableData.size(); i++) { + List row = tableData.get(i); + if (index < row.size()) { + row.get(index).setWidth(width); + } + } + } + + + /** + * Returns the column width of the column at the specified index. + * + * @param index the index of the column. + * @return the width of the column. + */ + public float getColumnWidth(int index) throws Exception { + return getCellAtRowColumn(0, index).getWidth(); + } + + + /** + * Returns the cell at the specified row and column. + * + * @param row the specified row. + * @param col the specified column. + * + * @return the cell at the specified row and column. + */ + public Cell getCellAt( + int row, int col) throws Exception { + if (row >= 0) { + return tableData.get(row).get(col); + } + return tableData.get(tableData.size() + row).get(col); + } + + + /** + * Returns the cell at the specified row and column. + * + * @param row the specified row. + * @param col the specified column. + * + * @return the cell at the specified row and column. + */ + public Cell getCellAtRowColumn(int row, int col) throws Exception { + return getCellAt(row, col); + } + + + /** + * Returns a list of cell for the specified row. + * + * @param index the index of the specified row. + * + * @return the list of cells. + */ + public List getRow(int index) throws Exception { + return tableData.get(index); + } + + + public List getRowAtIndex(int index) throws Exception { + return getRow(index); + } + + + /** + * Returns a list of cell for the specified column. + * + * @param index the index of the specified column. + * + * @return the list of cells. + */ + public List getColumn(int index) throws Exception { + List column = new ArrayList(); + for (int i = 0; i < tableData.size(); i++) { + List row = tableData.get(i); + if (index < row.size()) { + column.add(row.get(index)); + } + } + return column; + } + + + public List getColumnAtIndex(int index) throws Exception { + return getColumn(index); + } + + + /** + * Returns the total number of pages that are required to draw this table on. + * + * @param page the type of pages we are drawing this table on. + * + * @return the number of pages. + */ + public int getNumberOfPages(Page page) throws Exception { + numOfPages = 1; + while (hasMoreData()) { + drawOn(page, false); + } + resetRenderedPagesCount(); + return numOfPages; + } + + + /** + * Draws this table on the specified page. + * + * @param page the page to draw this table on. + * + * @return Point the point on the page where to draw the next component. + */ + public Point drawOn(Page page) throws Exception { + return drawOn(page, true); + } + + + /** + * Draws this table on the specified page. + * + * @param page the page to draw this table on. + * @param draw if false - do not draw the table. Use to only find out where the table ends. + * + * @return Point the point on the page where to draw the next component. + */ + private Point drawOn(Page page, boolean draw) throws Exception { + return drawTableRows(page, draw, drawHeaderRows(page, draw)); + } + + + private float[] drawHeaderRows(Page page, boolean draw) throws Exception { + float x = x1; + float y = y1; + float cell_w = 0f; + float cell_h = 0f; + + for (int i = 0; i < numOfHeaderRows; i++) { + List dataRow = tableData.get(i); + cell_h = getMaxCellHeight(dataRow); + + for (int j = 0; j < dataRow.size(); j++) { + Cell cell = dataRow.get(j); + cell_w = cell.getWidth(); + int colspan = cell.getColSpan(); + for (int k = 1; k < colspan; k++) { + cell_w += dataRow.get(++j).width; + } + + if (draw) { + page.setBrushColor(cell.getBrushColor()); + cell.paint(page, x, y, cell_w, cell_h); + } + + x += cell_w; + } + x = x1; + y += cell_h; + } + + return new float[] {x, y, cell_w, cell_h}; + } + + + private Point drawTableRows(Page page, boolean draw, float[] parameter) throws Exception { + float x = parameter[0]; + float y = parameter[1]; + float cell_w = parameter[2]; + float cell_h = parameter[3]; + + for (int i = rendered; i < tableData.size(); i++) { + List dataRow = tableData.get(i); + cell_h = getMaxCellHeight(dataRow); + + for (int j = 0; j < dataRow.size(); j++) { + Cell cell = dataRow.get(j); + cell_w = cell.getWidth(); + int colspan = cell.getColSpan(); + for (int k = 1; k < colspan; k++) { + cell_w += dataRow.get(++j).getWidth(); + } + + if (draw) { + page.setBrushColor(cell.getBrushColor()); + cell.paint(page, x, y, cell_w, cell_h); + } + + x += cell_w; + } + x = x1; + y += cell_h; + + // Consider the height of the next row when checking if we must go to a new page + if (i < (tableData.size() - 1)) { + List nextRow = tableData.get(i + 1); + for (int j = 0; j < nextRow.size(); j++) { + Cell cell = nextRow.get(j); + float cellHeight = cell.getHeight(); + if (cellHeight > cell_h) { + cell_h = cellHeight; + } + } + } + + if ((y + cell_h) > (page.height - bottom_margin)) { + if (i == tableData.size() - 1) { + rendered = -1; + } + else { + rendered = i + 1; + numOfPages++; + } + return new Point(x, y); + } + } + rendered = -1; + + return new Point(x, y); + } + + + private float getMaxCellHeight(List row) { + float max_cell_height = 0f; + for (int j = 0; j < row.size(); j++) { + Cell cell = row.get(j); + if (cell.getHeight() > max_cell_height) { + max_cell_height = cell.getHeight(); + } + } + return max_cell_height; + } + + + /** + * Returns true if the table contains more data that needs to be drawn on a page. + */ + public boolean hasMoreData() { + return rendered != -1; + } + + + /** + * Returns the width of this table when drawn on a page. + * + * @return the widht of this table. + */ + public float getWidth() { + float table_width = 0f; + List row = tableData.get(0); + for (int i = 0; i < row.size(); i++) { + table_width += row.get(i).getWidth(); + } + return table_width; + } + + + /** + * Returns the number of data rows that have been rendered so far. + * + * @return the number of data rows that have been rendered so far. + */ + public int getRowsRendered() { + return rendered == -1 ? rendered : rendered - numOfHeaderRows; + } + + + /** + * Just calls the wrapAroundCellText method. + */ + @Deprecated + public void wrapAroundCellText2() { + wrapAroundCellText(); + } + + + /** + * Wraps around the text in all cells so it fits the column width. + * This method should be called after all calls to setColumnWidth and autoAdjustColumnWidths. + * + */ + public void wrapAroundCellText() { + List> tableData2 = new ArrayList>(); + + for (int i = 0; i < tableData.size(); i++) { + List row = tableData.get(i); + int maxNumVerCells = 1; + for (int j = 0; j < row.size(); j++) { + Cell cell = row.get(j); + int colspan = cell.getColSpan(); + for (int n = 1; n < colspan; n++) { + Cell next = row.get(j + n); + cell.setWidth(cell.getWidth() + next.getWidth()); + next.setWidth(0f); + } + int numVerCells = cell.getNumVerCells(); + if (numVerCells > maxNumVerCells) { + maxNumVerCells = numVerCells; + } + } + + for (int j = 0; j < maxNumVerCells; j++) { + List row2 = new ArrayList(); + for (int k = 0; k < row.size(); k++) { + Cell cell = row.get(k); + + Cell cell2 = new Cell(cell.getFont(), ""); + cell2.setFallbackFont(cell.getFallbackFont()); + cell2.setPoint(cell.getPoint()); + cell2.setWidth(cell.getWidth()); + if (j == 0) { + cell2.setTopPadding(cell.top_padding); + } + if (j == (maxNumVerCells - 1)) { + cell2.setBottomPadding(cell.bottom_padding); + } + cell2.setLeftPadding(cell.left_padding); + cell2.setRightPadding(cell.right_padding); + cell2.setLineWidth(cell.lineWidth); + cell2.setBgColor(cell.getBgColor()); + cell2.setPenColor(cell.getPenColor()); + cell2.setBrushColor(cell.getBrushColor()); + cell2.setProperties(cell.getProperties()); + cell2.setVerTextAlignment(cell.getVerTextAlignment()); + cell2.setIgnoreImageHeight(cell.getIgnoreImageHeight()); + + if (j == 0) { + cell2.setImage(cell.getImage()); + if (cell.getCompositeTextLine() != null) { + cell2.setCompositeTextLine(cell.getCompositeTextLine()); + } + else { + cell2.setText(cell.getText()); + } + if (maxNumVerCells > 1) { + cell2.setBorder(Border.BOTTOM, false); + } + } + else { + cell2.setBorder(Border.TOP, false); + if (j < (maxNumVerCells - 1)) { + cell2.setBorder(Border.BOTTOM, false); + } + } + row2.add(cell2); + } + tableData2.add(row2); + } + } + + for (int i = 0; i < tableData2.size(); i++) { + List row = tableData2.get(i); + for (int j = 0; j < row.size(); j++) { + Cell cell = row.get(j); + if (cell.text != null) { + int n = 0; + String[] textLines = cell.getText().split("\\r?\\n"); + for (String textLine : textLines) { + StringBuilder sb = new StringBuilder(); + String[] tokens = textLine.split("\\s+"); + if (tokens.length == 1) { + sb.append(tokens[0]); + } + else { + for (int k = 0; k < tokens.length; k++) { + String token = tokens[k]; + if (cell.font.stringWidth(cell.fallbackFont, sb.toString() + " " + token) > + (cell.getWidth() - (cell.left_padding + cell.right_padding))) { + tableData2.get(i + n).get(j).setText(sb.toString()); + sb = new StringBuilder(token); + n++; + } + else { + if (k > 0) { + sb.append(" "); + } + sb.append(token); + } + } + } + tableData2.get(i + n).get(j).setText(sb.toString()); + n++; + } + } + else { + tableData2.get(i).get(j).setCompositeTextLine(cell.getCompositeTextLine()); + } + } + } + + tableData = tableData2; + } + + + /** + * Sets all table cells borders to false. + * + */ + public void setNoCellBorders() { + for (int i = 0; i < tableData.size(); i++) { + List row = tableData.get(i); + for (int j = 0; j < row.size(); j++) { + tableData.get(i).get(j).setNoBorders(); + } + } + } + + + /** + * Sets the color of the cell border lines. + * + * @param color the color of the cell border lines. + */ + public void setCellBordersColor(int color) { + for (int i = 0; i < tableData.size(); i++) { + List row = tableData.get(i); + for (int j = 0; j < row.size(); j++) { + tableData.get(i).get(j).setPenColor(color); + } + } + } + + + /** + * Sets the width of the cell border lines. + * + * @param width the width of the border lines. + */ + public void setCellBordersWidth(float width) { + for (int i = 0; i < tableData.size(); i++) { + List row = tableData.get(i); + for (int j = 0; j < row.size(); j++) { + tableData.get(i).get(j).setLineWidth(width); + } + } + } + + + /** + * Resets the rendered pages count. + * Call this method if you have to draw this table more than one time. + */ + public void resetRenderedPagesCount() { + this.rendered = numOfHeaderRows; + } + + + /** + * This method removes borders that have the same color and overlap 100%. + * The result is improved onscreen rendering of thin border lines by some PDF viewers. + */ + public void mergeOverlaidBorders() { + for (int i = 0; i < tableData.size(); i++) { + List currentRow = tableData.get(i); + for (int j = 0; j < currentRow.size(); j++) { + Cell currentCell = currentRow.get(j); + if (j < currentRow.size() - 1) { + Cell cellAtRight = currentRow.get(j + 1); + if (cellAtRight.getBorder(Border.LEFT) && + currentCell.getPenColor() == cellAtRight.getPenColor() && + currentCell.getLineWidth() == cellAtRight.getLineWidth() && + (currentCell.getColSpan() + j) < (currentRow.size() - 1)) { + currentCell.setBorder(Border.RIGHT, false); + } + } + if (i < tableData.size() - 1) { + List nextRow = tableData.get(i + 1); + Cell cellBelow = nextRow.get(j); + if (cellBelow.getBorder(Border.TOP) && + currentCell.getPenColor() == cellBelow.getPenColor() && + currentCell.getLineWidth() == cellBelow.getLineWidth()) { + currentCell.setBorder(Border.BOTTOM, false); + } + } + } + } + } + +} // End of Table.java diff --git a/PDFJet/src/main/java/com/pdfjet/Tabloid.java b/PDFJet/src/main/java/com/pdfjet/Tabloid.java new file mode 100644 index 0000000..b9fcd61 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Tabloid.java @@ -0,0 +1,41 @@ +/** + * Tabloid.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + + +/** + * Used to specify PDF page with size Tabloid. + * For more information about the page size classes - A3, A4, A5, B5, Executive, Letter, Legal and Tabloid - see the Page class. + * + */ +public class Tabloid { + public static final float[] PORTRAIT = new float[] {792.0f, 1224.0f}; + public static final float[] LANDSCAPE = new float[] {1224.0f, 792.0f}; +} diff --git a/PDFJet/src/main/java/com/pdfjet/Text.java b/PDFJet/src/main/java/com/pdfjet/Text.java new file mode 100644 index 0000000..79abe26 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Text.java @@ -0,0 +1,254 @@ +/** + * Text.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + +import java.util.*; + + +/** + * Please see Example_45 + */ +public class Text { + + private List paragraphs; + private Font font; + private Font fallbackFont; + private float x; + private float y; + private float w; + private float x_text; + private float y_text; + private float leading; + private float paragraphLeading; + private List beginParagraphPoints; + private List endParagraphPoints; + private float spaceBetweenTextLines; + + + public Text(List paragraphs) throws Exception { + this.paragraphs = paragraphs; + this.font = paragraphs.get(0).list.get(0).getFont(); + this.fallbackFont = paragraphs.get(0).list.get(0).getFallbackFont(); + this.leading = font.getBodyHeight(); + this.paragraphLeading = 2*leading; + this.beginParagraphPoints = new ArrayList(); + this.endParagraphPoints = new ArrayList(); + this.spaceBetweenTextLines = font.stringWidth(fallbackFont, Single.space); + } + + + public Text setLocation(float x, float y) { + this.x = x; + this.y = y; + return this; + } + + + public Text setWidth(float w) { + this.w = w; + return this; + } + + + public Text setLeading(float leading) { + this.leading = leading; + return this; + } + + + public Text setParagraphLeading(float paragraphLeading) { + this.paragraphLeading = paragraphLeading; + return this; + } + + + public List getBeginParagraphPoints() { + return this.beginParagraphPoints; + } + + + public List getEndParagraphPoints() { + return this.endParagraphPoints; + } + + + public Text setSpaceBetweenTextLines(float spaceBetweenTextLines) { + this.spaceBetweenTextLines = spaceBetweenTextLines; + return this; + } + + + public float[] drawOn(Page page) throws Exception { + return drawOn(page, true); + } + + + public float[] drawOn(Page page, boolean draw) throws Exception { + this.x_text = x; + this.y_text = y + font.getAscent(); + for (Paragraph paragraph : paragraphs) { + int numberOfTextLines = paragraph.list.size(); + StringBuilder buf = new StringBuilder(); + for (int i = 0; i < numberOfTextLines; i++) { + TextLine textLine = paragraph.list.get(i); + buf.append(textLine.getText()); + } + for (int i = 0; i < numberOfTextLines; i++) { + TextLine textLine = paragraph.list.get(i); + if (i == 0) { + beginParagraphPoints.add(new float[] { x_text, y_text }); + } + textLine.setAltDescription((i == 0) ? buf.toString() : Single.space); + textLine.setActualText((i == 0) ? buf.toString() : Single.space); + float[] point = drawTextLine( + page, x_text, y_text, textLine, draw); + if (i == (numberOfTextLines - 1)) { + endParagraphPoints.add(new float[] { point[0], point[1] }); + } + x_text = point[0]; + if (textLine.getTrailingSpace()) { + x_text += spaceBetweenTextLines; + } + y_text = point[1]; + } + x_text = x; + y_text += paragraphLeading; + } + return new float[] { x_text, y_text + font.getDescent() }; + } + + + public float[] drawTextLine( + Page page, + float x_text, + float y_text, + TextLine textLine, + boolean draw) throws Exception { + + Font font = textLine.getFont(); + Font fallbackFont = textLine.getFallbackFont(); + int color = textLine.getColor(); + + String[] tokens = null; + String str = textLine.getText(); + if (stringIsCJK(str)) { + tokens = tokenizeCJK(str, this.w); + } + else { + tokens = str.split("\\s+"); + } + + StringBuilder buf = new StringBuilder(); + boolean firstTextSegment = true; + for (int i = 0; i < tokens.length; i++) { + String token = (i == 0) ? tokens[i] : (Single.space + tokens[i]); + if (font.stringWidth(fallbackFont, token) < (this.w - (x_text - x))) { + buf.append(token); + x_text += font.stringWidth(fallbackFont, token); + } + else { + if (draw) { + new TextLine(font, buf.toString()) + .setFallbackFont(fallbackFont) + .setLocation(x_text - font.stringWidth(fallbackFont, buf.toString()), + y_text + textLine.getVerticalOffset()) + .setColor(color) + .setUnderline(textLine.getUnderline()) + .setStrikeout(textLine.getStrikeout()) + .setLanguage(textLine.getLanguage()) + .setAltDescription(firstTextSegment ? textLine.getAltDescription() : Single.space) + .setActualText(firstTextSegment ? textLine.getActualText() : Single.space) + .drawOn(page); + firstTextSegment = false; + } + x_text = x + font.stringWidth(fallbackFont, tokens[i]); + y_text += leading; + buf.setLength(0); + buf.append(tokens[i]); + } + } + if (draw) { + new TextLine(font, buf.toString()) + .setFallbackFont(fallbackFont) + .setLocation(x_text - font.stringWidth(fallbackFont, buf.toString()), + y_text + textLine.getVerticalOffset()) + .setColor(color) + .setUnderline(textLine.getUnderline()) + .setStrikeout(textLine.getStrikeout()) + .setLanguage(textLine.getLanguage()) + .setAltDescription(firstTextSegment ? textLine.getAltDescription() : Single.space) + .setActualText(firstTextSegment ? textLine.getActualText() : Single.space) + .drawOn(page); + firstTextSegment = false; + } + + return new float[] { x_text, y_text }; + } + + + private boolean stringIsCJK(String str) { + // CJK Unified Ideographs Range: 4E00–9FD5 + // Hiragana Range: 3040–309F + // Katakana Range: 30A0–30FF + // Hangul Jamo Range: 1100–11FF + int numOfCJK = 0; + for (int i = 0; i < str.length(); i++) { + char ch = str.charAt(i); + if ((ch >= 0x4E00 && ch <= 0x9FD5) || + (ch >= 0x3040 && ch <= 0x309F) || + (ch >= 0x30A0 && ch <= 0x30FF) || + (ch >= 0x1100 && ch <= 0x11FF)) { + numOfCJK += 1; + } + } + return (numOfCJK > (str.length() / 2)); + } + + + private String[] tokenizeCJK(String str, float textWidth) { + List list = new ArrayList(); + StringBuilder buf = new StringBuilder(); + for (int i = 0; i < str.length(); i++) { + char ch = str.charAt(i); + if (font.stringWidth(fallbackFont, buf.toString()) < textWidth) { + buf.append(ch); + } + else { + list.add(buf.toString()); + buf.setLength(0); + } + } + if (buf.toString().length() > 0) { + list.add(buf.toString()); + } + return list.toArray(new String[list.size()]); + } + +} // End of Text.java diff --git a/PDFJet/src/main/java/com/pdfjet/TextBlock.java b/PDFJet/src/main/java/com/pdfjet/TextBlock.java new file mode 100644 index 0000000..6fd59de --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/TextBlock.java @@ -0,0 +1,359 @@ +/** + * TextBlock.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +package com.pdfjet; + +import java.util.*; + + +/** + * Class for creating blocks of text. + * + */ +public class TextBlock { + + private Font font = null; + private Font fallbackFont = null; + + private String text = null; + private float space = 0f; + private int textAlign = Align.LEFT; + + private float x; + private float y; + private float w = 300f; + private float h = 200f; + + private int background = Color.white; + private int brush = Color.black; + + + /** + * Creates a text block. + * + * @param font the text font. + */ + public TextBlock(Font font) { + this.font = font; + this.space = this.font.getDescent(); + } + + + /** + * Sets the fallback font. + * + * @param fallbackFont the fallback font. + * @return the TextBlock object. + */ + public TextBlock setFallbackFont(Font fallbackFont) { + this.fallbackFont = fallbackFont; + return this; + } + + + /** + * Sets the block text. + * + * @param text the block text. + * @return the TextBlock object. + */ + public TextBlock setText(String text) { + this.text = text; + return this; + } + + + /** + * Sets the location where this text block will be drawn on the page. + * + * @param x the x coordinate of the top left corner of the text block. + * @param y the y coordinate of the top left corner of the text block. + * @return the TextBlock object. + */ + public TextBlock setLocation(float x, float y) { + this.x = x; + this.y = y; + return this; + } + + + /** + * Sets the width of this text block. + * + * @param width the specified width. + * @return the TextBlock object. + */ + public TextBlock setWidth(float width) { + this.w = width; + return this; + } + + + /** + * Returns the text block width. + * + * @return the text block width. + */ + public float getWidth() { + return this.w; + } + + + /** + * Sets the height of this text block. + * + * @param height the specified height. + * @return the TextBlock object. + */ + public TextBlock setHeight(float height) { + this.h = height; + return this; + } + + + /** + * Returns the text block height. + * + * @return the text block height. + */ + public float getHeight() throws Exception { + return drawOn(null).h; + } + + + /** + * Sets the space between two lines of text. + * + * @param space the space between two lines. + * @return the TextBlock object. + */ + public TextBlock setSpaceBetweenLines(float space) { + this.space = space; + return this; + } + + + /** + * Returns the space between two lines of text. + * + * @return float the space. + */ + public float getSpaceBetweenLines() { + return space; + } + + + /** + * Sets the text alignment. + * + * @param textAlign the alignment parameter. + * Supported values: Align.LEFT, Align.RIGHT and Align.CENTER. + */ + public TextBlock setTextAlignment(int textAlign) { + this.textAlign = textAlign; + return this; + } + + + /** + * Returns the text alignment. + * + * @return the alignment code. + */ + public int getTextAlignment() { + return this.textAlign; + } + + + /** + * Sets the background to the specified color. + * + * @param color the color specified as 0xRRGGBB integer. + * @return the TextBlock object. + */ + public TextBlock setBgColor(int color) { + this.background = color; + return this; + } + + + /** + * Returns the background color. + * + * @return int the color as 0xRRGGBB integer. + */ + public int getBgColor() { + return this.background; + } + + + /** + * Sets the brush color. + * + * @param color the color specified as 0xRRGGBB integer. + * @return the TextBlock object. + */ + public TextBlock setBrushColor(int color) { + this.brush = color; + return this; + } + + + /** + * Returns the brush color. + * + * @return int the brush color specified as 0xRRGGBB integer. + */ + public int getBrushColor() { + return this.brush; + } + + + // Is the text Chinese, Japanese or Korean? + private boolean isCJK(String text) { + int cjk = 0; + int other = 0; + for (char ch : text.toCharArray()) { + if (ch >= 0x4E00 && ch <= 0x9FFF || // Unified CJK + ch >= 0xAC00 && ch <= 0xD7AF || // Hangul (Korean) + ch >= 0x30A0 && ch <= 0x30FF || // Katakana (Japanese) + ch >= 0x3040 && ch <= 0x309F) { // Hiragana (Japanese) + cjk += 1; + } + else { + other += 1; + } + } + return cjk > other; + } + + + /** + * Draws this text block on the specified page. + * + * @param page the page to draw this text block on. + * @return the TextBlock object. + */ + public TextBlock drawOn(Page page) throws Exception { + if (page != null) { + if (getBgColor() != Color.white) { + page.setBrushColor(this.background); + page.fillRect(x, y, w, h); + } + page.setBrushColor(this.brush); + } + return drawText(page); + } + + + private TextBlock drawText(Page page) throws Exception { + + List list = new ArrayList(); + StringBuilder buf = new StringBuilder(); + String[] lines = text.split("\\r?\\n"); + for (String line : lines) { + if (isCJK(line)) { + buf.setLength(0); + for (int i = 0; i < line.length(); i++) { + Character ch = line.charAt(i); + if (font.stringWidth(fallbackFont, buf.toString() + ch) < this.w) { + buf.append(ch); + } + else { + list.add(buf.toString()); + buf.setLength(0); + buf.append(ch); + } + } + if (!buf.toString().trim().equals("")) { + list.add(buf.toString().trim()); + } + } + else { + if (font.stringWidth(fallbackFont, line) < this.w) { + list.add(line); + } + else { + buf.setLength(0); + String[] tokens = line.split("\\s+"); + for (String token : tokens) { + if (font.stringWidth(fallbackFont, + buf.toString() + " " + token) < this.w) { + buf.append(" " + token); + } + else { + list.add(buf.toString().trim()); + buf.setLength(0); + buf.append(token); + } + } + + if (!buf.toString().trim().equals("")) { + list.add(buf.toString().trim()); + } + } + } + } + lines = list.toArray(new String[] {}); + + float x_text; + float y_text = y + font.getAscent(); + + for (int i = 0; i < lines.length; i++) { + if (textAlign == Align.LEFT) { + x_text = x; + } + else if (textAlign == Align.RIGHT) { + x_text = (x + this.w) - (font.stringWidth(fallbackFont, lines[i])); + } + else if (textAlign == Align.CENTER) { + x_text = x + (this.w - font.stringWidth(fallbackFont, lines[i]))/2; + } + else { + throw new Exception("Invalid text alignment option."); + } + + if (page != null) { + page.drawString( + font, fallbackFont, lines[i], x_text, y_text); + } + + if (i < (lines.length - 1)) { + y_text += font.getBodyHeight() + space; + } + else { + y_text += font.getDescent() + space; + } + } + + this.h = y_text - y; + + return this; + } + +} // End of TextBlock.java diff --git a/PDFJet/src/main/java/com/pdfjet/TextBox.java b/PDFJet/src/main/java/com/pdfjet/TextBox.java new file mode 100644 index 0000000..e9fed9e --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/TextBox.java @@ -0,0 +1,909 @@ +/** + * TextBox.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +package com.pdfjet; + +import java.util.*; + +/** + * A box containing line-wrapped text. + * + *

Defaults:
+ * x = 0f
+ * y = 0f
+ * width = 300f
+ * height = 0f
+ * alignment = Align.LEFT
+ * valign = Align.TOP
+ * spacing = 3f
+ * margin = 1f
+ *

+ * + * This class was originally developed by Ronald Bourret. + * It was completely rewritten in 2013 by Eugene Dragoev. + */ +public class TextBox implements Drawable { + + protected Font font; + protected String text; + + protected float x; + protected float y; + + protected float width = 300f; + protected float height = 0f; + protected float spacing = 3f; + protected float margin = 1f; + private float lineWidth = 0f; + + private int background = Color.transparent; + private int pen = Color.black; + private int brush = Color.black; + private int valign = 0; + private Font fallbackFont; + private Map colors = null; + + // TextBox properties + // Future use: + // bits 0 to 15 + // Border: + // bit 16 - top + // bit 17 - bottom + // bit 18 - left + // bit 19 - right + // Text Alignment: + // bit 20 + // bit 21 + // Text Decoration: + // bit 22 - underline + // bit 23 - strikeout + // Future use: + // bits 24 to 31 + private int properties = 0x000F0001; + + + /** + * Creates a text box and sets the font. + * + * @param font the font. + */ + public TextBox(Font font) { + this.font = font; + } + + + /** + * Creates a text box and sets the font. + * + * @param text the text. + * @param font the font. + */ + public TextBox(Font font, String text) { + this.font = font; + this.text = text; + } + + + /** + * Creates a text box and sets the font and the text. + * + * @param font the font. + * @param text the text. + * @param width the width. + * @param height the height. + */ + public TextBox(Font font, String text, double width, double height) { + this(font, text, (float) width, (float) height); + } + + + /** + * Creates a text box and sets the font and the text. + * + * @param font the font. + * @param text the text. + * @param width the width. + * @param height the height. + */ + public TextBox(Font font, String text, float width, float height) { + this.font = font; + this.text = text; + this.width = width; + this.height = height; + } + + + /** + * Sets the font for this text box. + * + * @param font the font. + */ + public void setFont(Font font) { + this.font = font; + } + + + /** + * Returns the font used by this text box. + * + * @return the font. + */ + public Font getFont() { + return font; + } + + + /** + * Sets the text box text. + * + * @param text the text box text. + */ + public void setText(String text) { + this.text = text; + } + + + /** + * Returns the text box text. + * + * @return the text box text. + */ + public String getText() { + return text; + } + + + /** + * Sets the position where this text box will be drawn on the page. + * + * @param x the x coordinate of the top left corner of the text box. + * @param y the y coordinate of the top left corner of the text box. + */ + public void setPosition(double x, double y) { + setPosition((float) x, (float) y); + } + + + /** + * Sets the position where this text box will be drawn on the page. + * + * @param x the x coordinate of the top left corner of the text box. + * @param y the y coordinate of the top left corner of the text box. + */ + public void setPosition(float x, float y) { + setLocation(x, y); + } + + + /** + * Sets the location where this text box will be drawn on the page. + * + * @param x the x coordinate of the top left corner of the text box. + * @param y the y coordinate of the top left corner of the text box. + */ + public void setLocation(float x, float y) { + this.x = x; + this.y = y; + } + + + /** + * Gets the x coordinate where this text box will be drawn on the page. + * + * @return the x coordinate of the top left corner of the text box. + */ + public float getX() { + return x; + } + + + /** + * Gets the y coordinate where this text box will be drawn on the page. + * + * @return the y coordinate of the top left corner of the text box. + */ + public float getY() { + return y; + } + + + /** + * Sets the width of this text box. + * + * @param width the specified width. + */ + public void setWidth(double width) { + this.width = (float) width; + } + + + /** + * Sets the width of this text box. + * + * @param width the specified width. + */ + public void setWidth(float width) { + this.width = width; + } + + + /** + * Returns the text box width. + * + * @return the text box width. + */ + public float getWidth() { + return width; + } + + + /** + * Sets the height of this text box. + * + * @param height the specified height. + */ + public void setHeight(double height) { + this.height = (float) height; + } + + + /** + * Sets the height of this text box. + * + * @param height the specified height. + */ + public void setHeight(float height) { + this.height = height; + } + + + /** + * Returns the text box height. + * + * @return the text box height. + */ + public float getHeight() { + return height; + } + + + /** + * Sets the margin of this text box. + * + * @param margin the margin between the text and the box + */ + public void setMargin(double margin) { + this.margin = (float) margin; + } + + + /** + * Sets the margin of this text box. + * + * @param margin the margin between the text and the box + */ + public void setMargin(float margin) { + this.margin = margin; + } + + + /** + * Returns the text box margin. + * + * @return the margin between the text and the box + */ + public float getMargin() { + return margin; + } + + + /** + * Sets the border line width. + * + * @param lineWidth double + */ + public void setLineWidth(double lineWidth) { + this.lineWidth = (float) lineWidth; + } + + + /** + * Sets the border line width. + * + * @param lineWidth float + */ + public void setLineWidth(float lineWidth) { + this.lineWidth = lineWidth; + } + + + /** + * Returns the border line width. + * + * @return float the line width. + */ + public float getLineWidth() { + return lineWidth; + } + + + /** + * Sets the spacing between lines of text. + * + * @param spacing the spacing + */ + public void setSpacing(double spacing) { + this.spacing = (float) spacing; + } + + + /** + * Sets the spacing between lines of text. + * + * @param spacing + */ + public void setSpacing(float spacing) { + this.spacing = spacing; + } + + + /** + * Returns the spacing between lines of text. + * + * @return float the spacing. + */ + public float getSpacing() { + return spacing; + } + + + /** + * Sets the background to the specified color. + * + * @param color the color specified as 0xRRGGBB integer. + */ + public void setBgColor(int color) { + this.background = color; + } + + + /** + * Sets the background to the specified color. + * + * @param color the color specified as array of integer values from 0x00 to 0xFF. + */ + public void setBgColor(int[] color) { + this.background = color[0] << 16 | color[1] << 8 | color[2]; + } + + + /** + * Sets the background to the specified color. + * + * @param color the color specified as array of double values from 0.0 to 1.0. + */ + public void setBgColor(double[] color) { + setBgColor(new int[] { (int) color[0], (int) color[1], (int) color[2] }); + } + + + /** + * Returns the background color. + * + * @return int the color as 0xRRGGBB integer. + */ + public int getBgColor() { + return this.background; + } + + + /** + * Sets the pen and brush colors to the specified color. + * + * @param color the color specified as 0xRRGGBB integer. + */ + public void setFgColor(int color) { + this.pen = color; + this.brush = color; + } + + + /** + * Sets the pen and brush colors to the specified color. + * + * @param color the color specified as 0xRRGGBB integer. + */ + public void setFgColor(int[] color) { + this.pen = color[0] << 16 | color[1] << 8 | color[2]; + this.brush = pen; + } + + + /** + * Sets the foreground pen and brush colors to the specified color. + * + * @param color the color specified as an array of double values from 0.0 to 1.0. + */ + public void setFgColor(double[] color) { + setPenColor(new int[] { (int) color[0], (int) color[1], (int) color[2] }); + setBrushColor(pen); + } + + + /** + * Sets the pen color. + * + * @param color the color specified as 0xRRGGBB integer. + */ + public void setPenColor(int color) { + this.pen = color; + } + + + /** + * Sets the pen color. + * + * @param color the color specified as an array of int values from 0x00 to 0xFF. + */ + public void setPenColor(int[] color) { + this.pen = color[0] << 16 | color[1] << 8 | color[2]; + } + + + /** + * Sets the pen color. + * + * @param color the color specified as an array of double values from 0.0 to 1.0. + */ + public void setPenColor(double[] color) { + setPenColor(new int[] { (int) color[0], (int) color[1], (int) color[2] }); + } + + + /** + * Returns the pen color as 0xRRGGBB integer. + * + * @return int the pen color. + */ + public int getPenColor() { + return this.pen; + } + + + /** + * Sets the brush color. + * + * @param color the color specified as 0xRRGGBB integer. + */ + public void setBrushColor(int color) { + this.brush = color; + } + + + /** + * Sets the brush color. + * + * @param color the color specified as an array of int values from 0x00 to 0xFF. + */ + public void setBrushColor(int[] color) { + this.brush = color[0] << 16 | color[1] << 8 | color[2]; + } + + + /** + * Sets the brush color. + * + * @param color the color specified as an array of double values from 0.0 to 1.0. + */ + public void setBrushColor(double[] color) { + setBrushColor(new int [] { (int) color[0], (int) color[1], (int) color[2] }); + } + + + /** + * Returns the brush color. + * + * @return int the brush color specified as 0xRRGGBB integer. + */ + public int getBrushColor() { + return this.brush; + } + + + /** + * Sets the TextBox border object. + * + * @param border the border object. + */ + public void setBorder(int border, boolean visible) { + if (visible) { + this.properties |= border; + } + else { + this.properties &= (~border & 0x00FFFFFF); + } + } + + + /** + * Returns the text box border. + * + * @return boolean the text border object. + */ + public boolean getBorder(int border) { + return (this.properties & border) != 0; + } + + + /** + * Sets all borders to be invisible. + * This cell will have no borders when drawn on the page. + */ + public void setNoBorders() { + this.properties &= 0x00F0FFFF; + } + + + /** + * Sets the cell text alignment. + * + * @param alignment the alignment code. + * Supported values: Align.LEFT, Align.RIGHT and Align.CENTER. + */ + public void setTextAlignment(int alignment) { + this.properties &= 0x00CFFFFF; + this.properties |= (alignment & 0x00300000); + } + + + /** + * Returns the text alignment. + * + * @return alignment the alignment code. Supported values: Align.LEFT, Align.RIGHT and Align.CENTER. + */ + public int getTextAlignment() { + return (this.properties & 0x00300000); + } + + + /** + * Sets the underline variable. + * If the value of the underline variable is 'true' - the text is underlined. + * + * @param underline the underline flag. + */ + public void setUnderline(boolean underline) { + if (underline) { + this.properties |= 0x00400000; + } + else { + this.properties &= 0x00BFFFFF; + } + } + + + /** + * Whether the text will be underlined. + * + * @return whether the text will be underlined + */ + public boolean getUnderline() { + return (properties & 0x00400000) != 0; + } + + + /** + * Sets the srikeout flag. + * In the flag is true - draw strikeout line through the text. + * + * @param strikeout the strikeout flag. + */ + public void setStrikeout(boolean strikeout) { + if (strikeout) { + this.properties |= 0x00800000; + } + else { + this.properties &= 0x007FFFFF; + } + } + + + /** + * Returns the strikeout flag. + * + * @return boolean the strikeout flag. + */ + public boolean getStrikeout() { + return (properties & 0x00800000) != 0; + } + + + public void setFallbackFont(Font font) { + this.fallbackFont = font; + } + + + public Font getFallbackFont() { + return this.fallbackFont; + } + + + /** + * Sets the vertical alignment of the text in this TextBox. + * + * @param alignment - valid values areAlign.TOP, Align.BOTTOM and Align.CENTER + */ + public void setVerticalAlignment(int alignment) { + this.valign = alignment; + } + + + public int getVerticalAlignment() { + return this.valign; + } + + + public void setTextColors(Map colors) { + this.colors = colors; + } + + + public Map getTextColors() { + return this.colors; + } + + + /** + * Draws this text box on the specified page. + * + * @param page the Page where the TextBox is to be drawn. + * @return x and y coordinates of the bottom right corner of this component. + * @throws Exception + */ + public float[] drawOn(Page page) throws Exception { + return drawOn(page, true); + } + + + /** + * Draws this text box on the specified page. + * + * @param page the Page where the TextBox is to be drawn. + * @param draw flag specifying if this component should actually be drawn on the page. + * @return x and y coordinates of the bottom right corner of this component. + * @throws Exception + */ + public float[] drawOn(Page page, boolean draw) throws Exception { + return drawTextAndBorders(page, draw); + } + + + private void drawBackground(Page page) throws Exception { + page.setBrushColor(background); + page.fillRect(x, y, width, height); + } + + + private void drawBorders(Page page) throws Exception { + page.setPenColor(pen); + page.setPenWidth(lineWidth); + + if (getBorder(Border.TOP) && + getBorder(Border.BOTTOM) && + getBorder(Border.LEFT) && + getBorder(Border.RIGHT)) { + page.drawRect(x, y, width, height); + } + else { + if (getBorder(Border.TOP)) { + page.moveTo(x, y); + page.lineTo(x + width, y); + page.strokePath(); + } + if (getBorder(Border.BOTTOM)) { + page.moveTo(x, y + height); + page.lineTo(x + width, y + height); + page.strokePath(); + } + if (getBorder(Border.LEFT)) { + page.moveTo(x, y); + page.lineTo(x, y + height); + page.strokePath(); + } + if (getBorder(Border.RIGHT)) { + page.moveTo(x + width, y); + page.lineTo(x + width, y + height); + page.strokePath(); + } + } + } + + + private float[] drawTextAndBorders(Page page, boolean draw) throws Exception { + + float textAreaWidth = width - (font.stringWidth("w") + 2*margin); + List list = new ArrayList(); + StringBuilder buf = new StringBuilder(); + String[] lines = text.split("\\r?\\n"); + for (int i = 0; i < lines.length; i++) { + String line = lines[i]; + if (font.stringWidth(line) < textAreaWidth) { + list.add(line); + } + else { + String str = null; + buf.setLength(0); + for (int j = 0; j < line.length(); j++) { + buf.append(line.charAt(j)); + str = buf.toString(); + if (font.stringWidth(str) > textAreaWidth) { + if ((str.charAt(str.length() - 1) == ' ') || + str.split("\\s+").length <= 1) { + list.add(str); + } + else { + list.add(str.substring(0, str.lastIndexOf(' '))); + while (line.charAt(j) != ' ') { j -= 1; } + } + buf.setLength(0); + } + } + if (!str.equals("")) { + list.add(str); + } + } + } + lines = list.toArray(new String[] {} ); + + float lineHeight = font.getBodyHeight() + spacing; + float x_text; + float y_text = y + font.ascent + margin; + + if (draw) { + if (getBgColor() != Color.transparent) { + this.height = lines.length * lineHeight; + drawBackground(page); + } + page.setPenColor(this.pen); + page.setBrushColor(this.brush); + page.setPenWidth(this.font.underlineThickness); + } + + if (height > 0f) { + + if (valign == Align.BOTTOM) { + y_text += height - lines.length*lineHeight; + } + else if (valign == Align.CENTER) { + y_text += (height - lines.length*lineHeight)/2; + } + + for (int i = 0; i < lines.length; i++) { + + if (getTextAlignment() == Align.RIGHT) { + x_text = (x + width) - (font.stringWidth(lines[i]) + margin); + } + else if (getTextAlignment() == Align.CENTER) { + x_text = x + (width - font.stringWidth(lines[i]))/2; + } + else { + // Align.LEFT + x_text = x + margin; + } + + if (y_text + font.getBodyHeight() + spacing + font.getDescent() >= y + height + && i < (lines.length - 1)) { + String str = lines[i]; + int index = str.lastIndexOf(' '); + if (index != -1) { + lines[i] = str.substring(0, index) + " ..."; + } + else { + lines[i] = str + " ..."; + } + } + + if (y_text + font.getDescent() < y + height) { + if (draw) { + drawText(page, font, fallbackFont, lines[i], x_text, y_text, colors); + } + y_text += font.getBodyHeight() + spacing; + } + + } + + } + else { + + for (int i = 0; i < lines.length; i++) { + + if (getTextAlignment() == Align.RIGHT) { + x_text = (x + width) - (font.stringWidth(lines[i]) + margin); + } + else if (getTextAlignment() == Align.CENTER) { + x_text = x + (width - font.stringWidth(lines[i]))/2; + } + else { + // Align.LEFT + x_text = x + margin; + } + + if (draw) { + drawText(page, font, fallbackFont, lines[i], x_text, y_text, colors); + } + + y_text += font.getBodyHeight() + spacing; + } + + height = y_text - (y + font.ascent + margin); + } + + if (draw) { + drawBorders(page); + } + + return new float[] {x + width, y + height}; + } + + + private void drawText( + Page page, + Font font, + Font fallbackFont, + String text, + float x_text, + float y_text, + Map colors) throws Exception { + if (fallbackFont == null) { + if (colors == null) { + page.drawString(font, text, x_text, y_text); + } + else { + page.drawString(font, text, x_text, y_text, colors); + } + } + else { + page.drawString(font, fallbackFont, text, x_text, y_text); + } + + float lineLength = font.stringWidth(text); + if (getUnderline()) { + float y_adjust = font.underlinePosition; + page.moveTo(x_text, y_text + y_adjust); + page.lineTo(x_text + lineLength, y_text + y_adjust); + page.strokePath(); + } + if (getStrikeout()) { + float y_adjust = font.body_height/4; + page.moveTo(x_text, y_text - y_adjust); + page.lineTo(x_text + lineLength, y_text - y_adjust); + page.strokePath(); + } + } + +} // End of TextBox.java diff --git a/PDFJet/src/main/java/com/pdfjet/TextFrame.java b/PDFJet/src/main/java/com/pdfjet/TextFrame.java new file mode 100644 index 0000000..f20c031 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/TextFrame.java @@ -0,0 +1,263 @@ +/** + * TextFrame.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + +import java.util.*; + + +/** + * Please see Example_47 + * + */ +public class TextFrame { + + private List paragraphs; + private Font font; + private Font fallbackFont; + private float x; + private float y; + private float w; + private float h; + private float x_text; + private float y_text; + private float leading; + private float paragraphLeading; + private List beginParagraphPoints; + private List endParagraphPoints; + private float spaceBetweenTextLines; + + + public TextFrame(List paragraphs) throws Exception { + if (paragraphs != null) { + this.paragraphs = paragraphs; + this.font = paragraphs.get(0).list.get(0).getFont(); + this.fallbackFont = paragraphs.get(0).list.get(0).getFallbackFont(); + this.leading = font.getBodyHeight(); + this.paragraphLeading = 2*leading; + this.beginParagraphPoints = new ArrayList(); + this.endParagraphPoints = new ArrayList(); + this.spaceBetweenTextLines = font.stringWidth(fallbackFont, Single.space); + } + } + + + public TextFrame setLocation(float x, float y) { + this.x = x; + this.y = y; + return this; + } + + + public TextFrame setWidth(float w) { + this.w = w; + return this; + } + + + public TextFrame setHeight(float h) { + this.h = h; + return this; + } + + + public TextFrame setLeading(float leading) { + this.leading = leading; + return this; + } + + + public TextFrame setParagraphLeading(float paragraphLeading) { + this.paragraphLeading = paragraphLeading; + return this; + } + + + public List getBeginParagraphPoints() { + return this.beginParagraphPoints; + } + + + public List getEndParagraphPoints() { + return this.endParagraphPoints; + } + + + public TextFrame setSpaceBetweenTextLines(float spaceBetweenTextLines) { + this.spaceBetweenTextLines = spaceBetweenTextLines; + return this; + } + + + public List getParagraphs() { + return this.paragraphs; + } + + + public TextFrame drawOn(Page page) throws Exception { + return drawOn(page, true); + } + + + public TextFrame drawOn(Page page, boolean draw) throws Exception { + this.x_text = x; + this.y_text = y + font.getAscent(); + + Paragraph paragraph = null; + for (int i = 0; i < paragraphs.size(); i++) { + paragraph = paragraphs.get(i); + + StringBuilder buf = new StringBuilder(); + for (TextLine textLine : paragraph.list) { + buf.append(textLine.getText()); + buf.append(Single.space); + } + + int numOfTextLines = paragraph.list.size(); + for (int j = 0; j < numOfTextLines; j++) { + TextLine textLine1 = paragraph.list.get(j); + if (j == 0) { + beginParagraphPoints.add(new float[] { x_text, y_text }); + } + textLine1.setAltDescription((j == 0) ? buf.toString() : Single.space); + textLine1.setActualText((j == 0) ? buf.toString() : Single.space); + + TextLine textLine2 = drawTextLine( + page, x_text, y_text, textLine1, draw); + if (!textLine2.getText().equals("")) { + List theRest = new ArrayList(); + Paragraph paragraph2 = new Paragraph(textLine2); + j++; + while (j < numOfTextLines) { + paragraph2.add(paragraph.list.get(j)); + j++; + } + theRest.add(paragraph2); + i++; + while (i < paragraphs.size()) { + theRest.add(paragraphs.get(i)); + i++; + } + return new TextFrame(theRest); + } + + if (j == (numOfTextLines - 1)) { + endParagraphPoints.add(new float[] { textLine2.x, textLine2.y }); + } + x_text = textLine2.x; + if (textLine1.getTrailingSpace()) { + x_text += spaceBetweenTextLines; + } + y_text = textLine2.y; + } + x_text = x; + y_text += paragraphLeading; + } + + TextFrame textFrame = new TextFrame(null); + textFrame.setLocation(x_text, y_text + font.getDescent()); + return textFrame; + } + + + public TextLine drawTextLine( + Page page, + float x_text, + float y_text, + TextLine textLine, + boolean draw) throws Exception { + + TextLine textLine2 = null; + Font font = textLine.getFont(); + Font fallbackFont = textLine.getFallbackFont(); + int color = textLine.getColor(); + + StringBuilder buf = new StringBuilder(); + String[] tokens = textLine.getText().split("\\s+"); + boolean firstTextSegment = true; + for (int i = 0; i < tokens.length; i++) { + String token = (i == 0) ? tokens[i] : (Single.space + tokens[i]); + if (font.stringWidth(fallbackFont, token) < (this.w - (x_text - x))) { + buf.append(token); + x_text += font.stringWidth(fallbackFont, token); + } + else { + if (draw) { + new TextLine(font, buf.toString()) + .setFallbackFont(fallbackFont) + .setLocation(x_text - font.stringWidth(fallbackFont, buf.toString()), + y_text + textLine.getVerticalOffset()) + .setColor(color) + .setUnderline(textLine.getUnderline()) + .setStrikeout(textLine.getStrikeout()) + .setLanguage(textLine.getLanguage()) + .setAltDescription(firstTextSegment ? textLine.getAltDescription() : Single.space) + .setActualText(firstTextSegment ? textLine.getActualText() : Single.space) + .drawOn(page); + firstTextSegment = false; + } + x_text = x + font.stringWidth(fallbackFont, tokens[i]); + y_text += leading; + buf.setLength(0); + buf.append(tokens[i]); + + if (y_text + font.getDescent() > (y + h)) { + i++; + while (i < tokens.length) { + buf.append(Single.space); + buf.append(tokens[i]); + i++; + } + textLine2 = new TextLine(font, buf.toString()); + textLine2.setLocation(x, y_text); + return textLine2; + } + } + } + if (draw) { + new TextLine(font, buf.toString()) + .setFallbackFont(fallbackFont) + .setLocation(x_text - font.stringWidth(fallbackFont, buf.toString()), + y_text + textLine.getVerticalOffset()) + .setColor(color) + .setUnderline(textLine.getUnderline()) + .setStrikeout(textLine.getStrikeout()) + .setLanguage(textLine.getLanguage()) + .setAltDescription(firstTextSegment ? textLine.getAltDescription() : Single.space) + .setActualText(firstTextSegment ? textLine.getActualText() : Single.space) + .drawOn(page); + firstTextSegment = false; + } + + textLine2 = new TextLine(font, ""); + textLine2.setLocation(x_text, y_text); + return textLine2; + } + +} // End of TextFrame.java diff --git a/PDFJet/src/main/java/com/pdfjet/TextLine.java b/PDFJet/src/main/java/com/pdfjet/TextLine.java new file mode 100644 index 0000000..e930839 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/TextLine.java @@ -0,0 +1,690 @@ +/** + * TextLine.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + + +/** + * Used to create text line objects. + * + * + */ +public class TextLine implements Drawable { + + protected float x; + protected float y; + + protected Font font; + protected Font fallbackFont; + protected String str; + protected boolean trailingSpace = true; + + private String uri; + private String key; + + private boolean underline = false; + private boolean strikeout = false; + private String underlineTTS = "underline"; + private String strikeoutTTS = "strikeout"; + + private int degrees = 0; + private int color = Color.black; + + private float box_x; + private float box_y; + + private int textEffect = Effect.NORMAL; + private float verticalOffset = 0f; + + private String language = null; + private String altDescription = null; + private String actualText = null; + + private String uriLanguage = null; + private String uriAltDescription = null; + private String uriActualText = null; + + + /** + * Constructor for creating text line objects. + * + * @param font the font to use. + */ + public TextLine(Font font) { + this.font = font; + } + + + /** + * Constructor for creating text line objects. + * + * @param font the font to use. + * @param text the text. + */ + public TextLine(Font font, String text) { + this.font = font; + this.str = text; + if (this.altDescription == null) { + this.altDescription = text; + } + if (this.actualText == null) { + this.actualText = text; + } + } + + + /** + * Sets the text. + * + * @param text the text. + * @return this TextLine. + */ + public TextLine setText(String text) { + this.str = text; + if (this.altDescription == null) { + this.altDescription = text; + } + if (this.actualText == null) { + this.actualText = text; + } + return this; + } + + + /** + * Returns the text. + * + * @return the text. + */ + public String getText() { + return str; + } + + + /** + * Sets the position where this text line will be drawn on the page. + * + * @param x the x coordinate of the text line. + * @param y the y coordinate of the text line. + * @return this TextLine. + */ + public TextLine setPosition(double x, double y) { + return setLocation((float) x, (float) y); + } + + + /** + * Sets the position where this text line will be drawn on the page. + * + * @param x the x coordinate of the text line. + * @param y the y coordinate of the text line. + * @return this TextLine. + */ + public TextLine setPosition(float x, float y) { + return setLocation(x, y); + } + + + /** + * Sets the location where this text line will be drawn on the page. + * + * @param x the x coordinate of the text line. + * @param y the y coordinate of the text line. + * @return this TextLine. + */ + public TextLine setLocation(float x, float y) { + this.x = x; + this.y = y; + return this; + } + + + /** + * Sets the font to use for this text line. + * + * @param font the font to use. + * @return this TextLine. + */ + public TextLine setFont(Font font) { + this.font = font; + return this; + } + + + /** + * Gets the font to use for this text line. + * + * @return font the font to use. + */ + public Font getFont() { + return font; + } + + + /** + * Sets the font size to use for this text line. + * + * @param fontSize the fontSize to use. + * @return this TextLine. + */ + public TextLine setFontSize(float fontSize) { + this.font.setSize(fontSize); + return this; + } + + + /** + * Sets the fallback font. + * + * @param fallbackFont the fallback font. + * @return this TextLine. + */ + public TextLine setFallbackFont(Font fallbackFont) { + this.fallbackFont = fallbackFont; + return this; + } + + + /** + * Sets the fallback font size to use for this text line. + * + * @param fallbackFontSize the fallback font size. + * @return this TextLine. + */ + public TextLine setFallbackFontSize(float fallbackFontSize) { + this.fallbackFont.setSize(fallbackFontSize); + return this; + } + + + /** + * Returns the fallback font. + * + * @return the fallback font. + */ + public Font getFallbackFont() { + return this.fallbackFont; + } + + + /** + * Sets the color for this text line. + * + * @param color the color is specified as an integer. + * @return this TextLine. + */ + public TextLine setColor(int color) { + this.color = color; + return this; + } + + + /** + * Sets the pen color. + * + * @param color the color. See the Color class for predefined values or define your own using 0x00RRGGBB packed integers. + * @return this TextLine. + */ + public TextLine setColor(int[] color) { + this.color = color[0] << 16 | color[1] << 8 | color[2]; + return this; + } + + + /** + * Returns the text line color. + * + * @return the text line color. + */ + public int getColor() { + return this.color; + } + + + /** + * Returns the y coordinate of the destination. + * + * @return the y coordinate of the destination. + */ + public float getDestinationY() { + return y - font.getSize(); + } + + + /** + * Returns the y coordinate of the destination. + * + * @return the y coordinate of the destination. + */ + public float getY() { + return getDestinationY(); + } + + + /** + * Returns the width of this TextLine. + * + * @return the width. + */ + public float getWidth() { + if (fallbackFont == null) { + return font.stringWidth(str); + } + return font.stringWidth(fallbackFont, str); + } + + + /** + * Returns the height of this TextLine. + * + * @return the height. + */ + public float getHeight() { + return font.getHeight(); + } + + + /** + * Sets the URI for the "click text line" action. + * + * @param uri the URI + * @return this TextLine. + */ + public TextLine setURIAction(String uri) { + this.uri = uri; + return this; + } + + + /** + * Returns the action URI. + * + * @return the action URI. + */ + public String getURIAction() { + return this.uri; + } + + + /** + * Sets the destination key for the action. + * + * @param key the destination name. + * @return this TextLine. + */ + public TextLine setGoToAction(String key) { + this.key = key; + return this; + } + + + /** + * Returns the GoTo action string. + * + * @return the GoTo action string. + */ + public String getGoToAction() { + return this.key; + } + + + /** + * Sets the underline variable. + * If the value of the underline variable is 'true' - the text is underlined. + * + * @param underline the underline flag. + * @return this TextLine. + */ + public TextLine setUnderline(boolean underline) { + this.underline = underline; + return this; + } + + + /** + * Returns the underline flag. + * + * @return the underline flag. + */ + public boolean getUnderline() { + return this.underline; + } + + + /** + * Sets the strike variable. + * If the value of the strike variable is 'true' - a strike line is drawn through the text. + * + * @param strikeout the strikeout flag. + * @return this TextLine. + */ + public TextLine setStrikeout(boolean strikeout) { + this.strikeout = strikeout; + return this; + } + + + /** + * Returns the strikeout flag. + * + * @return the strikeout flag. + */ + public boolean getStrikeout() { + return this.strikeout; + } + + + /** + * Sets the direction in which to draw the text. + * + * @param degrees the number of degrees. + * @return this TextLine. + */ + public TextLine setTextDirection(int degrees) { + this.degrees = degrees; + return this; + } + + + /** + * Returns the text direction. + * + * @return the text direction. + */ + public int getTextDirection() { + return degrees; + } + + + /** + * Sets the text effect. + * + * @param textEffect Effect.NORMAL, Effect.SUBSCRIPT or Effect.SUPERSCRIPT. + * @return this TextLine. + */ + public TextLine setTextEffect(int textEffect) { + this.textEffect = textEffect; + return this; + } + + + /** + * Returns the text effect. + * + * @return the text effect. + */ + public int getTextEffect() { + return textEffect; + } + + + /** + * Sets the vertical offset of the text. + * + * @param verticalOffset the vertical offset. + * @return this TextLine. + */ + public TextLine setVerticalOffset(float verticalOffset) { + this.verticalOffset = verticalOffset; + return this; + } + + + /** + * Returns the vertical text offset. + * + * @return the vertical text offset. + */ + public float getVerticalOffset() { + return verticalOffset; + } + + + /** + * Sets the trailing space after this text line when used in paragraph. + * + * @param trailingSpace the trailing space. + * @return this TextLine. + */ + public TextLine setTrailingSpace(boolean trailingSpace) { + this.trailingSpace = trailingSpace; + return this; + } + + + /** + * Returns the trailing space. + * + * @return the trailing space. + */ + public boolean getTrailingSpace() { + return trailingSpace; + } + + + public TextLine setLanguage(String language) { + this.language = language; + return this; + } + + + public String getLanguage() { + return this.language; + } + + + /** + * Sets the alternate description of this text line. + * + * @param altDescription the alternate description of the text line. + * @return this TextLine. + */ + public TextLine setAltDescription(String altDescription) { + this.altDescription = altDescription; + return this; + } + + + public String getAltDescription() { + return altDescription; + } + + + /** + * Sets the actual text for this text line. + * + * @param actualText the actual text for the text line. + * @return this TextLine. + */ + public TextLine setActualText(String actualText) { + this.actualText = actualText; + return this; + } + + + public String getActualText() { + return actualText; + } + + + public TextLine setURILanguage(String uriLanguage) { + this.uriLanguage = uriLanguage; + return this; + } + + + public TextLine setURIAltDescription(String uriAltDescription) { + this.uriAltDescription = uriAltDescription; + return this; + } + + + public TextLine setURIActualText(String uriActualText) { + this.uriActualText = uriActualText; + return this; + } + + + /** + * Places this text line in the specified box. + * + * @param box the specified box. + * @return this TextLine. + */ + public TextLine placeIn(Box box) throws Exception { + placeIn(box, 0f, 0f); + return this; + } + + + /** + * Places this text line in the box at the specified offset. + * + * @param box the specified box. + * @param x_offset the x offset from the top left corner of the box. + * @param y_offset the y offset from the top left corner of the box. + * @return this TextLine. + */ + public TextLine placeIn( + Box box, + double x_offset, + double y_offset) throws Exception { + return placeIn(box, (float) x_offset, (float) y_offset); + } + + + /** + * Places this text line in the box at the specified offset. + * + * @param box the specified box. + * @param x_offset the x offset from the top left corner of the box. + * @param y_offset the y offset from the top left corner of the box. + * @return this TextLine. + */ + public TextLine placeIn( + Box box, + float x_offset, + float y_offset) throws Exception { + box_x = box.x + x_offset; + box_y = box.y + y_offset; + return this; + } + + + /** + * Draws this text line on the specified page. + * + * @param page the page to draw this text line on. + * @return x and y coordinates of the bottom right corner of this component. + * @throws Exception + */ + public float[] drawOn(Page page) throws Exception { + return drawOn(page, true); + } + + + /** + * Draws this text line on the specified page if the draw parameter is true. + * + * @param page the page to draw this text line on. + * @param draw if draw is false - no action is performed. + */ + protected float[] drawOn(Page page, boolean draw) throws Exception { + if (page == null || !draw || str == null || str.equals("")) { + return new float[] {x, y}; + } + + page.setTextDirection(degrees); + + x += box_x; + y += box_y; + + page.setBrushColor(color); + page.addBMC(StructElem.SPAN, language, altDescription, actualText); + if (fallbackFont == null) { + page.drawString(font, str, x, y); + } + else { + page.drawString(font, fallbackFont, str, x, y); + } + page.addEMC(); + + double radians = Math.PI * degrees / 180.0; + if (underline) { + page.setPenWidth(font.underlineThickness); + page.setPenColor(color); + float lineLength = font.stringWidth(str); + double x_adjust = font.underlinePosition * Math.sin(radians); + double y_adjust = font.underlinePosition * Math.cos(radians); + double x2 = x + lineLength * Math.cos(radians); + double y2 = y - lineLength * Math.sin(radians); + page.addBMC(StructElem.SPAN, language, underlineTTS, underlineTTS); + page.moveTo(x + x_adjust, y + y_adjust); + page.lineTo(x2 + x_adjust, y2 + y_adjust); + page.strokePath(); + page.addEMC(); + } + + if (strikeout) { + page.setPenWidth(font.underlineThickness); + page.setPenColor(color); + float lineLength = font.stringWidth(str); + double x_adjust = ( font.body_height / 4.0 ) * Math.sin(radians); + double y_adjust = ( font.body_height / 4.0 ) * Math.cos(radians); + double x2 = x + lineLength * Math.cos(radians); + double y2 = y - lineLength * Math.sin(radians); + page.addBMC(StructElem.SPAN, language, strikeoutTTS, strikeoutTTS); + page.moveTo(x - x_adjust, y - y_adjust); + page.lineTo(x2 - x_adjust, y2 - y_adjust); + page.strokePath(); + page.addEMC(); + } + + if (uri != null || key != null) { + page.addAnnotation(new Annotation( + uri, + key, // The destination name + x, + page.height - (y - font.ascent), + x + font.stringWidth(str), + page.height - (y - font.descent), + uriLanguage, + uriAltDescription, + uriActualText)); + } + page.setTextDirection(0); + + float len = font.stringWidth(str); + double x_max = Math.max((double) x, x + len*Math.cos(radians)); + double y_max = Math.max((double) y, y - len*Math.sin(radians)); + + return new float[] {(float) x_max, (float) y_max}; + } + +} // End of TextLine.java diff --git a/PDFJet/src/main/java/com/pdfjet/Times_Bold.java b/PDFJet/src/main/java/com/pdfjet/Times_Bold.java new file mode 100644 index 0000000..7bbc744 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Times_Bold.java @@ -0,0 +1,238 @@ +package com.pdfjet; + +class Times_Bold { + protected static final String name = "Times-Bold"; + protected static final int bBoxLLx = -168; + protected static final int bBoxLLy = -218; + protected static final int bBoxURx = 1000; + protected static final int bBoxURy = 935; + protected static final int underlinePosition = -100; + protected static final int underlineThickness = 50; + protected static final String notice = "Copyright (c) 1985, 1987, 1989, 1990, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved. Times is a trademark of Linotype-Hell AG and/or its subsidiaries."; + protected static final int[][] metrics = { + {32,250,65,-55,193,-55,194,-55,196,-55,192,-55,197,-55,195,-55,84,-30,86,-45,87,-30,89,-55,221,-55,159,-55,}, + {33,333,}, + {34,555,}, + {35,500,}, + {36,500,}, + {37,1000,}, + {38,833,}, + {39,278,}, + {40,333,}, + {41,333,}, + {42,500,}, + {43,570,}, + {44,250,148,-45,146,-55,}, + {45,333,}, + {46,250,148,-55,146,-55,}, + {47,278,}, + {48,500,}, + {49,500,}, + {50,500,}, + {51,500,}, + {52,500,}, + {53,500,}, + {54,500,}, + {55,500,}, + {56,500,}, + {57,500,}, + {58,333,}, + {59,333,}, + {60,570,}, + {61,570,}, + {62,570,}, + {63,500,}, + {64,930,}, + {65,722,67,-55,199,-55,71,-55,79,-45,211,-45,212,-45,214,-45,210,-45,216,-45,213,-45,81,-45,84,-95,85,-50,218,-50,219,-50,220,-50,217,-50,86,-145,87,-130,89,-100,221,-100,159,-100,112,-25,146,-74,117,-50,250,-50,251,-50,252,-50,249,-50,118,-100,119,-90,121,-74,253,-74,255,-74,}, + {66,667,65,-30,193,-30,194,-30,196,-30,192,-30,197,-30,195,-30,85,-10,218,-10,219,-10,220,-10,217,-10,}, + {67,722,}, + {68,722,65,-35,193,-35,194,-35,196,-35,192,-35,197,-35,195,-35,86,-40,87,-40,89,-40,221,-40,159,-40,46,-20,}, + {69,667,}, + {70,611,65,-90,193,-90,194,-90,196,-90,192,-90,197,-90,195,-90,97,-25,225,-25,226,-25,228,-25,224,-25,229,-25,227,-25,44,-92,101,-25,233,-25,234,-25,235,-25,232,-25,111,-25,243,-25,244,-25,246,-25,242,-25,248,-25,245,-25,46,-110,}, + {71,778,}, + {72,778,}, + {73,389,}, + {74,500,65,-30,193,-30,194,-30,196,-30,192,-30,197,-30,195,-30,97,-15,225,-15,226,-15,228,-15,224,-15,229,-15,227,-15,101,-15,233,-15,234,-15,235,-15,232,-15,111,-15,243,-15,244,-15,246,-15,242,-15,248,-15,245,-15,46,-20,117,-15,250,-15,251,-15,252,-15,249,-15,}, + {75,778,79,-30,211,-30,212,-30,214,-30,210,-30,216,-30,213,-30,101,-25,233,-25,234,-25,235,-25,232,-25,111,-25,243,-25,244,-25,246,-25,242,-25,248,-25,245,-25,117,-15,250,-15,251,-15,252,-15,249,-15,121,-45,253,-45,255,-45,}, + {76,667,84,-92,86,-92,87,-92,89,-92,221,-92,159,-92,148,-20,146,-110,121,-55,253,-55,255,-55,}, + {77,944,}, + {78,722,65,-20,193,-20,194,-20,196,-20,192,-20,197,-20,195,-20,}, + {79,778,65,-40,193,-40,194,-40,196,-40,192,-40,197,-40,195,-40,84,-40,86,-50,87,-50,88,-40,89,-50,221,-50,159,-50,}, + {80,611,65,-74,193,-74,194,-74,196,-74,192,-74,197,-74,195,-74,97,-10,225,-10,226,-10,228,-10,224,-10,229,-10,227,-10,44,-92,101,-20,233,-20,234,-20,235,-20,232,-20,111,-20,243,-20,244,-20,246,-20,242,-20,248,-20,245,-20,46,-110,}, + {81,778,85,-10,218,-10,219,-10,220,-10,217,-10,46,-20,}, + {82,722,79,-30,211,-30,212,-30,214,-30,210,-30,216,-30,213,-30,84,-40,85,-30,218,-30,219,-30,220,-30,217,-30,86,-55,87,-35,89,-35,221,-35,159,-35,}, + {83,556,}, + {84,667,65,-90,193,-90,194,-90,196,-90,192,-90,197,-90,195,-90,79,-18,211,-18,212,-18,214,-18,210,-18,216,-18,213,-18,97,-92,225,-92,226,-52,228,-52,224,-52,229,-92,227,-52,58,-74,44,-74,101,-92,233,-92,234,-92,235,-52,232,-52,45,-92,105,-18,237,-18,111,-92,243,-92,244,-92,246,-92,242,-92,248,-92,245,-92,46,-90,114,-74,59,-74,117,-92,250,-92,251,-92,252,-92,249,-92,119,-74,121,-34,253,-34,255,-34,}, + {85,722,65,-60,193,-60,194,-60,196,-60,192,-60,197,-60,195,-60,44,-50,46,-50,}, + {86,722,65,-135,193,-135,194,-135,196,-135,192,-135,197,-135,195,-135,71,-30,79,-45,211,-45,212,-45,214,-45,210,-45,216,-45,213,-45,97,-92,225,-92,226,-92,228,-92,224,-92,229,-92,227,-92,58,-92,44,-129,101,-100,233,-100,234,-100,235,-100,232,-100,45,-74,105,-37,237,-37,238,-37,239,-37,236,-37,111,-100,243,-100,244,-100,246,-100,242,-100,248,-100,245,-100,46,-145,59,-92,117,-92,250,-92,251,-92,252,-92,249,-92,}, + {87,1000,65,-120,193,-120,194,-120,196,-120,192,-120,197,-120,195,-120,79,-10,211,-10,212,-10,214,-10,210,-10,216,-10,213,-10,97,-65,225,-65,226,-65,228,-65,224,-65,229,-65,227,-65,58,-55,44,-92,101,-65,233,-65,234,-65,235,-65,232,-65,45,-37,105,-18,237,-18,111,-75,243,-75,244,-75,246,-75,242,-75,248,-75,245,-75,46,-92,59,-55,117,-50,250,-50,251,-50,252,-50,249,-50,121,-60,253,-60,255,-60,}, + {88,722,}, + {89,722,65,-110,193,-110,194,-110,196,-110,192,-110,197,-110,195,-110,79,-35,211,-35,212,-35,214,-35,210,-35,216,-35,213,-35,97,-85,225,-85,226,-85,228,-85,224,-85,229,-85,227,-85,58,-92,44,-92,101,-111,233,-111,234,-111,235,-71,232,-71,45,-92,105,-37,237,-37,111,-111,243,-111,244,-111,246,-111,242,-111,248,-111,245,-111,46,-92,59,-92,117,-92,250,-92,251,-92,252,-92,249,-92,}, + {90,667,}, + {91,333,}, + {92,278,}, + {93,333,}, + {94,581,}, + {95,500,}, + {96,333,}, + {97,500,118,-25,}, + {98,556,98,-10,46,-40,117,-20,250,-20,251,-20,252,-20,249,-20,118,-15,}, + {99,444,}, + {100,556,119,-15,}, + {101,444,118,-15,}, + {102,333,44,-15,105,-25,111,-25,243,-25,244,-25,246,-25,242,-25,248,-25,245,-25,46,-15,148,50,146,55,}, + {103,500,46,-15,}, + {104,556,121,-15,253,-15,255,-15,}, + {105,278,118,-10,}, + {106,333,}, + {107,556,101,-10,233,-10,234,-10,235,-10,232,-10,111,-15,243,-15,244,-15,246,-15,242,-15,248,-15,245,-15,121,-15,253,-15,255,-15,}, + {108,278,}, + {109,833,}, + {110,556,118,-40,}, + {111,500,118,-10,119,-10,}, + {112,556,}, + {113,556,}, + {114,444,99,-18,231,-18,44,-92,101,-18,233,-18,234,-18,235,-18,232,-18,103,-10,45,-37,110,-15,241,-15,111,-18,243,-18,244,-18,246,-18,242,-18,248,-18,245,-18,112,-10,46,-100,113,-18,118,-10,}, + {115,389,}, + {116,333,}, + {117,556,}, + {118,500,97,-10,225,-10,226,-10,228,-10,224,-10,229,-10,227,-10,44,-55,101,-10,233,-10,234,-10,235,-10,232,-10,111,-10,243,-10,244,-10,246,-10,242,-10,248,-10,245,-10,46,-70,}, + {119,722,44,-55,111,-10,243,-10,244,-10,246,-10,242,-10,248,-10,245,-10,46,-70,}, + {120,500,}, + {121,500,44,-55,101,-10,233,-10,234,-10,235,-10,232,-10,111,-25,243,-25,244,-25,246,-25,242,-25,248,-25,245,-25,46,-70,}, + {122,444,}, + {123,394,}, + {124,220,}, + {125,394,}, + {126,520,}, + {127,250,}, + {128,500,}, + {129,250,}, + {130,333,}, + {131,500,}, + {132,500,}, + {133,1000,}, + {134,500,}, + {135,500,}, + {136,333,}, + {137,1000,}, + {138,556,}, + {139,333,}, + {140,1000,}, + {141,250,}, + {142,667,}, + {143,250,}, + {144,250,}, + {145,333,65,-10,193,-10,194,-10,196,-10,192,-10,197,-10,195,-10,145,-63,}, + {146,333,100,-20,146,-63,114,-20,115,-37,154,-37,32,-74,118,-20,}, + {147,500,65,-10,193,-10,194,-10,196,-10,192,-10,197,-10,195,-10,}, + {148,500,}, + {149,350,}, + {150,500,}, + {151,1000,}, + {152,333,}, + {153,1000,}, + {154,389,}, + {155,333,}, + {156,722,}, + {157,250,}, + {158,444,}, + {159,722,65,-110,193,-110,194,-110,196,-110,192,-110,197,-110,195,-110,79,-35,211,-35,212,-35,214,-35,210,-35,216,-35,213,-35,97,-85,225,-85,226,-85,228,-85,224,-85,229,-85,227,-85,58,-92,44,-92,101,-111,233,-111,234,-111,235,-71,232,-71,45,-92,105,-37,237,-37,111,-111,243,-111,244,-111,246,-111,242,-111,248,-111,245,-111,46,-92,59,-92,117,-92,250,-92,251,-92,252,-92,249,-92,}, + {160,250,}, + {161,333,}, + {162,500,}, + {163,500,}, + {164,500,}, + {165,500,}, + {166,220,}, + {167,500,}, + {168,333,}, + {169,747,}, + {170,300,}, + {171,500,}, + {172,570,}, + {173,250,}, + {174,747,}, + {175,333,}, + {176,400,}, + {177,570,}, + {178,300,}, + {179,300,}, + {180,333,}, + {181,556,}, + {182,540,}, + {183,250,}, + {184,333,}, + {185,300,}, + {186,330,}, + {187,500,}, + {188,750,}, + {189,750,}, + {190,750,}, + {191,500,}, + {192,722,67,-55,199,-55,71,-55,79,-45,211,-45,212,-45,214,-45,210,-45,216,-45,213,-45,81,-45,84,-95,85,-50,218,-50,219,-50,220,-50,217,-50,86,-145,87,-130,89,-100,221,-100,159,-100,112,-25,146,-74,117,-50,250,-50,251,-50,252,-50,249,-50,118,-100,119,-90,121,-74,253,-74,255,-74,}, + {193,722,67,-55,199,-55,71,-55,79,-45,211,-45,212,-45,214,-45,210,-45,216,-45,213,-45,81,-45,84,-95,85,-50,218,-50,219,-50,220,-50,217,-50,86,-145,87,-130,89,-100,221,-100,159,-100,112,-25,146,-74,117,-50,250,-50,251,-50,252,-50,249,-50,118,-100,119,-90,121,-74,253,-74,255,-74,}, + {194,722,67,-55,199,-55,71,-55,79,-45,211,-45,212,-45,214,-45,210,-45,216,-45,213,-45,81,-45,84,-95,85,-50,218,-50,219,-50,220,-50,217,-50,86,-145,87,-130,89,-100,221,-100,159,-100,112,-25,146,-74,117,-50,250,-50,251,-50,252,-50,249,-50,118,-100,119,-90,121,-74,253,-74,255,-74,}, + {195,722,67,-55,199,-55,71,-55,79,-45,211,-45,212,-45,214,-45,210,-45,216,-45,213,-45,81,-45,84,-95,85,-50,218,-50,219,-50,220,-50,217,-50,86,-145,87,-130,89,-100,221,-100,159,-100,112,-25,146,-74,117,-50,250,-50,251,-50,252,-50,249,-50,118,-100,119,-90,121,-74,253,-74,255,-74,}, + {196,722,67,-55,199,-55,71,-55,79,-45,211,-45,212,-45,214,-45,210,-45,216,-45,213,-45,81,-45,84,-95,85,-50,218,-50,219,-50,220,-50,217,-50,86,-145,87,-130,89,-100,221,-100,159,-100,112,-25,146,-74,117,-50,250,-50,251,-50,252,-50,249,-50,118,-100,119,-90,121,-74,253,-74,255,-74,}, + {197,722,67,-55,199,-55,71,-55,79,-45,211,-45,212,-45,214,-45,210,-45,216,-45,213,-45,81,-45,84,-95,85,-50,218,-50,219,-50,220,-50,217,-50,86,-145,87,-130,89,-100,221,-100,159,-100,112,-25,146,-74,117,-50,250,-50,251,-50,252,-50,249,-50,118,-100,119,-90,121,-74,253,-74,255,-74,}, + {198,1000,}, + {199,722,}, + {200,667,}, + {201,667,}, + {202,667,}, + {203,667,}, + {204,389,}, + {205,389,}, + {206,389,}, + {207,389,}, + {208,722,}, + {209,722,65,-20,193,-20,194,-20,196,-20,192,-20,197,-20,195,-20,}, + {210,778,65,-40,193,-40,194,-40,196,-40,192,-40,197,-40,195,-40,84,-40,86,-50,87,-50,88,-40,89,-50,221,-50,159,-50,}, + {211,778,65,-40,193,-40,194,-40,196,-40,192,-40,197,-40,195,-40,84,-40,86,-50,87,-50,88,-40,89,-50,221,-50,159,-50,}, + {212,778,65,-40,193,-40,194,-40,196,-40,192,-40,197,-40,195,-40,84,-40,86,-50,87,-50,88,-40,89,-50,221,-50,159,-50,}, + {213,778,65,-40,193,-40,194,-40,196,-40,192,-40,197,-40,195,-40,84,-40,86,-50,87,-50,88,-40,89,-50,221,-50,159,-50,}, + {214,778,65,-40,193,-40,194,-40,196,-40,192,-40,197,-40,195,-40,84,-40,86,-50,87,-50,88,-40,89,-50,221,-50,159,-50,}, + {215,570,}, + {216,778,65,-40,193,-40,194,-40,196,-40,192,-40,197,-40,195,-40,84,-40,86,-50,87,-50,88,-40,89,-50,221,-50,159,-50,}, + {217,722,65,-60,193,-60,194,-60,196,-60,192,-60,197,-60,195,-60,44,-50,46,-50,}, + {218,722,65,-60,193,-60,194,-60,196,-60,192,-60,197,-60,195,-60,44,-50,46,-50,}, + {219,722,65,-60,193,-60,194,-60,196,-60,192,-60,197,-60,195,-60,44,-50,46,-50,}, + {220,722,65,-60,193,-60,194,-60,196,-60,192,-60,197,-60,195,-60,44,-50,46,-50,}, + {221,722,65,-110,193,-110,194,-110,196,-110,192,-110,197,-110,195,-110,79,-35,211,-35,212,-35,214,-35,210,-35,216,-35,213,-35,97,-85,225,-85,226,-85,228,-85,224,-85,229,-85,227,-85,58,-92,44,-92,101,-111,233,-111,234,-111,235,-71,232,-71,45,-92,105,-37,237,-37,111,-111,243,-111,244,-111,246,-111,242,-111,248,-111,245,-111,46,-92,59,-92,117,-92,250,-92,251,-92,252,-92,249,-92,}, + {222,611,}, + {223,556,}, + {224,500,118,-25,}, + {225,500,118,-25,}, + {226,500,118,-25,}, + {227,500,118,-25,}, + {228,500,118,-25,}, + {229,500,118,-25,}, + {230,722,}, + {231,444,}, + {232,444,118,-15,}, + {233,444,118,-15,}, + {234,444,118,-15,}, + {235,444,118,-15,}, + {236,278,118,-10,}, + {237,278,118,-10,}, + {238,278,118,-10,}, + {239,278,118,-10,}, + {240,500,}, + {241,556,118,-40,}, + {242,500,118,-10,119,-10,}, + {243,500,118,-10,119,-10,}, + {244,500,118,-10,119,-10,}, + {245,500,118,-10,119,-10,}, + {246,500,118,-10,119,-10,}, + {247,570,}, + {248,500,118,-10,119,-10,}, + {249,556,}, + {250,556,}, + {251,556,}, + {252,556,}, + {253,500,44,-55,101,-10,233,-10,234,-10,235,-10,232,-10,111,-25,243,-25,244,-25,246,-25,242,-25,248,-25,245,-25,46,-70,}, + {254,556,}, + {255,500,44,-55,101,-10,233,-10,234,-10,235,-10,232,-10,111,-25,243,-25,244,-25,246,-25,242,-25,248,-25,245,-25,46,-70,}, + }; +} diff --git a/PDFJet/src/main/java/com/pdfjet/Times_BoldItalic.java b/PDFJet/src/main/java/com/pdfjet/Times_BoldItalic.java new file mode 100644 index 0000000..308bcb9 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Times_BoldItalic.java @@ -0,0 +1,238 @@ +package com.pdfjet; + +class Times_BoldItalic { + protected static final String name = "Times-BoldItalic"; + protected static final int bBoxLLx = -200; + protected static final int bBoxLLy = -218; + protected static final int bBoxURx = 996; + protected static final int bBoxURy = 921; + protected static final int underlinePosition = -100; + protected static final int underlineThickness = 50; + protected static final String notice = "Copyright (c) 1985, 1987, 1989, 1990, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved. Times is a trademark of Linotype-Hell AG and/or its subsidiaries."; + protected static final int[][] metrics = { + {32,250,65,-37,193,-37,194,-37,196,-37,192,-37,197,-37,195,-37,86,-70,87,-70,89,-70,221,-70,159,-70,}, + {33,389,}, + {34,555,}, + {35,500,}, + {36,500,}, + {37,833,}, + {38,778,}, + {39,278,}, + {40,333,}, + {41,333,}, + {42,500,}, + {43,570,}, + {44,250,148,-95,146,-95,}, + {45,333,}, + {46,250,148,-95,146,-95,}, + {47,278,}, + {48,500,}, + {49,500,}, + {50,500,}, + {51,500,}, + {52,500,}, + {53,500,}, + {54,500,}, + {55,500,}, + {56,500,}, + {57,500,}, + {58,333,}, + {59,333,}, + {60,570,}, + {61,570,}, + {62,570,}, + {63,500,}, + {64,832,}, + {65,667,67,-65,199,-65,71,-60,79,-50,211,-50,212,-50,214,-50,210,-50,216,-50,213,-50,81,-55,84,-55,85,-50,218,-50,219,-50,220,-50,217,-50,86,-95,87,-100,89,-70,221,-70,159,-70,146,-74,117,-30,250,-30,251,-30,252,-30,249,-30,118,-74,119,-74,121,-74,253,-74,255,-74,}, + {66,667,65,-25,193,-25,194,-25,196,-25,192,-25,197,-25,195,-25,85,-10,218,-10,219,-10,220,-10,217,-10,}, + {67,667,}, + {68,722,65,-25,193,-25,194,-25,196,-25,192,-25,197,-25,195,-25,86,-50,87,-40,89,-50,221,-50,159,-50,}, + {69,667,}, + {70,667,65,-100,193,-100,194,-100,196,-100,192,-100,197,-100,195,-100,97,-95,225,-95,226,-95,228,-95,224,-95,229,-95,227,-95,44,-129,101,-100,233,-100,234,-100,235,-100,232,-100,105,-40,237,-40,238,-40,239,-40,236,-40,111,-70,243,-70,244,-70,246,-70,242,-70,248,-70,245,-70,46,-129,114,-50,}, + {71,722,}, + {72,778,}, + {73,389,}, + {74,500,65,-25,193,-25,194,-25,196,-25,192,-25,197,-25,195,-25,97,-40,225,-40,226,-40,228,-40,224,-40,229,-40,227,-40,44,-10,101,-40,233,-40,234,-40,235,-40,232,-40,111,-40,243,-40,244,-40,246,-40,242,-40,248,-40,245,-40,46,-10,117,-40,250,-40,251,-40,252,-40,249,-40,}, + {75,667,79,-30,211,-30,212,-30,214,-30,210,-30,216,-30,213,-30,101,-25,233,-25,234,-25,235,-25,232,-25,111,-25,243,-25,244,-25,246,-25,242,-25,248,-25,245,-25,117,-20,250,-20,251,-20,252,-20,249,-20,121,-20,253,-20,255,-20,}, + {76,611,84,-18,86,-37,87,-37,89,-37,221,-37,159,-37,146,-55,121,-37,253,-37,255,-37,}, + {77,889,}, + {78,722,65,-30,193,-30,194,-30,196,-30,192,-30,197,-30,195,-30,}, + {79,722,65,-40,193,-40,194,-40,196,-40,192,-40,197,-40,195,-40,84,-40,86,-50,87,-50,88,-40,89,-50,221,-50,159,-50,}, + {80,611,65,-85,193,-85,194,-85,196,-85,192,-85,197,-85,195,-85,97,-40,225,-40,226,-40,228,-40,224,-40,229,-40,227,-40,44,-129,101,-50,233,-50,234,-50,235,-50,232,-50,111,-55,243,-55,244,-55,246,-55,242,-55,248,-55,245,-55,46,-129,}, + {81,722,85,-10,218,-10,219,-10,220,-10,217,-10,}, + {82,667,79,-40,211,-40,212,-40,214,-40,210,-40,216,-40,213,-40,84,-30,85,-40,218,-40,219,-40,220,-40,217,-40,86,-18,87,-18,89,-18,221,-18,159,-18,}, + {83,556,}, + {84,611,65,-55,193,-55,194,-55,196,-55,192,-55,197,-55,195,-55,79,-18,211,-18,212,-18,214,-18,210,-18,216,-18,213,-18,97,-92,225,-92,226,-92,228,-92,224,-92,229,-92,227,-92,58,-74,44,-92,101,-92,233,-92,234,-92,235,-52,232,-52,45,-92,105,-37,237,-37,111,-95,243,-95,244,-95,246,-95,242,-95,248,-95,245,-95,46,-92,114,-37,59,-74,117,-37,250,-37,251,-37,252,-37,249,-37,119,-37,121,-37,253,-37,255,-37,}, + {85,722,65,-45,193,-45,194,-45,196,-45,192,-45,197,-45,195,-45,}, + {86,667,65,-85,193,-85,194,-85,196,-85,192,-85,197,-85,195,-85,71,-10,79,-30,211,-30,212,-30,214,-30,210,-30,216,-30,213,-30,97,-111,225,-111,226,-111,228,-111,224,-111,229,-111,227,-111,58,-74,44,-129,101,-111,233,-111,234,-111,235,-71,232,-71,45,-70,105,-55,237,-55,111,-111,243,-111,244,-111,246,-111,242,-111,248,-111,245,-111,46,-129,59,-74,117,-55,250,-55,251,-55,252,-55,249,-55,}, + {87,889,65,-74,193,-74,194,-74,196,-74,192,-74,197,-74,195,-74,79,-15,211,-15,212,-15,214,-15,210,-15,216,-15,213,-15,97,-85,225,-85,226,-85,228,-85,224,-85,229,-85,227,-85,58,-55,44,-74,101,-90,233,-90,234,-90,235,-50,232,-50,45,-50,105,-37,237,-37,111,-80,243,-80,244,-80,246,-80,242,-80,248,-80,245,-80,46,-74,59,-55,117,-55,250,-55,251,-55,252,-55,249,-55,121,-55,253,-55,255,-55,}, + {88,667,}, + {89,611,65,-74,193,-74,194,-74,196,-74,192,-74,197,-74,195,-74,79,-25,211,-25,212,-25,214,-25,210,-25,216,-25,213,-25,97,-92,225,-92,226,-92,228,-92,224,-92,229,-92,227,-92,58,-92,44,-92,101,-111,233,-111,234,-71,235,-71,232,-71,45,-92,105,-55,237,-55,111,-111,243,-111,244,-111,246,-111,242,-111,248,-111,245,-111,46,-74,59,-92,117,-92,250,-92,251,-92,252,-92,249,-92,}, + {90,611,}, + {91,333,}, + {92,278,}, + {93,333,}, + {94,570,}, + {95,500,}, + {96,333,}, + {97,500,}, + {98,500,98,-10,46,-40,117,-20,250,-20,251,-20,252,-20,249,-20,}, + {99,444,104,-10,107,-10,}, + {100,500,}, + {101,444,98,-10,}, + {102,333,44,-10,101,-10,233,-10,102,-18,111,-10,243,-10,244,-10,242,-10,248,-10,245,-10,46,-10,146,55,}, + {103,500,}, + {104,556,}, + {105,278,}, + {106,278,}, + {107,500,101,-30,233,-30,234,-30,235,-30,232,-30,111,-10,243,-10,244,-10,246,-10,242,-10,248,-10,245,-10,}, + {108,278,}, + {109,778,}, + {110,556,118,-40,}, + {111,500,118,-15,119,-25,120,-10,121,-10,253,-10,255,-10,}, + {112,500,}, + {113,500,}, + {114,389,44,-65,46,-65,}, + {115,389,}, + {116,278,}, + {117,556,}, + {118,444,44,-37,101,-15,233,-15,234,-15,235,-15,232,-15,111,-15,243,-15,244,-15,246,-15,242,-15,248,-15,245,-15,46,-37,}, + {119,667,97,-10,225,-10,226,-10,228,-10,224,-10,229,-10,227,-10,44,-37,101,-10,233,-10,234,-10,235,-10,232,-10,111,-15,243,-15,244,-15,246,-15,242,-15,248,-15,245,-15,46,-37,}, + {120,500,101,-10,233,-10,234,-10,235,-10,232,-10,}, + {121,444,44,-37,46,-37,}, + {122,389,}, + {123,348,}, + {124,220,}, + {125,348,}, + {126,570,}, + {127,250,}, + {128,500,}, + {129,250,}, + {130,333,}, + {131,500,}, + {132,500,}, + {133,1000,}, + {134,500,}, + {135,500,}, + {136,333,}, + {137,1000,}, + {138,556,}, + {139,333,}, + {140,944,}, + {141,250,}, + {142,611,}, + {143,250,}, + {144,250,}, + {145,333,145,-74,}, + {146,333,100,-15,146,-74,114,-15,115,-74,154,-74,32,-74,116,-37,118,-15,}, + {147,500,}, + {148,500,}, + {149,350,}, + {150,500,}, + {151,1000,}, + {152,333,}, + {153,1000,}, + {154,389,}, + {155,333,}, + {156,722,}, + {157,250,}, + {158,389,}, + {159,611,65,-74,193,-74,194,-74,196,-74,192,-74,197,-74,195,-74,79,-25,211,-25,212,-25,214,-25,210,-25,216,-25,213,-25,97,-92,225,-92,226,-92,228,-92,224,-92,229,-92,227,-92,58,-92,44,-92,101,-111,233,-111,234,-71,235,-71,232,-71,45,-92,105,-55,237,-55,111,-111,243,-111,244,-111,246,-111,242,-111,248,-111,245,-111,46,-74,59,-92,117,-92,250,-92,251,-92,252,-92,249,-92,}, + {160,250,}, + {161,389,}, + {162,500,}, + {163,500,}, + {164,500,}, + {165,500,}, + {166,220,}, + {167,500,}, + {168,333,}, + {169,747,}, + {170,266,}, + {171,500,}, + {172,606,}, + {173,250,}, + {174,747,}, + {175,333,}, + {176,400,}, + {177,570,}, + {178,300,}, + {179,300,}, + {180,333,}, + {181,576,}, + {182,500,}, + {183,250,}, + {184,333,}, + {185,300,}, + {186,300,}, + {187,500,}, + {188,750,}, + {189,750,}, + {190,750,}, + {191,500,}, + {192,667,67,-65,199,-65,71,-60,79,-50,211,-50,212,-50,214,-50,210,-50,216,-50,213,-50,81,-55,84,-55,85,-50,218,-50,219,-50,220,-50,217,-50,86,-95,87,-100,89,-70,221,-70,159,-70,146,-74,117,-30,250,-30,251,-30,252,-30,249,-30,118,-74,119,-74,121,-74,253,-74,255,-74,}, + {193,667,67,-65,199,-65,71,-60,79,-50,211,-50,212,-50,214,-50,210,-50,216,-50,213,-50,81,-55,84,-55,85,-50,218,-50,219,-50,220,-50,217,-50,86,-95,87,-100,89,-70,221,-70,159,-70,146,-74,117,-30,250,-30,251,-30,252,-30,249,-30,118,-74,119,-74,121,-74,253,-74,255,-74,}, + {194,667,67,-65,199,-65,71,-60,79,-50,211,-50,212,-50,214,-50,210,-50,216,-50,213,-50,81,-55,84,-55,85,-50,218,-50,219,-50,220,-50,217,-50,86,-95,87,-100,89,-70,221,-70,159,-70,146,-74,117,-30,250,-30,251,-30,252,-30,249,-30,118,-74,119,-74,121,-74,253,-74,255,-74,}, + {195,667,67,-65,199,-65,71,-60,79,-50,211,-50,212,-50,214,-50,210,-50,216,-50,213,-50,81,-55,84,-55,85,-50,218,-50,219,-50,220,-50,217,-50,86,-95,87,-100,89,-70,221,-70,159,-70,146,-74,117,-30,250,-30,251,-30,252,-30,249,-30,118,-74,119,-74,121,-74,253,-74,255,-74,}, + {196,667,67,-65,199,-65,71,-60,79,-50,211,-50,212,-50,214,-50,210,-50,216,-50,213,-50,81,-55,84,-55,85,-50,218,-50,219,-50,220,-50,217,-50,86,-95,87,-100,89,-70,221,-70,159,-70,146,-74,117,-30,250,-30,251,-30,252,-30,249,-30,118,-74,119,-74,121,-74,253,-74,255,-74,}, + {197,667,67,-65,199,-65,71,-60,79,-50,211,-50,212,-50,214,-50,210,-50,216,-50,213,-50,81,-55,84,-55,85,-50,218,-50,219,-50,220,-50,217,-50,86,-95,87,-100,89,-70,221,-70,159,-70,146,-74,117,-30,250,-30,251,-30,252,-30,249,-30,118,-74,119,-74,121,-74,253,-74,255,-74,}, + {198,944,}, + {199,667,}, + {200,667,}, + {201,667,}, + {202,667,}, + {203,667,}, + {204,389,}, + {205,389,}, + {206,389,}, + {207,389,}, + {208,722,}, + {209,722,65,-30,193,-30,194,-30,196,-30,192,-30,197,-30,195,-30,}, + {210,722,65,-40,193,-40,194,-40,196,-40,192,-40,197,-40,195,-40,84,-40,86,-50,87,-50,88,-40,89,-50,221,-50,159,-50,}, + {211,722,65,-40,193,-40,194,-40,196,-40,192,-40,197,-40,195,-40,84,-40,86,-50,87,-50,88,-40,89,-50,221,-50,159,-50,}, + {212,722,65,-40,193,-40,194,-40,196,-40,192,-40,197,-40,195,-40,84,-40,86,-50,87,-50,88,-40,89,-50,221,-50,159,-50,}, + {213,722,65,-40,193,-40,194,-40,196,-40,192,-40,197,-40,195,-40,84,-40,86,-50,87,-50,88,-40,89,-50,221,-50,159,-50,}, + {214,722,65,-40,193,-40,194,-40,196,-40,192,-40,197,-40,195,-40,84,-40,86,-50,87,-50,88,-40,89,-50,221,-50,159,-50,}, + {215,570,}, + {216,722,65,-40,193,-40,194,-40,196,-40,192,-40,197,-40,195,-40,84,-40,86,-50,87,-50,88,-40,89,-50,221,-50,159,-50,}, + {217,722,65,-45,193,-45,194,-45,196,-45,192,-45,197,-45,195,-45,}, + {218,722,65,-45,193,-45,194,-45,196,-45,192,-45,197,-45,195,-45,}, + {219,722,65,-45,193,-45,194,-45,196,-45,192,-45,197,-45,195,-45,}, + {220,722,65,-45,193,-45,194,-45,196,-45,192,-45,197,-45,195,-45,}, + {221,611,65,-74,193,-74,194,-74,196,-74,192,-74,197,-74,195,-74,79,-25,211,-25,212,-25,214,-25,210,-25,216,-25,213,-25,97,-92,225,-92,226,-92,228,-92,224,-92,229,-92,227,-92,58,-92,44,-92,101,-111,233,-111,234,-71,235,-71,232,-71,45,-92,105,-55,237,-55,111,-111,243,-111,244,-111,246,-111,242,-111,248,-111,245,-111,46,-74,59,-92,117,-92,250,-92,251,-92,252,-92,249,-92,}, + {222,611,}, + {223,500,}, + {224,500,}, + {225,500,}, + {226,500,}, + {227,500,}, + {228,500,}, + {229,500,}, + {230,722,}, + {231,444,104,-10,107,-10,}, + {232,444,98,-10,}, + {233,444,98,-10,}, + {234,444,98,-10,}, + {235,444,98,-10,}, + {236,278,}, + {237,278,}, + {238,278,}, + {239,278,}, + {240,500,}, + {241,556,118,-40,}, + {242,500,118,-15,119,-25,120,-10,121,-10,253,-10,255,-10,}, + {243,500,118,-15,119,-25,120,-10,121,-10,253,-10,255,-10,}, + {244,500,118,-15,119,-25,120,-10,121,-10,253,-10,255,-10,}, + {245,500,118,-15,119,-25,120,-10,121,-10,253,-10,255,-10,}, + {246,500,118,-15,119,-25,120,-10,121,-10,253,-10,255,-10,}, + {247,570,}, + {248,500,118,-15,119,-25,120,-10,121,-10,253,-10,255,-10,}, + {249,556,}, + {250,556,}, + {251,556,}, + {252,556,}, + {253,444,44,-37,46,-37,}, + {254,500,}, + {255,444,44,-37,46,-37,}, + }; +} diff --git a/PDFJet/src/main/java/com/pdfjet/Times_Italic.java b/PDFJet/src/main/java/com/pdfjet/Times_Italic.java new file mode 100644 index 0000000..f65d4de --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Times_Italic.java @@ -0,0 +1,238 @@ +package com.pdfjet; + +class Times_Italic { + protected static final String name = "Times-Italic"; + protected static final int bBoxLLx = -169; + protected static final int bBoxLLy = -217; + protected static final int bBoxURx = 1010; + protected static final int bBoxURy = 883; + protected static final int underlinePosition = -100; + protected static final int underlineThickness = 50; + protected static final String notice = "Copyright (c) 1985, 1987, 1989, 1990, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved. Times is a trademark of Linotype-Hell AG and/or its subsidiaries."; + protected static final int[][] metrics = { + {32,250,65,-18,193,-18,194,-18,196,-18,192,-18,197,-18,195,-18,84,-18,86,-35,87,-40,89,-75,221,-75,159,-75,}, + {33,333,}, + {34,420,}, + {35,500,}, + {36,500,}, + {37,833,}, + {38,778,}, + {39,214,}, + {40,333,}, + {41,333,}, + {42,500,}, + {43,675,}, + {44,250,148,-140,146,-140,}, + {45,333,}, + {46,250,148,-140,146,-140,}, + {47,278,}, + {48,500,}, + {49,500,}, + {50,500,}, + {51,500,}, + {52,500,}, + {53,500,}, + {54,500,}, + {55,500,}, + {56,500,}, + {57,500,}, + {58,333,}, + {59,333,}, + {60,675,}, + {61,675,}, + {62,675,}, + {63,500,}, + {64,920,}, + {65,611,67,-30,199,-30,71,-35,79,-40,211,-40,212,-40,214,-40,210,-40,216,-40,213,-40,81,-40,84,-37,85,-50,218,-50,219,-50,220,-50,217,-50,86,-105,87,-95,89,-55,221,-55,159,-55,146,-37,117,-20,250,-20,251,-20,252,-20,249,-20,118,-55,119,-55,121,-55,253,-55,255,-55,}, + {66,611,65,-25,193,-25,194,-25,196,-25,192,-25,197,-25,195,-25,85,-10,218,-10,219,-10,220,-10,217,-10,}, + {67,667,}, + {68,722,65,-35,193,-35,194,-35,196,-35,192,-35,197,-35,195,-35,86,-40,87,-40,89,-40,221,-40,159,-40,}, + {69,611,}, + {70,611,65,-115,193,-115,194,-115,196,-115,192,-115,197,-115,195,-115,97,-75,225,-75,226,-75,228,-75,224,-75,229,-75,227,-75,44,-135,101,-75,233,-75,234,-75,235,-75,232,-75,105,-45,237,-45,238,-45,239,-45,236,-45,111,-105,243,-105,244,-105,246,-105,242,-105,248,-105,245,-105,46,-135,114,-55,}, + {71,722,}, + {72,722,}, + {73,333,}, + {74,444,65,-40,193,-40,194,-40,196,-40,192,-40,197,-40,195,-40,97,-35,225,-35,226,-35,228,-35,224,-35,229,-35,227,-35,44,-25,101,-25,233,-25,234,-25,235,-25,232,-25,111,-25,243,-25,244,-25,246,-25,242,-25,248,-25,245,-25,46,-25,117,-35,250,-35,251,-35,252,-35,249,-35,}, + {75,667,79,-50,211,-50,212,-50,214,-50,210,-50,216,-50,213,-50,101,-35,233,-35,234,-35,235,-35,232,-35,111,-40,243,-40,244,-40,246,-40,242,-40,248,-40,245,-40,117,-40,250,-40,251,-40,252,-40,249,-40,121,-40,253,-40,255,-40,}, + {76,556,84,-20,86,-55,87,-55,89,-20,221,-20,159,-20,146,-37,121,-30,253,-30,255,-30,}, + {77,833,}, + {78,667,65,-27,193,-27,194,-27,196,-27,192,-27,197,-27,195,-27,}, + {79,722,65,-55,193,-55,194,-55,196,-55,192,-55,197,-55,195,-55,84,-40,86,-50,87,-50,88,-40,89,-50,221,-50,159,-50,}, + {80,611,65,-90,193,-90,194,-90,196,-90,192,-90,197,-90,195,-90,97,-80,225,-80,226,-80,228,-80,224,-80,229,-80,227,-80,44,-135,101,-80,233,-80,234,-80,235,-80,232,-80,111,-80,243,-80,244,-80,246,-80,242,-80,248,-80,245,-80,46,-135,}, + {81,722,85,-10,218,-10,219,-10,220,-10,217,-10,}, + {82,611,79,-40,211,-40,212,-40,214,-40,210,-40,216,-40,213,-40,85,-40,218,-40,219,-40,220,-40,217,-40,86,-18,87,-18,89,-18,221,-18,159,-18,}, + {83,500,}, + {84,556,65,-50,193,-50,194,-50,196,-50,192,-50,197,-50,195,-50,79,-18,211,-18,212,-18,214,-18,210,-18,216,-18,213,-18,97,-92,225,-92,226,-92,228,-92,224,-92,229,-92,227,-92,58,-55,44,-74,101,-92,233,-92,234,-52,235,-52,232,-52,45,-74,105,-55,237,-55,111,-92,243,-92,244,-92,246,-92,242,-92,248,-92,245,-92,46,-74,114,-55,59,-65,117,-55,250,-55,251,-55,252,-55,249,-55,119,-74,121,-74,253,-74,255,-34,}, + {85,722,65,-40,193,-40,194,-40,196,-40,192,-40,197,-40,195,-40,44,-25,46,-25,}, + {86,611,65,-60,193,-60,194,-60,196,-60,192,-60,197,-60,195,-60,79,-30,211,-30,212,-30,214,-30,210,-30,216,-30,213,-30,97,-111,225,-111,226,-111,228,-111,224,-111,229,-111,227,-111,58,-65,44,-129,101,-111,233,-111,234,-111,235,-71,232,-71,45,-55,105,-74,237,-74,238,-34,239,-34,236,-34,111,-111,243,-111,244,-111,246,-111,242,-111,248,-111,245,-111,46,-129,59,-74,117,-74,250,-74,251,-74,252,-74,249,-74,}, + {87,833,65,-60,193,-60,194,-60,196,-60,192,-60,197,-60,195,-60,79,-25,211,-25,212,-25,214,-25,210,-25,216,-25,213,-25,97,-92,225,-92,226,-92,228,-92,224,-92,229,-92,227,-92,58,-65,44,-92,101,-92,233,-92,234,-92,235,-52,232,-52,45,-37,105,-55,237,-55,111,-92,243,-92,244,-92,246,-92,242,-92,248,-92,245,-92,46,-92,59,-65,117,-55,250,-55,251,-55,252,-55,249,-55,121,-70,253,-70,255,-70,}, + {88,611,}, + {89,556,65,-50,193,-50,194,-50,196,-50,192,-50,197,-50,195,-50,79,-15,211,-15,212,-15,214,-15,210,-15,216,-15,213,-15,97,-92,225,-92,226,-92,228,-92,224,-92,229,-92,227,-92,58,-65,44,-92,101,-92,233,-92,234,-92,235,-52,232,-52,45,-74,105,-74,237,-74,238,-34,239,-34,236,-34,111,-92,243,-92,244,-92,246,-92,242,-92,248,-92,245,-92,46,-92,59,-65,117,-92,250,-92,251,-92,252,-92,249,-92,}, + {90,556,}, + {91,389,}, + {92,278,}, + {93,389,}, + {94,422,}, + {95,500,}, + {96,333,}, + {97,500,103,-10,}, + {98,500,46,-40,117,-20,250,-20,251,-20,252,-20,249,-20,}, + {99,444,104,-15,107,-20,}, + {100,500,}, + {101,444,44,-10,103,-40,46,-15,118,-15,119,-15,120,-20,121,-30,253,-30,255,-30,}, + {102,278,44,-10,102,-18,105,-20,46,-15,146,92,}, + {103,500,44,-10,101,-10,233,-10,234,-10,235,-10,232,-10,103,-10,46,-15,}, + {104,500,}, + {105,278,}, + {106,278,}, + {107,444,101,-10,233,-10,234,-10,235,-10,232,-10,111,-10,243,-10,244,-10,246,-10,242,-10,248,-10,245,-10,121,-10,253,-10,255,-10,}, + {108,278,}, + {109,722,}, + {110,500,118,-40,}, + {111,500,103,-10,118,-10,}, + {112,500,}, + {113,500,}, + {114,389,97,-15,225,-15,226,-15,228,-15,224,-15,229,-15,227,-15,99,-37,231,-37,44,-111,100,-37,101,-37,233,-37,234,-37,235,-37,232,-37,103,-37,45,-20,111,-45,243,-45,244,-45,246,-45,242,-45,248,-45,245,-45,46,-111,113,-37,115,-10,154,-10,}, + {115,389,}, + {116,278,}, + {117,500,}, + {118,444,44,-74,46,-74,}, + {119,667,44,-74,46,-74,}, + {120,444,}, + {121,444,44,-55,46,-55,}, + {122,389,}, + {123,400,}, + {124,275,}, + {125,400,}, + {126,541,}, + {127,250,}, + {128,500,}, + {129,250,}, + {130,333,}, + {131,500,}, + {132,556,}, + {133,889,}, + {134,500,}, + {135,500,}, + {136,333,}, + {137,1000,}, + {138,500,}, + {139,333,}, + {140,944,}, + {141,250,}, + {142,556,}, + {143,250,}, + {144,250,}, + {145,333,145,-111,}, + {146,333,100,-25,146,-111,114,-25,115,-40,154,-40,32,-111,116,-30,118,-10,}, + {147,556,}, + {148,556,}, + {149,350,}, + {150,500,}, + {151,889,}, + {152,333,}, + {153,980,}, + {154,389,}, + {155,333,}, + {156,667,}, + {157,250,}, + {158,389,}, + {159,556,65,-50,193,-50,194,-50,196,-50,192,-50,197,-50,195,-50,79,-15,211,-15,212,-15,214,-15,210,-15,216,-15,213,-15,97,-92,225,-92,226,-92,228,-92,224,-92,229,-92,227,-92,58,-65,44,-92,101,-92,233,-92,234,-92,235,-52,232,-52,45,-74,105,-74,237,-74,238,-34,239,-34,236,-34,111,-92,243,-92,244,-92,246,-92,242,-92,248,-92,245,-92,46,-92,59,-65,117,-92,250,-92,251,-92,252,-92,249,-92,}, + {160,250,}, + {161,389,}, + {162,500,}, + {163,500,}, + {164,500,}, + {165,500,}, + {166,275,}, + {167,500,}, + {168,333,}, + {169,760,}, + {170,276,}, + {171,500,}, + {172,675,}, + {173,250,}, + {174,760,}, + {175,333,}, + {176,400,}, + {177,675,}, + {178,300,}, + {179,300,}, + {180,333,}, + {181,500,}, + {182,523,}, + {183,250,}, + {184,333,}, + {185,300,}, + {186,310,}, + {187,500,}, + {188,750,}, + {189,750,}, + {190,750,}, + {191,500,}, + {192,611,67,-30,199,-30,71,-35,79,-40,211,-40,212,-40,214,-40,210,-40,216,-40,213,-40,81,-40,84,-37,85,-50,218,-50,219,-50,220,-50,217,-50,86,-105,87,-95,89,-55,221,-55,159,-55,146,-37,117,-20,250,-20,251,-20,252,-20,249,-20,118,-55,119,-55,121,-55,253,-55,255,-55,}, + {193,611,67,-30,199,-30,71,-35,79,-40,211,-40,212,-40,214,-40,210,-40,216,-40,213,-40,81,-40,84,-37,85,-50,218,-50,219,-50,220,-50,217,-50,86,-105,87,-95,89,-55,221,-55,159,-55,146,-37,117,-20,250,-20,251,-20,252,-20,249,-20,118,-55,119,-55,121,-55,253,-55,255,-55,}, + {194,611,67,-30,199,-30,71,-35,79,-40,211,-40,212,-40,214,-40,210,-40,216,-40,213,-40,81,-40,84,-37,85,-50,218,-50,219,-50,220,-50,217,-50,86,-105,87,-95,89,-55,221,-55,159,-55,146,-37,117,-20,250,-20,251,-20,252,-20,249,-20,118,-55,119,-55,121,-55,253,-55,255,-55,}, + {195,611,67,-30,199,-30,71,-35,79,-40,211,-40,212,-40,214,-40,210,-40,216,-40,213,-40,81,-40,84,-37,85,-50,218,-50,219,-50,220,-50,217,-50,86,-105,87,-95,89,-55,221,-55,159,-55,146,-37,117,-20,250,-20,251,-20,252,-20,249,-20,118,-55,119,-55,121,-55,253,-55,255,-55,}, + {196,611,67,-30,199,-30,71,-35,79,-40,211,-40,212,-40,214,-40,210,-40,216,-40,213,-40,81,-40,84,-37,85,-50,218,-50,219,-50,220,-50,217,-50,86,-105,87,-95,89,-55,221,-55,159,-55,146,-37,117,-20,250,-20,251,-20,252,-20,249,-20,118,-55,119,-55,121,-55,253,-55,255,-55,}, + {197,611,67,-30,199,-30,71,-35,79,-40,211,-40,212,-40,214,-40,210,-40,216,-40,213,-40,81,-40,84,-37,85,-50,218,-50,219,-50,220,-50,217,-50,86,-105,87,-95,89,-55,221,-55,159,-55,146,-37,117,-20,250,-20,251,-20,252,-20,249,-20,118,-55,119,-55,121,-55,253,-55,255,-55,}, + {198,889,}, + {199,667,}, + {200,611,}, + {201,611,}, + {202,611,}, + {203,611,}, + {204,333,}, + {205,333,}, + {206,333,}, + {207,333,}, + {208,722,}, + {209,667,65,-27,193,-27,194,-27,196,-27,192,-27,197,-27,195,-27,}, + {210,722,65,-55,193,-55,194,-55,196,-55,192,-55,197,-55,195,-55,84,-40,86,-50,87,-50,88,-40,89,-50,221,-50,159,-50,}, + {211,722,65,-55,193,-55,194,-55,196,-55,192,-55,197,-55,195,-55,84,-40,86,-50,87,-50,88,-40,89,-50,221,-50,159,-50,}, + {212,722,65,-55,193,-55,194,-55,196,-55,192,-55,197,-55,195,-55,84,-40,86,-50,87,-50,88,-40,89,-50,221,-50,159,-50,}, + {213,722,65,-55,193,-55,194,-55,196,-55,192,-55,197,-55,195,-55,84,-40,86,-50,87,-50,88,-40,89,-50,221,-50,159,-50,}, + {214,722,65,-55,193,-55,194,-55,196,-55,192,-55,197,-55,195,-55,84,-40,86,-50,87,-50,88,-40,89,-50,221,-50,159,-50,}, + {215,675,}, + {216,722,65,-55,193,-55,194,-55,196,-55,192,-55,197,-55,195,-55,84,-40,86,-50,87,-50,88,-40,89,-50,221,-50,159,-50,}, + {217,722,65,-40,193,-40,194,-40,196,-40,192,-40,197,-40,195,-40,44,-25,46,-25,}, + {218,722,65,-40,193,-40,194,-40,196,-40,192,-40,197,-40,195,-40,44,-25,46,-25,}, + {219,722,65,-40,193,-40,194,-40,196,-40,192,-40,197,-40,195,-40,44,-25,46,-25,}, + {220,722,65,-40,193,-40,194,-40,196,-40,192,-40,197,-40,195,-40,44,-25,46,-25,}, + {221,556,65,-50,193,-50,194,-50,196,-50,192,-50,197,-50,195,-50,79,-15,211,-15,212,-15,214,-15,210,-15,216,-15,213,-15,97,-92,225,-92,226,-92,228,-92,224,-92,229,-92,227,-92,58,-65,44,-92,101,-92,233,-92,234,-92,235,-52,232,-52,45,-74,105,-74,237,-74,238,-34,239,-34,236,-34,111,-92,243,-92,244,-92,246,-92,242,-92,248,-92,245,-92,46,-92,59,-65,117,-92,250,-92,251,-92,252,-92,249,-92,}, + {222,611,}, + {223,500,}, + {224,500,103,-10,}, + {225,500,103,-10,}, + {226,500,103,-10,}, + {227,500,103,-10,}, + {228,500,103,-10,}, + {229,500,103,-10,}, + {230,667,}, + {231,444,104,-15,107,-20,}, + {232,444,44,-10,103,-40,46,-15,118,-15,119,-15,120,-20,121,-30,253,-30,255,-30,}, + {233,444,44,-10,103,-40,46,-15,118,-15,119,-15,120,-20,121,-30,253,-30,255,-30,}, + {234,444,44,-10,103,-40,46,-15,118,-15,119,-15,120,-20,121,-30,253,-30,255,-30,}, + {235,444,44,-10,103,-40,46,-15,118,-15,119,-15,120,-20,121,-30,253,-30,255,-30,}, + {236,278,}, + {237,278,}, + {238,278,}, + {239,278,}, + {240,500,}, + {241,500,118,-40,}, + {242,500,103,-10,118,-10,}, + {243,500,103,-10,118,-10,}, + {244,500,103,-10,118,-10,}, + {245,500,103,-10,118,-10,}, + {246,500,103,-10,118,-10,}, + {247,675,}, + {248,500,103,-10,118,-10,}, + {249,500,}, + {250,500,}, + {251,500,}, + {252,500,}, + {253,444,44,-55,46,-55,}, + {254,500,}, + {255,444,44,-55,46,-55,}, + }; +} diff --git a/PDFJet/src/main/java/com/pdfjet/Times_Roman.java b/PDFJet/src/main/java/com/pdfjet/Times_Roman.java new file mode 100644 index 0000000..2151a4d --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Times_Roman.java @@ -0,0 +1,238 @@ +package com.pdfjet; + +class Times_Roman { + protected static final String name = "Times-Roman"; + protected static final int bBoxLLx = -168; + protected static final int bBoxLLy = -218; + protected static final int bBoxURx = 1000; + protected static final int bBoxURy = 898; + protected static final int underlinePosition = -100; + protected static final int underlineThickness = 50; + protected static final String notice = "Copyright (c) 1985, 1987, 1989, 1990, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved. Times is a trademark of Linotype-Hell AG and/or its subsidiaries."; + protected static final int[][] metrics = { + {32,250,65,-55,193,-55,194,-55,196,-55,192,-55,197,-55,195,-55,84,-18,86,-50,87,-30,89,-90,221,-90,159,-90,}, + {33,333,}, + {34,408,}, + {35,500,}, + {36,500,}, + {37,833,}, + {38,778,}, + {39,180,}, + {40,333,}, + {41,333,}, + {42,500,}, + {43,564,}, + {44,250,148,-70,146,-70,}, + {45,333,}, + {46,250,148,-70,146,-70,}, + {47,278,}, + {48,500,}, + {49,500,}, + {50,500,}, + {51,500,}, + {52,500,}, + {53,500,}, + {54,500,}, + {55,500,}, + {56,500,}, + {57,500,}, + {58,278,}, + {59,278,}, + {60,564,}, + {61,564,}, + {62,564,}, + {63,444,}, + {64,921,}, + {65,722,67,-40,199,-40,71,-40,79,-55,211,-55,212,-55,214,-55,210,-55,216,-55,213,-55,81,-55,84,-111,85,-55,218,-55,219,-55,220,-55,217,-55,86,-135,87,-90,89,-105,221,-105,159,-105,146,-111,118,-74,119,-92,121,-92,253,-92,255,-92,}, + {66,667,65,-35,193,-35,194,-35,196,-35,192,-35,197,-35,195,-35,85,-10,218,-10,219,-10,220,-10,217,-10,}, + {67,667,}, + {68,722,65,-40,193,-40,194,-40,196,-40,192,-40,197,-40,195,-40,86,-40,87,-30,89,-55,221,-55,159,-55,}, + {69,611,}, + {70,556,65,-74,193,-74,194,-74,196,-74,192,-74,197,-74,195,-74,97,-15,225,-15,226,-15,228,-15,224,-15,229,-15,227,-15,44,-80,111,-15,243,-15,244,-15,246,-15,242,-15,248,-15,245,-15,46,-80,}, + {71,722,}, + {72,722,}, + {73,333,}, + {74,389,65,-60,193,-60,194,-60,196,-60,192,-60,197,-60,195,-60,}, + {75,722,79,-30,211,-30,212,-30,214,-30,210,-30,216,-30,213,-30,101,-25,233,-25,234,-25,235,-25,232,-25,111,-35,243,-35,244,-35,246,-35,242,-35,248,-35,245,-35,117,-15,250,-15,251,-15,252,-15,249,-15,121,-25,253,-25,255,-25,}, + {76,611,84,-92,86,-100,87,-74,89,-100,221,-100,159,-100,146,-92,121,-55,253,-55,255,-55,}, + {77,889,}, + {78,722,65,-35,193,-35,194,-35,196,-35,192,-35,197,-35,195,-35,}, + {79,722,65,-35,193,-35,194,-35,196,-35,192,-35,197,-35,195,-35,84,-40,86,-50,87,-35,88,-40,89,-50,221,-50,159,-50,}, + {80,556,65,-92,193,-92,194,-92,196,-92,192,-92,197,-92,195,-92,97,-15,225,-15,226,-15,228,-15,224,-15,229,-15,227,-15,44,-111,46,-111,}, + {81,722,85,-10,218,-10,219,-10,220,-10,217,-10,}, + {82,667,79,-40,211,-40,212,-40,214,-40,210,-40,216,-40,213,-40,84,-60,85,-40,218,-40,219,-40,220,-40,217,-40,86,-80,87,-55,89,-65,221,-65,159,-65,}, + {83,556,}, + {84,611,65,-93,193,-93,194,-93,196,-93,192,-93,197,-93,195,-93,79,-18,211,-18,212,-18,214,-18,210,-18,216,-18,213,-18,97,-80,225,-80,226,-80,228,-40,224,-40,229,-80,227,-40,58,-50,44,-74,101,-70,233,-70,234,-70,235,-30,232,-70,45,-92,105,-35,237,-35,111,-80,243,-80,244,-80,246,-80,242,-80,248,-80,245,-80,46,-74,114,-35,59,-55,117,-45,250,-45,251,-45,252,-45,249,-45,119,-80,121,-80,253,-80,255,-80,}, + {85,722,65,-40,193,-40,194,-40,196,-40,192,-40,197,-40,195,-40,}, + {86,722,65,-135,193,-135,194,-135,196,-135,192,-135,197,-135,195,-135,71,-15,79,-40,211,-40,212,-40,214,-40,210,-40,216,-40,213,-40,97,-111,225,-111,226,-71,228,-71,224,-71,229,-111,227,-71,58,-74,44,-129,101,-111,233,-111,234,-71,235,-71,232,-71,45,-100,105,-60,237,-60,238,-20,239,-20,236,-20,111,-129,243,-129,244,-129,246,-89,242,-89,248,-129,245,-89,46,-129,59,-74,117,-75,250,-75,251,-75,252,-75,249,-75,}, + {87,944,65,-120,193,-120,194,-120,196,-120,192,-120,197,-120,195,-120,79,-10,211,-10,212,-10,214,-10,210,-10,216,-10,213,-10,97,-80,225,-80,226,-80,228,-80,224,-80,229,-80,227,-80,58,-37,44,-92,101,-80,233,-80,234,-80,235,-40,232,-40,45,-65,105,-40,237,-40,111,-80,243,-80,244,-80,246,-80,242,-80,248,-80,245,-80,46,-92,59,-37,117,-50,250,-50,251,-50,252,-50,249,-50,121,-73,253,-73,255,-73,}, + {88,722,}, + {89,722,65,-120,193,-120,194,-120,196,-120,192,-120,197,-120,195,-120,79,-30,211,-30,212,-30,214,-30,210,-30,216,-30,213,-30,97,-100,225,-100,226,-100,228,-60,224,-60,229,-100,227,-60,58,-92,44,-129,101,-100,233,-100,234,-100,235,-60,232,-60,45,-111,105,-55,237,-55,111,-110,243,-110,244,-110,246,-70,242,-70,248,-110,245,-70,46,-129,59,-92,117,-111,250,-111,251,-111,252,-71,249,-71,}, + {90,611,}, + {91,333,}, + {92,278,}, + {93,333,}, + {94,469,}, + {95,500,}, + {96,333,}, + {97,444,118,-20,119,-15,}, + {98,500,46,-40,117,-20,250,-20,251,-20,252,-20,249,-20,118,-15,}, + {99,444,121,-15,253,-15,255,-15,}, + {100,500,}, + {101,444,103,-15,118,-25,119,-25,120,-15,121,-15,253,-15,255,-15,}, + {102,333,97,-10,225,-10,226,-10,228,-10,224,-10,229,-10,227,-10,102,-25,105,-20,237,-20,146,55,}, + {103,500,97,-5,225,-5,226,-5,228,-5,224,-5,229,-5,227,-5,}, + {104,500,121,-5,253,-5,255,-5,}, + {105,278,118,-25,}, + {106,278,}, + {107,500,101,-10,233,-10,234,-10,235,-10,232,-10,111,-10,243,-10,244,-10,246,-10,242,-10,248,-10,245,-10,121,-15,253,-15,255,-15,}, + {108,278,119,-10,}, + {109,778,}, + {110,500,118,-40,121,-15,253,-15,255,-15,}, + {111,500,118,-15,119,-25,121,-10,253,-10,255,-10,}, + {112,500,121,-10,253,-10,255,-10,}, + {113,500,}, + {114,333,44,-40,103,-18,45,-20,46,-55,}, + {115,389,}, + {116,278,}, + {117,500,}, + {118,500,97,-25,225,-25,226,-25,228,-25,224,-25,229,-25,227,-25,44,-65,101,-15,233,-15,234,-15,235,-15,232,-15,111,-20,243,-20,244,-20,246,-20,242,-20,248,-20,245,-20,46,-65,}, + {119,722,97,-10,225,-10,226,-10,228,-10,224,-10,229,-10,227,-10,44,-65,111,-10,243,-10,244,-10,246,-10,242,-10,248,-10,245,-10,46,-65,}, + {120,500,101,-15,233,-15,234,-15,235,-15,232,-15,}, + {121,500,44,-65,46,-65,}, + {122,444,}, + {123,480,}, + {124,200,}, + {125,480,}, + {126,541,}, + {127,250,}, + {128,500,}, + {129,250,}, + {130,333,}, + {131,500,}, + {132,444,}, + {133,1000,}, + {134,500,}, + {135,500,}, + {136,333,}, + {137,1000,}, + {138,556,}, + {139,333,}, + {140,889,}, + {141,250,}, + {142,611,}, + {143,250,}, + {144,250,}, + {145,333,65,-80,193,-80,194,-80,196,-80,192,-80,197,-80,195,-80,145,-74,}, + {146,333,100,-50,108,-10,146,-74,114,-50,115,-55,154,-55,32,-74,116,-18,118,-50,}, + {147,444,65,-80,193,-80,194,-80,196,-80,192,-80,197,-80,195,-80,}, + {148,444,}, + {149,350,}, + {150,500,}, + {151,1000,}, + {152,333,}, + {153,980,}, + {154,389,}, + {155,333,}, + {156,722,}, + {157,250,}, + {158,444,}, + {159,722,65,-120,193,-120,194,-120,196,-120,192,-120,197,-120,195,-120,79,-30,211,-30,212,-30,214,-30,210,-30,216,-30,213,-30,97,-100,225,-100,226,-100,228,-60,224,-60,229,-100,227,-100,58,-92,44,-129,101,-100,233,-100,234,-100,235,-60,232,-60,45,-111,105,-55,237,-55,111,-110,243,-110,244,-110,246,-70,242,-70,248,-110,245,-70,46,-129,59,-92,117,-111,250,-111,251,-111,252,-71,249,-71,}, + {160,250,}, + {161,333,}, + {162,500,}, + {163,500,}, + {164,500,}, + {165,500,}, + {166,200,}, + {167,500,}, + {168,333,}, + {169,760,}, + {170,276,}, + {171,500,}, + {172,564,}, + {173,250,}, + {174,760,}, + {175,333,}, + {176,400,}, + {177,564,}, + {178,300,}, + {179,300,}, + {180,333,}, + {181,500,}, + {182,453,}, + {183,250,}, + {184,333,}, + {185,300,}, + {186,310,}, + {187,500,}, + {188,750,}, + {189,750,}, + {190,750,}, + {191,444,}, + {192,722,67,-40,199,-40,71,-40,79,-55,211,-55,212,-55,214,-55,210,-55,216,-55,213,-55,81,-55,84,-111,85,-55,218,-55,219,-55,220,-55,217,-55,86,-135,87,-90,89,-105,221,-105,159,-105,146,-111,118,-74,119,-92,121,-92,253,-92,255,-92,}, + {193,722,67,-40,199,-40,71,-40,79,-55,211,-55,212,-55,214,-55,210,-55,216,-55,213,-55,81,-55,84,-111,85,-55,218,-55,219,-55,220,-55,217,-55,86,-135,87,-90,89,-105,221,-105,159,-105,146,-111,118,-74,119,-92,121,-92,253,-92,255,-92,}, + {194,722,67,-40,199,-40,71,-40,79,-55,211,-55,212,-55,214,-55,210,-55,216,-55,213,-55,81,-55,84,-111,85,-55,218,-55,219,-55,220,-55,217,-55,86,-135,87,-90,89,-105,221,-105,159,-105,146,-111,118,-74,119,-92,121,-92,253,-92,255,-92,}, + {195,722,67,-40,199,-40,71,-40,79,-55,211,-55,212,-55,214,-55,210,-55,216,-55,213,-55,81,-55,84,-111,85,-55,218,-55,219,-55,220,-55,217,-55,86,-135,87,-90,89,-105,221,-105,159,-105,146,-111,118,-74,119,-92,121,-92,253,-92,255,-92,}, + {196,722,67,-40,199,-40,71,-40,79,-55,211,-55,212,-55,214,-55,210,-55,216,-55,213,-55,81,-55,84,-111,85,-55,218,-55,219,-55,220,-55,217,-55,86,-135,87,-90,89,-105,221,-105,159,-105,146,-111,118,-74,119,-92,121,-92,253,-92,255,-92,}, + {197,722,67,-40,199,-40,71,-40,79,-55,211,-55,212,-55,214,-55,210,-55,216,-55,213,-55,81,-55,84,-111,85,-55,218,-55,219,-55,220,-55,217,-55,86,-135,87,-90,89,-105,221,-105,159,-105,146,-111,118,-74,119,-92,121,-92,253,-92,255,-92,}, + {198,889,}, + {199,667,}, + {200,611,}, + {201,611,}, + {202,611,}, + {203,611,}, + {204,333,}, + {205,333,}, + {206,333,}, + {207,333,}, + {208,722,}, + {209,722,65,-35,193,-35,194,-35,196,-35,192,-35,197,-35,195,-35,}, + {210,722,65,-35,193,-35,194,-35,196,-35,192,-35,197,-35,195,-35,84,-40,86,-50,87,-35,88,-40,89,-50,221,-50,159,-50,}, + {211,722,65,-35,193,-35,194,-35,196,-35,192,-35,197,-35,195,-35,84,-40,86,-50,87,-35,88,-40,89,-50,221,-50,159,-50,}, + {212,722,65,-35,193,-35,194,-35,196,-35,192,-35,197,-35,195,-35,84,-40,86,-50,87,-35,88,-40,89,-50,221,-50,159,-50,}, + {213,722,65,-35,193,-35,194,-35,196,-35,192,-35,197,-35,195,-35,84,-40,86,-50,87,-35,88,-40,89,-50,221,-50,159,-50,}, + {214,722,65,-35,193,-35,194,-35,196,-35,192,-35,197,-35,195,-35,84,-40,86,-50,87,-35,88,-40,89,-50,221,-50,159,-50,}, + {215,564,}, + {216,722,65,-35,193,-35,194,-35,196,-35,192,-35,197,-35,195,-35,84,-40,86,-50,87,-35,88,-40,89,-50,221,-50,159,-50,}, + {217,722,65,-40,193,-40,194,-40,196,-40,192,-40,197,-40,195,-40,}, + {218,722,65,-40,193,-40,194,-40,196,-40,192,-40,197,-40,195,-40,}, + {219,722,65,-40,193,-40,194,-40,196,-40,192,-40,197,-40,195,-40,}, + {220,722,65,-40,193,-40,194,-40,196,-40,192,-40,197,-40,195,-40,}, + {221,722,65,-120,193,-120,194,-120,196,-120,192,-120,197,-120,195,-120,79,-30,211,-30,212,-30,214,-30,210,-30,216,-30,213,-30,97,-100,225,-100,226,-100,228,-60,224,-60,229,-100,227,-60,58,-92,44,-129,101,-100,233,-100,234,-100,235,-60,232,-60,45,-111,105,-55,237,-55,111,-110,243,-110,244,-110,246,-70,242,-70,248,-110,245,-70,46,-129,59,-92,117,-111,250,-111,251,-111,252,-71,249,-71,}, + {222,556,}, + {223,500,}, + {224,444,118,-20,119,-15,}, + {225,444,118,-20,119,-15,}, + {226,444,118,-20,119,-15,}, + {227,444,118,-20,119,-15,}, + {228,444,118,-20,119,-15,}, + {229,444,118,-20,119,-15,}, + {230,667,}, + {231,444,121,-15,253,-15,255,-15,}, + {232,444,103,-15,118,-25,119,-25,120,-15,121,-15,253,-15,255,-15,}, + {233,444,103,-15,118,-25,119,-25,120,-15,121,-15,253,-15,255,-15,}, + {234,444,103,-15,118,-25,119,-25,120,-15,121,-15,253,-15,255,-15,}, + {235,444,103,-15,118,-25,119,-25,120,-15,121,-15,253,-15,255,-15,}, + {236,278,118,-25,}, + {237,278,118,-25,}, + {238,278,118,-25,}, + {239,278,118,-25,}, + {240,500,}, + {241,500,118,-40,121,-15,253,-15,255,-15,}, + {242,500,118,-15,119,-25,121,-10,253,-10,255,-10,}, + {243,500,118,-15,119,-25,121,-10,253,-10,255,-10,}, + {244,500,118,-15,119,-25,121,-10,253,-10,255,-10,}, + {245,500,118,-15,119,-25,121,-10,253,-10,255,-10,}, + {246,500,118,-15,119,-25,121,-10,253,-10,255,-10,}, + {247,564,}, + {248,500,118,-15,119,-25,121,-10,253,-10,255,-10,}, + {249,500,}, + {250,500,}, + {251,500,}, + {252,500,}, + {253,500,44,-65,46,-65,}, + {254,500,}, + {255,500,44,-65,46,-65,}, + }; +} diff --git a/PDFJet/src/main/java/com/pdfjet/Title.java b/PDFJet/src/main/java/com/pdfjet/Title.java new file mode 100644 index 0000000..d1dc705 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/Title.java @@ -0,0 +1,70 @@ +/** + * Title.java + * +Copyright (c) 2018, Innovatics Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and / or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.pdfjet; + + +/** + * Please see Example_51 and Example_52 + * + */ +public class Title { + + public TextLine prefix = null; + public TextLine text = null; + + + public Title(Font font, String title, float x, float y) { + this.prefix = new TextLine(font); + this.text = new TextLine(font, title); + this.prefix.setLocation(x, y); + this.text.setLocation(x, y); + } + + + public Title setPrefix(String text) { + prefix.setText(text); + return this; + } + + + public Title setOffset(float offset) { + text.setLocation(text.x + offset, text.y); + return this; + } + + + public void drawOn(Page page) throws Exception { + if (!prefix.equals("")) { + prefix.drawOn(page); + } + text.drawOn(page); + } + +} diff --git a/PDFJet/src/main/java/com/pdfjet/ZapfDingbats.java b/PDFJet/src/main/java/com/pdfjet/ZapfDingbats.java new file mode 100644 index 0000000..8a34c60 --- /dev/null +++ b/PDFJet/src/main/java/com/pdfjet/ZapfDingbats.java @@ -0,0 +1,238 @@ +package com.pdfjet; + +class ZapfDingbats { + protected static final String name = "ZapfDingbats"; + protected static final int bBoxLLx = -1; + protected static final int bBoxLLy = -143; + protected static final int bBoxURx = 981; + protected static final int bBoxURy = 820; + protected static final int underlinePosition = -100; + protected static final int underlineThickness = 50; + protected static final String notice = "Copyright (c) 1985, 1987, 1988, 1989, 1997 Adobe Systems Incorporated. All Rights Reserved. ITC Zapf Dingbats is a registered trademark of International Typeface Corporation."; + protected static final int[][] metrics = { + {32,278}, + {33,974}, + {34,961}, + {35,974}, + {36,980}, + {37,719}, + {38,789}, + {39,790}, + {40,791}, + {41,690}, + {42,960}, + {43,939}, + {44,549}, + {45,855}, + {46,911}, + {47,933}, + {48,911}, + {49,945}, + {50,974}, + {51,755}, + {52,846}, + {53,762}, + {54,761}, + {55,571}, + {56,677}, + {57,763}, + {58,760}, + {59,759}, + {60,754}, + {61,494}, + {62,552}, + {63,537}, + {64,577}, + {65,692}, + {66,786}, + {67,788}, + {68,788}, + {69,790}, + {70,793}, + {71,794}, + {72,816}, + {73,823}, + {74,789}, + {75,841}, + {76,823}, + {77,833}, + {78,816}, + {79,831}, + {80,923}, + {81,744}, + {82,723}, + {83,749}, + {84,790}, + {85,792}, + {86,695}, + {87,776}, + {88,768}, + {89,792}, + {90,759}, + {91,707}, + {92,708}, + {93,682}, + {94,701}, + {95,826}, + {96,815}, + {97,789}, + {98,789}, + {99,707}, + {100,687}, + {101,696}, + {102,689}, + {103,786}, + {104,787}, + {105,713}, + {106,791}, + {107,785}, + {108,791}, + {109,873}, + {110,761}, + {111,762}, + {112,762}, + {113,759}, + {114,759}, + {115,892}, + {116,892}, + {117,788}, + {118,784}, + {119,438}, + {120,138}, + {121,277}, + {122,415}, + {123,392}, + {124,392}, + {125,668}, + {126,668}, + {127,278}, + {128,390}, + {129,390}, + {130,317}, + {131,317}, + {132,276}, + {133,276}, + {134,509}, + {135,509}, + {136,410}, + {137,410}, + {138,234}, + {139,234}, + {140,334}, + {141,334}, + {142,278}, + {143,278}, + {144,278}, + {145,278}, + {146,278}, + {147,278}, + {148,278}, + {149,278}, + {150,278}, + {151,278}, + {152,278}, + {153,278}, + {154,278}, + {155,278}, + {156,278}, + {157,278}, + {158,278}, + {159,278}, + {160,278}, + {161,732}, + {162,544}, + {163,544}, + {164,910}, + {165,667}, + {166,760}, + {167,760}, + {168,776}, + {169,595}, + {170,694}, + {171,626}, + {172,788}, + {173,788}, + {174,788}, + {175,788}, + {176,788}, + {177,788}, + {178,788}, + {179,788}, + {180,788}, + {181,788}, + {182,788}, + {183,788}, + {184,788}, + {185,788}, + {186,788}, + {187,788}, + {188,788}, + {189,788}, + {190,788}, + {191,788}, + {192,788}, + {193,788}, + {194,788}, + {195,788}, + {196,788}, + {197,788}, + {198,788}, + {199,788}, + {200,788}, + {201,788}, + {202,788}, + {203,788}, + {204,788}, + {205,788}, + {206,788}, + {207,788}, + {208,788}, + {209,788}, + {210,788}, + {211,788}, + {212,894}, + {213,838}, + {214,1016}, + {215,458}, + {216,748}, + {217,924}, + {218,748}, + {219,918}, + {220,927}, + {221,928}, + {222,928}, + {223,834}, + {224,873}, + {225,828}, + {226,924}, + {227,924}, + {228,917}, + {229,930}, + {230,931}, + {231,463}, + {232,883}, + {233,836}, + {234,836}, + {235,867}, + {236,867}, + {237,696}, + {238,696}, + {239,874}, + {240,278}, + {241,874}, + {242,760}, + {243,946}, + {244,771}, + {245,865}, + {246,771}, + {247,888}, + {248,967}, + {249,888}, + {250,831}, + {251,873}, + {252,927}, + {253,970}, + {254,918}, + {255,278}, + }; +} diff --git a/app/build.gradle b/app/build.gradle index fc16275..32bf169 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -12,11 +12,11 @@ androidExtensions { } android { - compileSdkVersion 29 + compileSdkVersion 28 defaultConfig { applicationId "cy.agorise.bitsybitshareswallet" minSdkVersion 21 - targetSdkVersion 29 + targetSdkVersion 28 versionCode 9 versionName "0.13.1-beta" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" @@ -72,6 +72,7 @@ dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation project(':graphenejlib:graphenej') + implementation project(':PDFJet') implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" // AndroidX implementation 'androidx.appcompat:appcompat:1.1.0-beta01' // Not updating to 1.1.0 due to a crash in Android 5.0.2's WebView @@ -110,8 +111,7 @@ dependencies { //Firebase implementation 'com.google.firebase:firebase-core:17.2.0' implementation 'com.crashlytics.sdk.android:crashlytics:2.10.1' - // PDF and CSV generation - implementation 'com.itextpdf:itextpdf:5.5.13' + // CSV generation implementation 'com.opencsv:opencsv:3.7' // Others api 'com.google.guava:guava:27.0.1-android' diff --git a/app/src/main/java/cy/agorise/bitsybitshareswallet/utils/CSVGenerationTask.kt b/app/src/main/java/cy/agorise/bitsybitshareswallet/utils/CSVGenerationTask.kt index a46e28f..75fb185 100644 --- a/app/src/main/java/cy/agorise/bitsybitshareswallet/utils/CSVGenerationTask.kt +++ b/app/src/main/java/cy/agorise/bitsybitshareswallet/utils/CSVGenerationTask.kt @@ -51,14 +51,12 @@ class CSVGenerationTask(context: Context) : AsyncTask, Int, // Configure date and time formats to reuse in all the transfers val locale = mContext.get()?.resources?.configuration?.locale - val calendar = Calendar.getInstance() val dateFormat = SimpleDateFormat("MM-dd-yyyy", locale) - val timeFormat = SimpleDateFormat("HH:MM:ss", locale) + val timeFormat = SimpleDateFormat("HH:mm:ss", locale) // Save all the transfers information for ( (index, transferDetail) in transferDetails.withIndex()) { - calendar.timeInMillis = transferDetail.date * 1000 - val date = calendar.time + val date = Date(transferDetail.date * 1000) row[0] = transferDetail.from ?: "" // From row[1] = transferDetail.to ?: "" // To diff --git a/app/src/main/java/cy/agorise/bitsybitshareswallet/utils/PDFGeneratorTask.kt b/app/src/main/java/cy/agorise/bitsybitshareswallet/utils/PDFGeneratorTask.kt index d216180..ad7b995 100644 --- a/app/src/main/java/cy/agorise/bitsybitshareswallet/utils/PDFGeneratorTask.kt +++ b/app/src/main/java/cy/agorise/bitsybitshareswallet/utils/PDFGeneratorTask.kt @@ -4,18 +4,12 @@ import android.content.Context import android.os.AsyncTask import android.os.Environment import android.util.Log -import com.itextpdf.text.Document -import com.itextpdf.text.PageSize -import com.itextpdf.text.Paragraph -import com.itextpdf.text.pdf.PdfPCell -import com.itextpdf.text.pdf.PdfPTable -import com.itextpdf.text.pdf.PdfWriter +import androidx.core.os.ConfigurationCompat +import com.pdfjet.* + import cy.agorise.bitsybitshareswallet.R import cy.agorise.bitsybitshareswallet.database.joins.TransferDetail -import java.io.File -import java.io.FileOutputStream -import java.io.FileWriter -import java.io.IOException +import java.io.* import java.lang.Exception import java.lang.ref.WeakReference import java.text.SimpleDateFormat @@ -31,81 +25,12 @@ class PDFGeneratorTask(context: Context) : AsyncTask, Int, private const val TAG = "PDFGeneratorTask" } - private val mContext: WeakReference = WeakReference(context) + private val mContextRef: WeakReference = WeakReference(context) override fun doInBackground(vararg params: List): String { return createPDFDocument(params[0]) } - private fun createPDFDocument(transferDetails: List): String { - val document = Document(PageSize.A4.rotate()) - return try { - // Create and configure a new PDF file to save the transfers list - val externalStorageFolder = Environment.getExternalStorageDirectory().absolutePath + File.separator + - Constants.EXTERNAL_STORAGE_FOLDER - val fileName = mContext.get()?.resources?.let { - "${it.getString(R.string.app_name)}-${it.getString(R.string.title_transactions)}"} + ".pdf" - val filePath = combinePath(externalStorageFolder, fileName) - createEmptyFile(filePath) - PdfWriter.getInstance(document, FileOutputStream(filePath)) - document.open() - - // Configure pdf table with 8 columns - val table = PdfPTable(7) - - // Add the table header - val columnNames = arrayOf(R.string.title_from, R.string.title_to, R.string.title_memo, R.string.title_date, - R.string.title_time, R.string.title_amount, R.string.title_equivalent_value) - for (columnName in columnNames) { - val cell = PdfPCell(Paragraph(mContext.get()?.getString(columnName))) - table.addCell(cell) - } - table.completeRow() - - // Configure date and time formats to reuse in all the transfers - val locale = mContext.get()?.resources?.configuration?.locale - val calendar = Calendar.getInstance() - val dateFormat = SimpleDateFormat("MM-dd-yyyy", locale) - val timeFormat = SimpleDateFormat("HH:MM:ss", locale) - - // Save all the transfers information - for ( (index, transferDetail) in transferDetails.withIndex()) { - calendar.timeInMillis = transferDetail.date * 1000 - val date = calendar.time - - table.addCell(makeCell(transferDetail.from ?: "")) // From - table.addCell(makeCell(transferDetail.to ?: "")) // To - table.addCell(makeCell(transferDetail.memo)) // Memo - table.addCell(makeCell(dateFormat.format(date))) // Date - table.addCell(makeCell(timeFormat.format(date))) // Time - - // Asset Amount - val assetPrecision = transferDetail.assetPrecision - val assetAmount = transferDetail.assetAmount.toDouble() / Math.pow(10.0, assetPrecision.toDouble()) - table.addCell(makeCell(String.format("%.${assetPrecision}f %s", assetAmount, transferDetail.assetSymbol))) - - // Fiat Equivalent - if (transferDetail.fiatAmount != null && transferDetail.fiatSymbol != null) { - val currency = Currency.getInstance(transferDetail.fiatSymbol) - val fiatAmount = transferDetail.fiatAmount.toDouble() / - Math.pow(10.0, currency.defaultFractionDigits.toDouble()) - table.addCell(makeCell(String.format("%.${currency.defaultFractionDigits}f %s", - fiatAmount, currency.currencyCode))) - } - - table.completeRow() - - // TODO update progress - } - document.add(table) - document.close() - "PDF generated and saved: $filePath" - } catch (e: Exception) { - Log.e(TAG, "Exception while trying to generate a PDF. Msg: " + e.message) - "Unable to generate PDF. Please retry. Error: ${e.message}" - } - } - private fun combinePath(path1: String, path2: String): String { val file1 = File(path1) val file2 = File(file1, path2) @@ -125,16 +50,166 @@ class PDFGeneratorTask(context: Context) : AsyncTask, Int, } - /** Hides the simple but repetitive logic of creating a PDF table cell */ - private fun makeCell(text: String) : PdfPCell { - return PdfPCell(Paragraph(text)) + private fun createPDFDocument(transferDetails: List): String { + return try { + // Create the PDF file name + val fileName = mContextRef.get()?.resources?.let { + "${it.getString(R.string.app_name)}-${it.getString(R.string.title_transactions)}"} + ".pdf" + + // Obtains the path to store the PDF + val externalStorageFolder = Environment.getExternalStorageDirectory().absolutePath + File.separator + + Constants.EXTERNAL_STORAGE_FOLDER + val filePath = combinePath(externalStorageFolder, fileName) + createEmptyFile(filePath) + + // Creates a new PDF object + val pdf = PDF( + BufferedOutputStream( + FileOutputStream(filePath)), Compliance.PDF_A_1B) + + + // Font used for the table headers + val f1 = Font(pdf, CoreFont.HELVETICA_BOLD) + f1.size = 7f + + // Font used for the table contents + val f2 = Font(pdf, CoreFont.HELVETICA) + f2.size = 7f + + // Creates a new PDF table + val table = Table() + + // 2D array of cells used to populate the PDF table + val tableData = ArrayList>() + + // Add column names/headers + val columnNames = intArrayOf(R.string.title_from, R.string.title_to, R.string.title_memo, R.string.title_date, + R.string.title_time, R.string.title_amount, R.string.title_equivalent_value) + + val header = ArrayList() + + for (columnName in columnNames) { + val cell = Cell(f1, mContextRef.get()?.getString(columnName)) + cell.setTopPadding(2f) + cell.setBottomPadding(2f) + cell.setLeftPadding(2f) + cell.setRightPadding(2f) + header.add(cell) + } + + // Add the table headers + tableData.add(header) + + // Add the table contents + mContextRef.get()?.let { context -> + val locale = ConfigurationCompat.getLocales(context.resources.configuration)[0] + tableData.addAll(getData(transferDetails, f2, locale)) + } + + // Configure the PDF table + table.setData(tableData, Table.DATA_HAS_1_HEADER_ROWS) + table.setCellBordersWidth(0.2f) + // The A4 size has 595 points of width, with the below we are trying to assign the same + // width to all cells and also keep them centered. + for (i in 0..6) { + table.setColumnWidth(i, 65f) + } + table.wrapAroundCellText() + table.mergeOverlaidBorders() + + // Populate the PDF table + while (table.hasMoreData()) { + // Configures the PDF page + val page = Page(pdf, Letter.PORTRAIT) + table.setLocation(45f, 30f) + table.drawOn(page) + } + + pdf.close() + + "PDF generated and saved: $filePath" + } catch (e: Exception) { + Log.e(TAG, "Exception while trying to generate a PDF. Msg: " + e.message) + "Unable to generate PDF. Please retry. Error: ${e.message}" + } } + private fun getData(transferDetails: List, font: Font, locale: Locale): List> { + + val tableData = ArrayList>() + + // Configure date and time formats to reuse in all the transfers + val dateFormat = SimpleDateFormat("MM-dd-yyyy", locale) + val timeFormat = SimpleDateFormat("HH:mm:ss", locale) + var date: Date + + // Save all the transfers information + for ( (index, transferDetail) in transferDetails.withIndex()) { + val row = ArrayList() + + val cols = ArrayList() + + date = Date(transferDetail.date * 1000) + + cols.add(transferDetail.from ?: "") // From + cols.add(transferDetail.to ?: "") // To + cols.add(transferDetail.memo) // Memo + cols.add(dateFormat.format(date)) // Date + cols.add(timeFormat.format(date)) // Time + + // Asset Amount + val assetPrecision = transferDetail.assetPrecision + val assetAmount = transferDetail.assetAmount.toDouble() / Math.pow(10.0, assetPrecision.toDouble()) + cols.add(String.format("%.${assetPrecision}f %s", assetAmount, transferDetail.assetSymbol)) + + // Fiat Equivalent + if (transferDetail.fiatAmount != null && transferDetail.fiatSymbol != null) { + val currency = Currency.getInstance(transferDetail.fiatSymbol) + val fiatAmount = transferDetail.fiatAmount.toDouble() / + Math.pow(10.0, currency.defaultFractionDigits.toDouble()) + cols.add(String.format("%.${currency.defaultFractionDigits}f %s", + fiatAmount, currency.currencyCode)) + } + + for (col in cols) { + val cell = Cell(font, col) + cell.setTopPadding(2f) + cell.setBottomPadding(2f) + cell.setLeftPadding(2f) + cell.setRightPadding(2f) + row.add(cell) + } + tableData.add(row) + + appendMissingCells(tableData, font) + + // TODO update progress + } + + return tableData + } + + private fun appendMissingCells(tableData: List>, font: Font) { + val firstRow = tableData[0] + val numOfColumns = firstRow.size + for (i in tableData.indices) { + val dataRow = tableData[i] as ArrayList + val dataRowColumns = dataRow.size + if (dataRowColumns < numOfColumns) { + for (j in 0 until numOfColumns - dataRowColumns) { + dataRow.add(Cell(font)) + } + dataRow[dataRowColumns - 1].colSpan = numOfColumns - dataRowColumns + 1 + } + } + } + + override fun onProgressUpdate(values: Array) { // TODO show progress } override fun onPostExecute(message: String) { - mContext.get()?.toast(message) + mContextRef.get()?.toast(message) } } \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 5bbb01a..3c84eb6 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1 @@ -include ':app', ':graphenejlib:graphenej' +include ':app', ':graphenejlib:graphenej', ':PDFJet'