From 6025b6016517c6d898d8957d1d7e03ba71431912 Mon Sep 17 00:00:00 2001 From: tknall Date: Fri, 1 Dec 2006 12:20:24 +0000 Subject: Initial import of release 2.2. git-svn-id: https://joinup.ec.europa.eu/svn/pdf-as/trunk@4 7b5415b0-85f9-ee4d-85bd-d5d0c3b42d1c --- src/main/java/org/pdfbox/Decrypt.java | 122 ++ src/main/java/org/pdfbox/Encrypt.java | 234 ++++ src/main/java/org/pdfbox/ExportFDF.java | 155 +++ src/main/java/org/pdfbox/ExportXFDF.java | 155 +++ src/main/java/org/pdfbox/ExtractImages.java | 210 +++ src/main/java/org/pdfbox/ExtractText.java | 270 ++++ src/main/java/org/pdfbox/ImportFDF.java | 156 +++ src/main/java/org/pdfbox/ImportXFDF.java | 157 +++ src/main/java/org/pdfbox/Overlay.java | 530 ++++++++ src/main/java/org/pdfbox/PDFDebugger.java | 420 ++++++ src/main/java/org/pdfbox/PDFReader.java | 308 +++++ src/main/java/org/pdfbox/PDFSplit.java | 227 ++++ src/main/java/org/pdfbox/PDFToImage.java | 270 ++++ src/main/java/org/pdfbox/PrintPDF.java | 118 ++ src/main/java/org/pdfbox/TextToPDF.java | 259 ++++ src/main/java/org/pdfbox/Version.java | 100 ++ src/main/java/org/pdfbox/afmparser/AFMParser.java | 1084 ++++++++++++++++ src/main/java/org/pdfbox/afmparser/package.html | 12 + src/main/java/org/pdfbox/afmtypes/CharMetric.java | 299 +++++ src/main/java/org/pdfbox/afmtypes/Composite.java | 89 ++ .../java/org/pdfbox/afmtypes/CompositePart.java | 93 ++ src/main/java/org/pdfbox/afmtypes/FontMetric.java | 891 +++++++++++++ src/main/java/org/pdfbox/afmtypes/KernPair.java | 110 ++ src/main/java/org/pdfbox/afmtypes/Ligature.java | 76 ++ src/main/java/org/pdfbox/afmtypes/TrackKern.java | 127 ++ src/main/java/org/pdfbox/afmtypes/package.html | 9 + src/main/java/org/pdfbox/ant/PDFToTextTask.java | 100 ++ src/main/java/org/pdfbox/ant/package.html | 18 + .../java/org/pdfbox/cmapparser/CMapParser.java | 285 ++++ src/main/java/org/pdfbox/cmapparser/package.html | 9 + src/main/java/org/pdfbox/cmaptypes/CMap.java | 161 +++ .../java/org/pdfbox/cmaptypes/CodespaceRange.java | 88 ++ src/main/java/org/pdfbox/cmaptypes/package.html | 9 + src/main/java/org/pdfbox/cos/COSArray.java | 492 +++++++ src/main/java/org/pdfbox/cos/COSBase.java | 86 ++ src/main/java/org/pdfbox/cos/COSBoolean.java | 161 +++ src/main/java/org/pdfbox/cos/COSDictionary.java | 1167 +++++++++++++++++ src/main/java/org/pdfbox/cos/COSDocument.java | 518 ++++++++ src/main/java/org/pdfbox/cos/COSFloat.java | 173 +++ src/main/java/org/pdfbox/cos/COSInteger.java | 190 +++ src/main/java/org/pdfbox/cos/COSName.java | 572 ++++++++ src/main/java/org/pdfbox/cos/COSNull.java | 88 ++ src/main/java/org/pdfbox/cos/COSNumber.java | 115 ++ src/main/java/org/pdfbox/cos/COSObject.java | 226 ++++ src/main/java/org/pdfbox/cos/COSStream.java | 495 +++++++ src/main/java/org/pdfbox/cos/COSString.java | 403 ++++++ src/main/java/org/pdfbox/cos/ICOSVisitor.java | 132 ++ src/main/java/org/pdfbox/cos/package.html | 12 + src/main/java/org/pdfbox/encoding/AFMEncoding.java | 76 ++ .../org/pdfbox/encoding/DictionaryEncoding.java | 112 ++ src/main/java/org/pdfbox/encoding/Encoding.java | 268 ++++ .../java/org/pdfbox/encoding/EncodingManager.java | 87 ++ .../java/org/pdfbox/encoding/MacRomanEncoding.java | 267 ++++ .../java/org/pdfbox/encoding/PdfDocEncoding.java | 289 +++++ .../java/org/pdfbox/encoding/StandardEncoding.java | 209 +++ .../java/org/pdfbox/encoding/WinAnsiEncoding.java | 281 ++++ src/main/java/org/pdfbox/encoding/package.html | 9 + src/main/java/org/pdfbox/encryption/ARCFour.java | 182 +++ .../org/pdfbox/encryption/DocumentEncryption.java | 427 ++++++ .../java/org/pdfbox/encryption/PDFEncryption.java | 599 +++++++++ src/main/java/org/pdfbox/encryption/package.html | 9 + .../java/org/pdfbox/examples/AbstractExample.java | 125 ++ .../java/org/pdfbox/examples/fdf/PrintFields.java | 163 +++ .../java/org/pdfbox/examples/fdf/SetField.java | 128 ++ src/main/java/org/pdfbox/examples/fdf/package.html | 9 + src/main/java/org/pdfbox/examples/package.html | 9 + .../org/pdfbox/examples/pdmodel/AddJavascript.java | 96 ++ .../examples/pdmodel/AddMessageToEachPage.java | 148 +++ .../examples/pdmodel/AddMetadataFromDocInfo.java | 180 +++ .../pdfbox/examples/pdmodel/CreateBlankPDF.java | 123 ++ .../pdfbox/examples/pdmodel/CreateBookmarks.java | 119 ++ .../org/pdfbox/examples/pdmodel/EmbeddedFiles.java | 170 +++ .../org/pdfbox/examples/pdmodel/HelloWorld.java | 137 ++ .../org/pdfbox/examples/pdmodel/HelloWorldTTF.java | 134 ++ .../examples/pdmodel/HelloWorldType1AfmPfb.java | 134 ++ .../org/pdfbox/examples/pdmodel/ImageToPDF.java | 146 +++ .../pdfbox/examples/pdmodel/PrintBookmarks.java | 142 ++ .../examples/pdmodel/PrintDocumentMetaData.java | 165 +++ .../pdfbox/examples/pdmodel/RemoveFirstPage.java | 98 ++ .../org/pdfbox/examples/pdmodel/ReplaceString.java | 186 +++ .../org/pdfbox/examples/pdmodel/RubberStamp.java | 113 ++ .../pdfbox/examples/pdmodel/ShowColorBoxes.java | 135 ++ .../java/org/pdfbox/examples/pdmodel/package.html | 9 + .../examples/persistence/AppendAndFillDoc.java | 282 ++++ .../org/pdfbox/examples/persistence/AppendDoc.java | 357 +++++ .../org/pdfbox/examples/persistence/CopyDoc.java | 140 ++ .../org/pdfbox/examples/persistence/FieldsDoc.java | 177 +++ .../examples/persistence/WriteDecodedDoc.java | 151 +++ .../org/pdfbox/examples/persistence/package.html | 9 + .../pdfbox/examples/signature/ShowSignature.java | 168 +++ .../org/pdfbox/examples/signature/package.html | 9 + .../pdfbox/examples/util/ExtractTextByArea.java | 119 ++ .../pdfbox/examples/util/PrintTextLocations.java | 144 ++ .../java/org/pdfbox/examples/util/package.html | 9 + .../org/pdfbox/exceptions/COSVisitorException.java | 53 + .../pdfbox/exceptions/CryptographyException.java | 82 ++ .../exceptions/InvalidPasswordException.java | 51 + .../exceptions/OutlineNotLocalException.java | 55 + .../org/pdfbox/exceptions/WrappedException.java | 75 ++ .../org/pdfbox/exceptions/WrappedIOException.java | 76 ++ src/main/java/org/pdfbox/exceptions/package.html | 9 + src/main/java/org/pdfbox/filter/ASCII85Filter.java | 103 ++ .../java/org/pdfbox/filter/ASCIIHexFilter.java | 205 +++ .../org/pdfbox/filter/CCITTFaxDecodeFilter.java | 735 +++++++++++ src/main/java/org/pdfbox/filter/DCTFilter.java | 77 ++ src/main/java/org/pdfbox/filter/Filter.java | 68 + src/main/java/org/pdfbox/filter/FilterManager.java | 135 ++ src/main/java/org/pdfbox/filter/FlateFilter.java | 303 +++++ src/main/java/org/pdfbox/filter/LZWDictionary.java | 215 +++ src/main/java/org/pdfbox/filter/LZWFilter.java | 235 ++++ src/main/java/org/pdfbox/filter/LZWNode.java | 115 ++ .../org/pdfbox/filter/RunLengthDecodeFilter.java | 126 ++ src/main/java/org/pdfbox/filter/package.html | 9 + .../java/org/pdfbox/io/ASCII85InputStream.java | 269 ++++ .../java/org/pdfbox/io/ASCII85OutputStream.java | 304 +++++ .../pdfbox/io/ByteArrayPushBackInputStream.java | 404 ++++++ .../org/pdfbox/io/FastByteArrayOutputStream.java | 62 + src/main/java/org/pdfbox/io/NBitInputStream.java | 124 ++ src/main/java/org/pdfbox/io/NBitOutputStream.java | 116 ++ .../java/org/pdfbox/io/PushBackInputStream.java | 92 ++ .../org/pdfbox/io/RandomAccessFileInputStream.java | 132 ++ .../pdfbox/io/RandomAccessFileOutputStream.java | 145 +++ src/main/java/org/pdfbox/io/package.html | 9 + src/main/java/org/pdfbox/package.html | 9 + src/main/java/org/pdfbox/pdfparser/BaseParser.java | 1369 ++++++++++++++++++++ .../pdfbox/pdfparser/PDFObjectStreamParser.java | 137 ++ src/main/java/org/pdfbox/pdfparser/PDFParser.java | 557 ++++++++ .../java/org/pdfbox/pdfparser/PDFStreamParser.java | 403 ++++++ src/main/java/org/pdfbox/pdfparser/PDFXref.java | 96 ++ src/main/java/org/pdfbox/pdfparser/package.html | 9 + src/main/java/org/pdfbox/pdfviewer/ArrayEntry.java | 83 ++ src/main/java/org/pdfbox/pdfviewer/MapEntry.java | 105 ++ .../java/org/pdfbox/pdfviewer/PDFPagePanel.java | 102 ++ .../org/pdfbox/pdfviewer/PDFTreeCellRenderer.java | 145 +++ .../java/org/pdfbox/pdfviewer/PDFTreeModel.java | 332 +++++ src/main/java/org/pdfbox/pdfviewer/PageDrawer.java | 268 ++++ .../java/org/pdfbox/pdfviewer/PageWrapper.java | 118 ++ .../org/pdfbox/pdfviewer/ReaderBottomPanel.java | 86 ++ src/main/java/org/pdfbox/pdfviewer/package.html | 9 + .../pdfbox/pdfwriter/COSStandardOutputStream.java | 180 +++ src/main/java/org/pdfbox/pdfwriter/COSWriter.java | 1091 ++++++++++++++++ .../org/pdfbox/pdfwriter/COSWriterXRefEntry.java | 165 +++ .../org/pdfbox/pdfwriter/ContentStreamWriter.java | 200 +++ src/main/java/org/pdfbox/pdfwriter/package.html | 9 + .../pdfbox/pdmodel/PDDestinationNameTreeNode.java | 90 ++ src/main/java/org/pdfbox/pdmodel/PDDocument.java | 725 +++++++++++ .../java/org/pdfbox/pdmodel/PDDocumentCatalog.java | 378 ++++++ .../org/pdfbox/pdmodel/PDDocumentInformation.java | 297 +++++ .../pdfbox/pdmodel/PDDocumentNameDictionary.java | 164 +++ .../pdmodel/PDEmbeddedFilesNameTreeNode.java | 89 ++ src/main/java/org/pdfbox/pdmodel/PDPage.java | 776 +++++++++++ src/main/java/org/pdfbox/pdmodel/PDPageNode.java | 459 +++++++ src/main/java/org/pdfbox/pdmodel/PDResources.java | 313 +++++ .../org/pdfbox/pdmodel/common/COSArrayList.java | 643 +++++++++ .../pdfbox/pdmodel/common/COSDictionaryMap.java | 278 ++++ .../org/pdfbox/pdmodel/common/COSObjectable.java | 49 + .../org/pdfbox/pdmodel/common/COSStreamArray.java | 304 +++++ .../pdfbox/pdmodel/common/DualCOSObjectable.java | 56 + .../java/org/pdfbox/pdmodel/common/PDMatrix.java | 120 ++ .../org/pdfbox/pdmodel/common/PDMemoryStream.java | 284 ++++ .../java/org/pdfbox/pdmodel/common/PDMetadata.java | 87 ++ .../org/pdfbox/pdmodel/common/PDNameTreeNode.java | 337 +++++ .../pdfbox/pdmodel/common/PDNamedTextStream.java | 137 ++ .../org/pdfbox/pdmodel/common/PDObjectStream.java | 151 +++ .../java/org/pdfbox/pdmodel/common/PDRange.java | 146 +++ .../org/pdfbox/pdmodel/common/PDRectangle.java | 295 +++++ .../java/org/pdfbox/pdmodel/common/PDStream.java | 538 ++++++++ .../org/pdfbox/pdmodel/common/PDTextStream.java | 180 +++ .../PDComplexFileSpecification.java | 326 +++++ .../common/filespecification/PDEmbeddedFile.java | 298 +++++ .../filespecification/PDFileSpecification.java | 83 ++ .../PDSimpleFileSpecification.java | 95 ++ .../pdmodel/common/filespecification/package.html | 9 + .../java/org/pdfbox/pdmodel/common/package.html | 9 + .../logicalstructure/PDMarkInfo.java | 149 +++ .../logicalstructure/PDStructureElement.java | 76 ++ .../logicalstructure/package.html | 10 + .../documentinterchange/prepress/PDBoxStyle.java | 222 ++++ .../documentinterchange/prepress/package.html | 9 + .../pdfbox/pdmodel/edit/PDPageContentStream.java | 648 +++++++++ src/main/java/org/pdfbox/pdmodel/edit/package.html | 9 + .../pdmodel/encryption/PDEncryptionDictionary.java | 193 +++ .../pdmodel/encryption/PDEncryptionManager.java | 131 ++ .../pdmodel/encryption/PDStandardEncryption.java | 416 ++++++ .../org/pdfbox/pdmodel/encryption/package.html | 9 + .../java/org/pdfbox/pdmodel/fdf/FDFAnnotation.java | 114 ++ .../java/org/pdfbox/pdmodel/fdf/FDFCatalog.java | 195 +++ .../java/org/pdfbox/pdmodel/fdf/FDFDictionary.java | 465 +++++++ .../java/org/pdfbox/pdmodel/fdf/FDFDocument.java | 377 ++++++ src/main/java/org/pdfbox/pdmodel/fdf/FDFField.java | 763 +++++++++++ .../java/org/pdfbox/pdmodel/fdf/FDFIconFit.java | 227 ++++ .../java/org/pdfbox/pdmodel/fdf/FDFJavaScript.java | 172 +++ .../pdfbox/pdmodel/fdf/FDFNamedPageReference.java | 128 ++ .../org/pdfbox/pdmodel/fdf/FDFOptionElement.java | 129 ++ src/main/java/org/pdfbox/pdmodel/fdf/FDFPage.java | 148 +++ .../java/org/pdfbox/pdmodel/fdf/FDFPageInfo.java | 85 ++ .../java/org/pdfbox/pdmodel/fdf/FDFTemplate.java | 167 +++ src/main/java/org/pdfbox/pdmodel/fdf/package.html | 9 + .../java/org/pdfbox/pdmodel/font/PDCIDFont.java | 248 ++++ .../pdfbox/pdmodel/font/PDCIDFontType0Font.java | 66 + .../pdfbox/pdmodel/font/PDCIDFontType2Font.java | 66 + src/main/java/org/pdfbox/pdmodel/font/PDFont.java | 863 ++++++++++++ .../org/pdfbox/pdmodel/font/PDFontDescriptor.java | 530 ++++++++ .../pdfbox/pdmodel/font/PDFontDescriptorAFM.java | 446 +++++++ .../pdmodel/font/PDFontDescriptorDictionary.java | 580 +++++++++ .../org/pdfbox/pdmodel/font/PDFontFactory.java | 108 ++ .../org/pdfbox/pdmodel/font/PDMMType1Font.java | 62 + .../java/org/pdfbox/pdmodel/font/PDSimpleFont.java | 239 ++++ .../org/pdfbox/pdmodel/font/PDTrueTypeFont.java | 437 +++++++ .../java/org/pdfbox/pdmodel/font/PDType0Font.java | 129 ++ .../org/pdfbox/pdmodel/font/PDType1AfmPfbFont.java | 206 +++ .../java/org/pdfbox/pdmodel/font/PDType1Font.java | 267 ++++ .../java/org/pdfbox/pdmodel/font/PDType3Font.java | 152 +++ .../org/pdfbox/pdmodel/font/Type3StreamParser.java | 607 +++++++++ src/main/java/org/pdfbox/pdmodel/font/package.html | 9 + .../pdmodel/graphics/PDExtendedGraphicsState.java | 724 +++++++++++ .../org/pdfbox/pdmodel/graphics/PDFontSetting.java | 133 ++ .../pdfbox/pdmodel/graphics/PDGraphicsState.java | 438 +++++++ .../pdfbox/pdmodel/graphics/PDLineDashPattern.java | 135 ++ .../pdfbox/pdmodel/graphics/color/PDCalGray.java | 240 ++++ .../pdfbox/pdmodel/graphics/color/PDCalRGB.java | 289 +++++ .../pdmodel/graphics/color/PDColorSpace.java | 97 ++ .../graphics/color/PDColorSpaceFactory.java | 218 ++++ .../graphics/color/PDColorSpaceInstance.java | 130 ++ .../pdmodel/graphics/color/PDDeviceCMYK.java | 137 ++ .../pdmodel/graphics/color/PDDeviceGray.java | 112 ++ .../pdfbox/pdmodel/graphics/color/PDDeviceN.java | 244 ++++ .../graphics/color/PDDeviceNAttributes.java | 126 ++ .../pdfbox/pdmodel/graphics/color/PDDeviceRGB.java | 130 ++ .../org/pdfbox/pdmodel/graphics/color/PDGamma.java | 151 +++ .../pdfbox/pdmodel/graphics/color/PDICCBased.java | 343 +++++ .../pdfbox/pdmodel/graphics/color/PDIndexed.java | 271 ++++ .../org/pdfbox/pdmodel/graphics/color/PDLab.java | 300 +++++ .../pdfbox/pdmodel/graphics/color/PDPattern.java | 122 ++ .../pdmodel/graphics/color/PDSeparation.java | 198 +++ .../pdmodel/graphics/color/PDTristimulus.java | 155 +++ .../org/pdfbox/pdmodel/graphics/color/package.html | 9 + .../java/org/pdfbox/pdmodel/graphics/package.html | 9 + .../pdfbox/pdmodel/graphics/predictor/Average.java | 81 ++ .../pdfbox/pdmodel/graphics/predictor/None.java | 104 ++ .../pdfbox/pdmodel/graphics/predictor/Paeth.java | 121 ++ .../graphics/predictor/PredictorAlgorithm.java | 336 +++++ .../org/pdfbox/pdmodel/graphics/predictor/Sub.java | 86 ++ .../org/pdfbox/pdmodel/graphics/predictor/Up.java | 100 ++ .../pdfbox/pdmodel/graphics/predictor/Uptimum.java | 153 +++ .../pdfbox/pdmodel/graphics/predictor/package.html | 10 + .../pdfbox/pdmodel/graphics/xobject/PDCcitt.java | 598 +++++++++ .../pdmodel/graphics/xobject/PDInlinedImage.java | 201 +++ .../pdfbox/pdmodel/graphics/xobject/PDJpeg.java | 156 +++ .../pdmodel/graphics/xobject/PDPixelMap.java | 236 ++++ .../pdfbox/pdmodel/graphics/xobject/PDXObject.java | 207 +++ .../pdmodel/graphics/xobject/PDXObjectForm.java | 120 ++ .../pdmodel/graphics/xobject/PDXObjectImage.java | 244 ++++ .../pdfbox/pdmodel/graphics/xobject/package.html | 9 + .../interactive/action/PDActionFactory.java | 96 ++ .../interactive/action/PDAdditionalActions.java | 106 ++ .../action/PDAnnotationAdditionalActions.java | 380 ++++++ .../action/PDDocumentCatalogAdditionalActions.java | 238 ++++ .../action/PDFormFieldAdditionalActions.java | 216 +++ .../action/PDPageAdditionalActions.java | 150 +++ .../pdfbox/pdmodel/interactive/action/package.html | 9 + .../pdmodel/interactive/action/type/PDAction.java | 187 +++ .../interactive/action/type/PDActionGoTo.java | 92 ++ .../action/type/PDActionJavaScript.java | 102 ++ .../interactive/action/type/PDActionLaunch.java | 244 ++++ .../action/type/PDActionRemoteGoTo.java | 187 +++ .../interactive/action/type/PDActionURI.java | 183 +++ .../action/type/PDWindowsLaunchParams.java | 180 +++ .../pdmodel/interactive/action/type/package.html | 9 + .../interactive/annotation/PDAnnotation.java | 503 +++++++ .../annotation/PDAnnotationRubberStamp.java | 153 +++ .../annotation/PDAnnotationUnknown.java | 54 + .../interactive/annotation/PDAnnotationWidget.java | 65 + .../annotation/PDAppearanceDictionary.java | 245 ++++ .../interactive/annotation/PDAppearanceStream.java | 146 +++ .../pdmodel/interactive/annotation/package.html | 9 + .../interactive/digitalsignature/PDSignature.java | 85 ++ .../interactive/digitalsignature/package.html | 9 + .../destination/PDDestination.java | 125 ++ .../destination/PDNamedDestination.java | 142 ++ .../destination/PDPageDestination.java | 155 +++ .../destination/PDPageFitDestination.java | 102 ++ .../destination/PDPageFitHeightDestination.java | 132 ++ .../destination/PDPageFitRectangleDestination.java | 188 +++ .../destination/PDPageFitWidthDestination.java | 134 ++ .../destination/PDPageXYZDestination.java | 159 +++ .../documentnavigation/destination/package.html | 9 + .../outline/PDDocumentOutline.java | 62 + .../documentnavigation/outline/PDOutlineItem.java | 425 ++++++ .../documentnavigation/outline/PDOutlineNode.java | 320 +++++ .../documentnavigation/outline/package.html | 9 + .../interactive/documentnavigation/package.html | 9 + .../pdmodel/interactive/form/PDAcroForm.java | 328 +++++ .../pdmodel/interactive/form/PDAppearance.java | 645 +++++++++ .../pdmodel/interactive/form/PDCheckbox.java | 187 +++ .../pdmodel/interactive/form/PDChoiceButton.java | 95 ++ .../pdmodel/interactive/form/PDChoiceField.java | 127 ++ .../pdfbox/pdmodel/interactive/form/PDField.java | 610 +++++++++ .../pdmodel/interactive/form/PDFieldFactory.java | 218 ++++ .../pdmodel/interactive/form/PDPushButton.java | 84 ++ .../interactive/form/PDRadioCollection.java | 170 +++ .../pdmodel/interactive/form/PDSignature.java | 90 ++ .../pdfbox/pdmodel/interactive/form/PDTextbox.java | 64 + .../pdmodel/interactive/form/PDUnknownField.java | 72 + .../pdmodel/interactive/form/PDVariableText.java | 324 +++++ .../pdfbox/pdmodel/interactive/form/package.html | 9 + .../interactive/pagenavigation/PDThread.java | 152 +++ .../interactive/pagenavigation/PDThreadBead.java | 234 ++++ .../interactive/pagenavigation/package.html | 9 + .../viewerpreferences/PDViewerPreferences.java | 365 ++++++ .../interactive/viewerpreferences/package.html | 9 + src/main/java/org/pdfbox/pdmodel/package.html | 9 + .../java/org/pdfbox/pdmodel/text/PDTextState.java | 286 ++++ src/main/java/org/pdfbox/pdmodel/text/package.html | 9 + .../org/pdfbox/persistence/util/COSHEXTable.java | 566 ++++++++ .../org/pdfbox/persistence/util/COSObjectKey.java | 131 ++ .../java/org/pdfbox/persistence/util/package.html | 9 + src/main/java/org/pdfbox/pfb/PfbParser.java | 211 +++ src/main/java/org/pdfbox/pfb/package.html | 9 + .../org/pdfbox/searchengine/lucene/IndexFiles.java | 308 +++++ .../searchengine/lucene/LucenePDFDocument.java | 387 ++++++ .../org/pdfbox/searchengine/lucene/package.html | 9 + src/main/java/org/pdfbox/searchengine/package.html | 9 + .../java/org/pdfbox/ttf/CMAPEncodingEntry.java | 219 ++++ src/main/java/org/pdfbox/ttf/CMAPTable.java | 122 ++ .../java/org/pdfbox/ttf/DigitalSignatureTable.java | 45 + src/main/java/org/pdfbox/ttf/GlyphData.java | 125 ++ src/main/java/org/pdfbox/ttf/GlyphTable.java | 88 ++ src/main/java/org/pdfbox/ttf/HeaderTable.java | 332 +++++ .../java/org/pdfbox/ttf/HorizontalHeaderTable.java | 332 +++++ .../org/pdfbox/ttf/HorizontalMetricsTable.java | 95 ++ .../java/org/pdfbox/ttf/IndexToLocationTable.java | 96 ++ .../java/org/pdfbox/ttf/MaximumProfileTable.java | 300 +++++ .../java/org/pdfbox/ttf/MemoryTTFDataStream.java | 231 ++++ src/main/java/org/pdfbox/ttf/NameRecord.java | 242 ++++ src/main/java/org/pdfbox/ttf/NamingTable.java | 112 ++ .../org/pdfbox/ttf/OS2WindowsMetricsTable.java | 694 ++++++++++ src/main/java/org/pdfbox/ttf/PostScriptTable.java | 304 +++++ src/main/java/org/pdfbox/ttf/RAFDataStream.java | 193 +++ src/main/java/org/pdfbox/ttf/TTFDataStream.java | 253 ++++ src/main/java/org/pdfbox/ttf/TTFParser.java | 219 ++++ src/main/java/org/pdfbox/ttf/TTFTable.java | 115 ++ src/main/java/org/pdfbox/ttf/TrueTypeFont.java | 221 ++++ src/main/java/org/pdfbox/ttf/package.html | 9 + src/main/java/org/pdfbox/util/BitFlagHelper.java | 85 ++ src/main/java/org/pdfbox/util/BoundingBox.java | 188 +++ src/main/java/org/pdfbox/util/DateConverter.java | 281 ++++ .../java/org/pdfbox/util/DefaultFileFilter.java | 285 ++++ src/main/java/org/pdfbox/util/ErrorLogger.java | 72 + src/main/java/org/pdfbox/util/ImageParameters.java | 234 ++++ src/main/java/org/pdfbox/util/Matrix.java | 350 +++++ src/main/java/org/pdfbox/util/PDFHighlighter.java | 213 +++ src/main/java/org/pdfbox/util/PDFOperator.java | 153 +++ src/main/java/org/pdfbox/util/PDFStreamEngine.java | 622 +++++++++ src/main/java/org/pdfbox/util/PDFText2HTML.java | 271 ++++ src/main/java/org/pdfbox/util/PDFTextStripper.java | 1033 +++++++++++++++ .../org/pdfbox/util/PDFTextStripperByArea.java | 165 +++ src/main/java/org/pdfbox/util/ResourceLoader.java | 169 +++ .../java/org/pdfbox/util/SimpleConfigurator.java | 68 + src/main/java/org/pdfbox/util/Splitter.java | 201 +++ src/main/java/org/pdfbox/util/TextPosition.java | 203 +++ .../org/pdfbox/util/TextPositionComparator.java | 126 ++ src/main/java/org/pdfbox/util/XMLUtil.java | 103 ++ .../java/org/pdfbox/util/operator/BeginText.java | 68 + .../java/org/pdfbox/util/operator/Concatenate.java | 106 ++ .../java/org/pdfbox/util/operator/EndText.java | 67 + .../java/org/pdfbox/util/operator/GRestore.java | 67 + src/main/java/org/pdfbox/util/operator/GSave.java | 66 + src/main/java/org/pdfbox/util/operator/Invoke.java | 113 ++ .../java/org/pdfbox/util/operator/MoveAndShow.java | 75 ++ .../java/org/pdfbox/util/operator/MoveText.java | 76 ++ .../pdfbox/util/operator/MoveTextSetLeading.java | 80 ++ .../java/org/pdfbox/util/operator/NextLine.java | 82 ++ .../pdfbox/util/operator/OperatorProcessor.java | 93 ++ .../org/pdfbox/util/operator/SetCharSpacing.java | 79 ++ .../util/operator/SetGraphicsStateParameters.java | 72 + .../util/operator/SetHorizontalTextScaling.java | 64 + .../org/pdfbox/util/operator/SetLineWidth.java | 64 + .../java/org/pdfbox/util/operator/SetMatrix.java | 90 ++ .../org/pdfbox/util/operator/SetMoveAndShow.java | 80 ++ .../util/operator/SetNonStrokingCMYKColor.java | 69 + .../util/operator/SetNonStrokingColorSpace.java | 86 ++ .../util/operator/SetNonStrokingRGBColor.java | 69 + .../pdfbox/util/operator/SetStrokingCMYKColor.java | 71 + .../util/operator/SetStrokingColorSpace.java | 89 ++ .../pdfbox/util/operator/SetStrokingRGBColor.java | 71 + .../java/org/pdfbox/util/operator/SetTextFont.java | 96 ++ .../org/pdfbox/util/operator/SetTextLeading.java | 69 + .../pdfbox/util/operator/SetTextRenderingMode.java | 64 + .../java/org/pdfbox/util/operator/SetTextRise.java | 64 + .../org/pdfbox/util/operator/SetWordSpacing.java | 68 + .../java/org/pdfbox/util/operator/ShowText.java | 73 ++ .../org/pdfbox/util/operator/ShowTextGlyph.java | 99 ++ .../java/org/pdfbox/util/operator/package.html | 9 + .../operator/pagedrawer/AppendRectangleToPath.java | 77 ++ .../util/operator/pagedrawer/BeginInlineImage.java | 114 ++ .../pdfbox/util/operator/pagedrawer/ClosePath.java | 59 + .../pdfbox/util/operator/pagedrawer/CurveTo.java | 73 ++ .../pagedrawer/CurveToReplicateFinalPoint.java | 69 + .../pagedrawer/CurveToReplicateInitialPoint.java | 76 ++ .../util/operator/pagedrawer/FillEvenOddRule.java | 71 + .../util/operator/pagedrawer/FillNonZeroRule.java | 71 + .../pdfbox/util/operator/pagedrawer/Invoke.java | 180 +++ .../pdfbox/util/operator/pagedrawer/LineTo.java | 65 + .../pdfbox/util/operator/pagedrawer/MoveTo.java | 68 + .../util/operator/pagedrawer/SetLineWidth.java | 65 + .../pagedrawer/SetNonStrokingCMYKColor.java | 64 + .../pagedrawer/SetNonStrokingColorSpace.java | 71 + .../pagedrawer/SetNonStrokingRGBColor.java | 65 + .../operator/pagedrawer/SetStrokingCMYKColor.java | 64 + .../operator/pagedrawer/SetStrokingColorSpace.java | 70 + .../operator/pagedrawer/SetStrokingRGBColor.java | 65 + .../util/operator/pagedrawer/StrokePath.java | 73 ++ .../pdfbox/util/operator/pagedrawer/package.html | 9 + src/main/java/org/pdfbox/util/package.html | 9 + 415 files changed, 78282 insertions(+) create mode 100644 src/main/java/org/pdfbox/Decrypt.java create mode 100644 src/main/java/org/pdfbox/Encrypt.java create mode 100644 src/main/java/org/pdfbox/ExportFDF.java create mode 100644 src/main/java/org/pdfbox/ExportXFDF.java create mode 100644 src/main/java/org/pdfbox/ExtractImages.java create mode 100644 src/main/java/org/pdfbox/ExtractText.java create mode 100644 src/main/java/org/pdfbox/ImportFDF.java create mode 100644 src/main/java/org/pdfbox/ImportXFDF.java create mode 100644 src/main/java/org/pdfbox/Overlay.java create mode 100644 src/main/java/org/pdfbox/PDFDebugger.java create mode 100644 src/main/java/org/pdfbox/PDFReader.java create mode 100644 src/main/java/org/pdfbox/PDFSplit.java create mode 100644 src/main/java/org/pdfbox/PDFToImage.java create mode 100644 src/main/java/org/pdfbox/PrintPDF.java create mode 100644 src/main/java/org/pdfbox/TextToPDF.java create mode 100644 src/main/java/org/pdfbox/Version.java create mode 100644 src/main/java/org/pdfbox/afmparser/AFMParser.java create mode 100644 src/main/java/org/pdfbox/afmparser/package.html create mode 100644 src/main/java/org/pdfbox/afmtypes/CharMetric.java create mode 100644 src/main/java/org/pdfbox/afmtypes/Composite.java create mode 100644 src/main/java/org/pdfbox/afmtypes/CompositePart.java create mode 100644 src/main/java/org/pdfbox/afmtypes/FontMetric.java create mode 100644 src/main/java/org/pdfbox/afmtypes/KernPair.java create mode 100644 src/main/java/org/pdfbox/afmtypes/Ligature.java create mode 100644 src/main/java/org/pdfbox/afmtypes/TrackKern.java create mode 100644 src/main/java/org/pdfbox/afmtypes/package.html create mode 100644 src/main/java/org/pdfbox/ant/PDFToTextTask.java create mode 100644 src/main/java/org/pdfbox/ant/package.html create mode 100644 src/main/java/org/pdfbox/cmapparser/CMapParser.java create mode 100644 src/main/java/org/pdfbox/cmapparser/package.html create mode 100644 src/main/java/org/pdfbox/cmaptypes/CMap.java create mode 100644 src/main/java/org/pdfbox/cmaptypes/CodespaceRange.java create mode 100644 src/main/java/org/pdfbox/cmaptypes/package.html create mode 100644 src/main/java/org/pdfbox/cos/COSArray.java create mode 100644 src/main/java/org/pdfbox/cos/COSBase.java create mode 100644 src/main/java/org/pdfbox/cos/COSBoolean.java create mode 100644 src/main/java/org/pdfbox/cos/COSDictionary.java create mode 100644 src/main/java/org/pdfbox/cos/COSDocument.java create mode 100644 src/main/java/org/pdfbox/cos/COSFloat.java create mode 100644 src/main/java/org/pdfbox/cos/COSInteger.java create mode 100644 src/main/java/org/pdfbox/cos/COSName.java create mode 100644 src/main/java/org/pdfbox/cos/COSNull.java create mode 100644 src/main/java/org/pdfbox/cos/COSNumber.java create mode 100644 src/main/java/org/pdfbox/cos/COSObject.java create mode 100644 src/main/java/org/pdfbox/cos/COSStream.java create mode 100644 src/main/java/org/pdfbox/cos/COSString.java create mode 100644 src/main/java/org/pdfbox/cos/ICOSVisitor.java create mode 100644 src/main/java/org/pdfbox/cos/package.html create mode 100644 src/main/java/org/pdfbox/encoding/AFMEncoding.java create mode 100644 src/main/java/org/pdfbox/encoding/DictionaryEncoding.java create mode 100644 src/main/java/org/pdfbox/encoding/Encoding.java create mode 100644 src/main/java/org/pdfbox/encoding/EncodingManager.java create mode 100644 src/main/java/org/pdfbox/encoding/MacRomanEncoding.java create mode 100644 src/main/java/org/pdfbox/encoding/PdfDocEncoding.java create mode 100644 src/main/java/org/pdfbox/encoding/StandardEncoding.java create mode 100644 src/main/java/org/pdfbox/encoding/WinAnsiEncoding.java create mode 100644 src/main/java/org/pdfbox/encoding/package.html create mode 100644 src/main/java/org/pdfbox/encryption/ARCFour.java create mode 100644 src/main/java/org/pdfbox/encryption/DocumentEncryption.java create mode 100644 src/main/java/org/pdfbox/encryption/PDFEncryption.java create mode 100644 src/main/java/org/pdfbox/encryption/package.html create mode 100644 src/main/java/org/pdfbox/examples/AbstractExample.java create mode 100644 src/main/java/org/pdfbox/examples/fdf/PrintFields.java create mode 100644 src/main/java/org/pdfbox/examples/fdf/SetField.java create mode 100644 src/main/java/org/pdfbox/examples/fdf/package.html create mode 100644 src/main/java/org/pdfbox/examples/package.html create mode 100644 src/main/java/org/pdfbox/examples/pdmodel/AddJavascript.java create mode 100644 src/main/java/org/pdfbox/examples/pdmodel/AddMessageToEachPage.java create mode 100644 src/main/java/org/pdfbox/examples/pdmodel/AddMetadataFromDocInfo.java create mode 100644 src/main/java/org/pdfbox/examples/pdmodel/CreateBlankPDF.java create mode 100644 src/main/java/org/pdfbox/examples/pdmodel/CreateBookmarks.java create mode 100644 src/main/java/org/pdfbox/examples/pdmodel/EmbeddedFiles.java create mode 100644 src/main/java/org/pdfbox/examples/pdmodel/HelloWorld.java create mode 100644 src/main/java/org/pdfbox/examples/pdmodel/HelloWorldTTF.java create mode 100644 src/main/java/org/pdfbox/examples/pdmodel/HelloWorldType1AfmPfb.java create mode 100644 src/main/java/org/pdfbox/examples/pdmodel/ImageToPDF.java create mode 100644 src/main/java/org/pdfbox/examples/pdmodel/PrintBookmarks.java create mode 100644 src/main/java/org/pdfbox/examples/pdmodel/PrintDocumentMetaData.java create mode 100644 src/main/java/org/pdfbox/examples/pdmodel/RemoveFirstPage.java create mode 100644 src/main/java/org/pdfbox/examples/pdmodel/ReplaceString.java create mode 100644 src/main/java/org/pdfbox/examples/pdmodel/RubberStamp.java create mode 100644 src/main/java/org/pdfbox/examples/pdmodel/ShowColorBoxes.java create mode 100644 src/main/java/org/pdfbox/examples/pdmodel/package.html create mode 100644 src/main/java/org/pdfbox/examples/persistence/AppendAndFillDoc.java create mode 100644 src/main/java/org/pdfbox/examples/persistence/AppendDoc.java create mode 100644 src/main/java/org/pdfbox/examples/persistence/CopyDoc.java create mode 100644 src/main/java/org/pdfbox/examples/persistence/FieldsDoc.java create mode 100644 src/main/java/org/pdfbox/examples/persistence/WriteDecodedDoc.java create mode 100644 src/main/java/org/pdfbox/examples/persistence/package.html create mode 100644 src/main/java/org/pdfbox/examples/signature/ShowSignature.java create mode 100644 src/main/java/org/pdfbox/examples/signature/package.html create mode 100644 src/main/java/org/pdfbox/examples/util/ExtractTextByArea.java create mode 100644 src/main/java/org/pdfbox/examples/util/PrintTextLocations.java create mode 100644 src/main/java/org/pdfbox/examples/util/package.html create mode 100644 src/main/java/org/pdfbox/exceptions/COSVisitorException.java create mode 100644 src/main/java/org/pdfbox/exceptions/CryptographyException.java create mode 100644 src/main/java/org/pdfbox/exceptions/InvalidPasswordException.java create mode 100644 src/main/java/org/pdfbox/exceptions/OutlineNotLocalException.java create mode 100644 src/main/java/org/pdfbox/exceptions/WrappedException.java create mode 100644 src/main/java/org/pdfbox/exceptions/WrappedIOException.java create mode 100644 src/main/java/org/pdfbox/exceptions/package.html create mode 100644 src/main/java/org/pdfbox/filter/ASCII85Filter.java create mode 100644 src/main/java/org/pdfbox/filter/ASCIIHexFilter.java create mode 100644 src/main/java/org/pdfbox/filter/CCITTFaxDecodeFilter.java create mode 100644 src/main/java/org/pdfbox/filter/DCTFilter.java create mode 100644 src/main/java/org/pdfbox/filter/Filter.java create mode 100644 src/main/java/org/pdfbox/filter/FilterManager.java create mode 100644 src/main/java/org/pdfbox/filter/FlateFilter.java create mode 100644 src/main/java/org/pdfbox/filter/LZWDictionary.java create mode 100644 src/main/java/org/pdfbox/filter/LZWFilter.java create mode 100644 src/main/java/org/pdfbox/filter/LZWNode.java create mode 100644 src/main/java/org/pdfbox/filter/RunLengthDecodeFilter.java create mode 100644 src/main/java/org/pdfbox/filter/package.html create mode 100644 src/main/java/org/pdfbox/io/ASCII85InputStream.java create mode 100644 src/main/java/org/pdfbox/io/ASCII85OutputStream.java create mode 100644 src/main/java/org/pdfbox/io/ByteArrayPushBackInputStream.java create mode 100644 src/main/java/org/pdfbox/io/FastByteArrayOutputStream.java create mode 100644 src/main/java/org/pdfbox/io/NBitInputStream.java create mode 100644 src/main/java/org/pdfbox/io/NBitOutputStream.java create mode 100644 src/main/java/org/pdfbox/io/PushBackInputStream.java create mode 100644 src/main/java/org/pdfbox/io/RandomAccessFileInputStream.java create mode 100644 src/main/java/org/pdfbox/io/RandomAccessFileOutputStream.java create mode 100644 src/main/java/org/pdfbox/io/package.html create mode 100644 src/main/java/org/pdfbox/package.html create mode 100644 src/main/java/org/pdfbox/pdfparser/BaseParser.java create mode 100644 src/main/java/org/pdfbox/pdfparser/PDFObjectStreamParser.java create mode 100644 src/main/java/org/pdfbox/pdfparser/PDFParser.java create mode 100644 src/main/java/org/pdfbox/pdfparser/PDFStreamParser.java create mode 100644 src/main/java/org/pdfbox/pdfparser/PDFXref.java create mode 100644 src/main/java/org/pdfbox/pdfparser/package.html create mode 100644 src/main/java/org/pdfbox/pdfviewer/ArrayEntry.java create mode 100644 src/main/java/org/pdfbox/pdfviewer/MapEntry.java create mode 100644 src/main/java/org/pdfbox/pdfviewer/PDFPagePanel.java create mode 100644 src/main/java/org/pdfbox/pdfviewer/PDFTreeCellRenderer.java create mode 100644 src/main/java/org/pdfbox/pdfviewer/PDFTreeModel.java create mode 100644 src/main/java/org/pdfbox/pdfviewer/PageDrawer.java create mode 100644 src/main/java/org/pdfbox/pdfviewer/PageWrapper.java create mode 100644 src/main/java/org/pdfbox/pdfviewer/ReaderBottomPanel.java create mode 100644 src/main/java/org/pdfbox/pdfviewer/package.html create mode 100644 src/main/java/org/pdfbox/pdfwriter/COSStandardOutputStream.java create mode 100644 src/main/java/org/pdfbox/pdfwriter/COSWriter.java create mode 100644 src/main/java/org/pdfbox/pdfwriter/COSWriterXRefEntry.java create mode 100644 src/main/java/org/pdfbox/pdfwriter/ContentStreamWriter.java create mode 100644 src/main/java/org/pdfbox/pdfwriter/package.html create mode 100644 src/main/java/org/pdfbox/pdmodel/PDDestinationNameTreeNode.java create mode 100644 src/main/java/org/pdfbox/pdmodel/PDDocument.java create mode 100644 src/main/java/org/pdfbox/pdmodel/PDDocumentCatalog.java create mode 100644 src/main/java/org/pdfbox/pdmodel/PDDocumentInformation.java create mode 100644 src/main/java/org/pdfbox/pdmodel/PDDocumentNameDictionary.java create mode 100644 src/main/java/org/pdfbox/pdmodel/PDEmbeddedFilesNameTreeNode.java create mode 100644 src/main/java/org/pdfbox/pdmodel/PDPage.java create mode 100644 src/main/java/org/pdfbox/pdmodel/PDPageNode.java create mode 100644 src/main/java/org/pdfbox/pdmodel/PDResources.java create mode 100644 src/main/java/org/pdfbox/pdmodel/common/COSArrayList.java create mode 100644 src/main/java/org/pdfbox/pdmodel/common/COSDictionaryMap.java create mode 100644 src/main/java/org/pdfbox/pdmodel/common/COSObjectable.java create mode 100644 src/main/java/org/pdfbox/pdmodel/common/COSStreamArray.java create mode 100644 src/main/java/org/pdfbox/pdmodel/common/DualCOSObjectable.java create mode 100644 src/main/java/org/pdfbox/pdmodel/common/PDMatrix.java create mode 100644 src/main/java/org/pdfbox/pdmodel/common/PDMemoryStream.java create mode 100644 src/main/java/org/pdfbox/pdmodel/common/PDMetadata.java create mode 100644 src/main/java/org/pdfbox/pdmodel/common/PDNameTreeNode.java create mode 100644 src/main/java/org/pdfbox/pdmodel/common/PDNamedTextStream.java create mode 100644 src/main/java/org/pdfbox/pdmodel/common/PDObjectStream.java create mode 100644 src/main/java/org/pdfbox/pdmodel/common/PDRange.java create mode 100644 src/main/java/org/pdfbox/pdmodel/common/PDRectangle.java create mode 100644 src/main/java/org/pdfbox/pdmodel/common/PDStream.java create mode 100644 src/main/java/org/pdfbox/pdmodel/common/PDTextStream.java create mode 100644 src/main/java/org/pdfbox/pdmodel/common/filespecification/PDComplexFileSpecification.java create mode 100644 src/main/java/org/pdfbox/pdmodel/common/filespecification/PDEmbeddedFile.java create mode 100644 src/main/java/org/pdfbox/pdmodel/common/filespecification/PDFileSpecification.java create mode 100644 src/main/java/org/pdfbox/pdmodel/common/filespecification/PDSimpleFileSpecification.java create mode 100644 src/main/java/org/pdfbox/pdmodel/common/filespecification/package.html create mode 100644 src/main/java/org/pdfbox/pdmodel/common/package.html create mode 100644 src/main/java/org/pdfbox/pdmodel/documentinterchange/logicalstructure/PDMarkInfo.java create mode 100644 src/main/java/org/pdfbox/pdmodel/documentinterchange/logicalstructure/PDStructureElement.java create mode 100644 src/main/java/org/pdfbox/pdmodel/documentinterchange/logicalstructure/package.html create mode 100644 src/main/java/org/pdfbox/pdmodel/documentinterchange/prepress/PDBoxStyle.java create mode 100644 src/main/java/org/pdfbox/pdmodel/documentinterchange/prepress/package.html create mode 100644 src/main/java/org/pdfbox/pdmodel/edit/PDPageContentStream.java create mode 100644 src/main/java/org/pdfbox/pdmodel/edit/package.html create mode 100644 src/main/java/org/pdfbox/pdmodel/encryption/PDEncryptionDictionary.java create mode 100644 src/main/java/org/pdfbox/pdmodel/encryption/PDEncryptionManager.java create mode 100644 src/main/java/org/pdfbox/pdmodel/encryption/PDStandardEncryption.java create mode 100644 src/main/java/org/pdfbox/pdmodel/encryption/package.html create mode 100644 src/main/java/org/pdfbox/pdmodel/fdf/FDFAnnotation.java create mode 100644 src/main/java/org/pdfbox/pdmodel/fdf/FDFCatalog.java create mode 100644 src/main/java/org/pdfbox/pdmodel/fdf/FDFDictionary.java create mode 100644 src/main/java/org/pdfbox/pdmodel/fdf/FDFDocument.java create mode 100644 src/main/java/org/pdfbox/pdmodel/fdf/FDFField.java create mode 100644 src/main/java/org/pdfbox/pdmodel/fdf/FDFIconFit.java create mode 100644 src/main/java/org/pdfbox/pdmodel/fdf/FDFJavaScript.java create mode 100644 src/main/java/org/pdfbox/pdmodel/fdf/FDFNamedPageReference.java create mode 100644 src/main/java/org/pdfbox/pdmodel/fdf/FDFOptionElement.java create mode 100644 src/main/java/org/pdfbox/pdmodel/fdf/FDFPage.java create mode 100644 src/main/java/org/pdfbox/pdmodel/fdf/FDFPageInfo.java create mode 100644 src/main/java/org/pdfbox/pdmodel/fdf/FDFTemplate.java create mode 100644 src/main/java/org/pdfbox/pdmodel/fdf/package.html create mode 100644 src/main/java/org/pdfbox/pdmodel/font/PDCIDFont.java create mode 100644 src/main/java/org/pdfbox/pdmodel/font/PDCIDFontType0Font.java create mode 100644 src/main/java/org/pdfbox/pdmodel/font/PDCIDFontType2Font.java create mode 100644 src/main/java/org/pdfbox/pdmodel/font/PDFont.java create mode 100644 src/main/java/org/pdfbox/pdmodel/font/PDFontDescriptor.java create mode 100644 src/main/java/org/pdfbox/pdmodel/font/PDFontDescriptorAFM.java create mode 100644 src/main/java/org/pdfbox/pdmodel/font/PDFontDescriptorDictionary.java create mode 100644 src/main/java/org/pdfbox/pdmodel/font/PDFontFactory.java create mode 100644 src/main/java/org/pdfbox/pdmodel/font/PDMMType1Font.java create mode 100644 src/main/java/org/pdfbox/pdmodel/font/PDSimpleFont.java create mode 100644 src/main/java/org/pdfbox/pdmodel/font/PDTrueTypeFont.java create mode 100644 src/main/java/org/pdfbox/pdmodel/font/PDType0Font.java create mode 100644 src/main/java/org/pdfbox/pdmodel/font/PDType1AfmPfbFont.java create mode 100644 src/main/java/org/pdfbox/pdmodel/font/PDType1Font.java create mode 100644 src/main/java/org/pdfbox/pdmodel/font/PDType3Font.java create mode 100644 src/main/java/org/pdfbox/pdmodel/font/Type3StreamParser.java create mode 100644 src/main/java/org/pdfbox/pdmodel/font/package.html create mode 100644 src/main/java/org/pdfbox/pdmodel/graphics/PDExtendedGraphicsState.java create mode 100644 src/main/java/org/pdfbox/pdmodel/graphics/PDFontSetting.java create mode 100644 src/main/java/org/pdfbox/pdmodel/graphics/PDGraphicsState.java create mode 100644 src/main/java/org/pdfbox/pdmodel/graphics/PDLineDashPattern.java create mode 100644 src/main/java/org/pdfbox/pdmodel/graphics/color/PDCalGray.java create mode 100644 src/main/java/org/pdfbox/pdmodel/graphics/color/PDCalRGB.java create mode 100644 src/main/java/org/pdfbox/pdmodel/graphics/color/PDColorSpace.java create mode 100644 src/main/java/org/pdfbox/pdmodel/graphics/color/PDColorSpaceFactory.java create mode 100644 src/main/java/org/pdfbox/pdmodel/graphics/color/PDColorSpaceInstance.java create mode 100644 src/main/java/org/pdfbox/pdmodel/graphics/color/PDDeviceCMYK.java create mode 100644 src/main/java/org/pdfbox/pdmodel/graphics/color/PDDeviceGray.java create mode 100644 src/main/java/org/pdfbox/pdmodel/graphics/color/PDDeviceN.java create mode 100644 src/main/java/org/pdfbox/pdmodel/graphics/color/PDDeviceNAttributes.java create mode 100644 src/main/java/org/pdfbox/pdmodel/graphics/color/PDDeviceRGB.java create mode 100644 src/main/java/org/pdfbox/pdmodel/graphics/color/PDGamma.java create mode 100644 src/main/java/org/pdfbox/pdmodel/graphics/color/PDICCBased.java create mode 100644 src/main/java/org/pdfbox/pdmodel/graphics/color/PDIndexed.java create mode 100644 src/main/java/org/pdfbox/pdmodel/graphics/color/PDLab.java create mode 100644 src/main/java/org/pdfbox/pdmodel/graphics/color/PDPattern.java create mode 100644 src/main/java/org/pdfbox/pdmodel/graphics/color/PDSeparation.java create mode 100644 src/main/java/org/pdfbox/pdmodel/graphics/color/PDTristimulus.java create mode 100644 src/main/java/org/pdfbox/pdmodel/graphics/color/package.html create mode 100644 src/main/java/org/pdfbox/pdmodel/graphics/package.html create mode 100644 src/main/java/org/pdfbox/pdmodel/graphics/predictor/Average.java create mode 100644 src/main/java/org/pdfbox/pdmodel/graphics/predictor/None.java create mode 100644 src/main/java/org/pdfbox/pdmodel/graphics/predictor/Paeth.java create mode 100644 src/main/java/org/pdfbox/pdmodel/graphics/predictor/PredictorAlgorithm.java create mode 100644 src/main/java/org/pdfbox/pdmodel/graphics/predictor/Sub.java create mode 100644 src/main/java/org/pdfbox/pdmodel/graphics/predictor/Up.java create mode 100644 src/main/java/org/pdfbox/pdmodel/graphics/predictor/Uptimum.java create mode 100644 src/main/java/org/pdfbox/pdmodel/graphics/predictor/package.html create mode 100644 src/main/java/org/pdfbox/pdmodel/graphics/xobject/PDCcitt.java create mode 100644 src/main/java/org/pdfbox/pdmodel/graphics/xobject/PDInlinedImage.java create mode 100644 src/main/java/org/pdfbox/pdmodel/graphics/xobject/PDJpeg.java create mode 100644 src/main/java/org/pdfbox/pdmodel/graphics/xobject/PDPixelMap.java create mode 100644 src/main/java/org/pdfbox/pdmodel/graphics/xobject/PDXObject.java create mode 100644 src/main/java/org/pdfbox/pdmodel/graphics/xobject/PDXObjectForm.java create mode 100644 src/main/java/org/pdfbox/pdmodel/graphics/xobject/PDXObjectImage.java create mode 100644 src/main/java/org/pdfbox/pdmodel/graphics/xobject/package.html create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/action/PDActionFactory.java create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/action/PDAdditionalActions.java create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/action/PDAnnotationAdditionalActions.java create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/action/PDDocumentCatalogAdditionalActions.java create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/action/PDFormFieldAdditionalActions.java create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/action/PDPageAdditionalActions.java create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/action/package.html create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/action/type/PDAction.java create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/action/type/PDActionGoTo.java create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/action/type/PDActionJavaScript.java create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/action/type/PDActionLaunch.java create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/action/type/PDActionRemoteGoTo.java create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/action/type/PDActionURI.java create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/action/type/PDWindowsLaunchParams.java create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/action/type/package.html create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/annotation/PDAnnotation.java create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/annotation/PDAnnotationRubberStamp.java create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/annotation/PDAnnotationUnknown.java create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/annotation/PDAnnotationWidget.java create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/annotation/PDAppearanceDictionary.java create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/annotation/PDAppearanceStream.java create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/annotation/package.html create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/digitalsignature/PDSignature.java create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/digitalsignature/package.html create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/destination/PDDestination.java create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/destination/PDNamedDestination.java create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/destination/PDPageDestination.java create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/destination/PDPageFitDestination.java create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/destination/PDPageFitHeightDestination.java create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/destination/PDPageFitRectangleDestination.java create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/destination/PDPageFitWidthDestination.java create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/destination/PDPageXYZDestination.java create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/destination/package.html create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/outline/PDDocumentOutline.java create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/outline/PDOutlineItem.java create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/outline/PDOutlineNode.java create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/outline/package.html create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/package.html create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/form/PDAcroForm.java create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/form/PDAppearance.java create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/form/PDCheckbox.java create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/form/PDChoiceButton.java create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/form/PDChoiceField.java create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/form/PDField.java create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/form/PDFieldFactory.java create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/form/PDPushButton.java create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/form/PDRadioCollection.java create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/form/PDSignature.java create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/form/PDTextbox.java create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/form/PDUnknownField.java create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/form/PDVariableText.java create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/form/package.html create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/pagenavigation/PDThread.java create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/pagenavigation/PDThreadBead.java create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/pagenavigation/package.html create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/viewerpreferences/PDViewerPreferences.java create mode 100644 src/main/java/org/pdfbox/pdmodel/interactive/viewerpreferences/package.html create mode 100644 src/main/java/org/pdfbox/pdmodel/package.html create mode 100644 src/main/java/org/pdfbox/pdmodel/text/PDTextState.java create mode 100644 src/main/java/org/pdfbox/pdmodel/text/package.html create mode 100644 src/main/java/org/pdfbox/persistence/util/COSHEXTable.java create mode 100644 src/main/java/org/pdfbox/persistence/util/COSObjectKey.java create mode 100644 src/main/java/org/pdfbox/persistence/util/package.html create mode 100644 src/main/java/org/pdfbox/pfb/PfbParser.java create mode 100644 src/main/java/org/pdfbox/pfb/package.html create mode 100644 src/main/java/org/pdfbox/searchengine/lucene/IndexFiles.java create mode 100644 src/main/java/org/pdfbox/searchengine/lucene/LucenePDFDocument.java create mode 100644 src/main/java/org/pdfbox/searchengine/lucene/package.html create mode 100644 src/main/java/org/pdfbox/searchengine/package.html create mode 100644 src/main/java/org/pdfbox/ttf/CMAPEncodingEntry.java create mode 100644 src/main/java/org/pdfbox/ttf/CMAPTable.java create mode 100644 src/main/java/org/pdfbox/ttf/DigitalSignatureTable.java create mode 100644 src/main/java/org/pdfbox/ttf/GlyphData.java create mode 100644 src/main/java/org/pdfbox/ttf/GlyphTable.java create mode 100644 src/main/java/org/pdfbox/ttf/HeaderTable.java create mode 100644 src/main/java/org/pdfbox/ttf/HorizontalHeaderTable.java create mode 100644 src/main/java/org/pdfbox/ttf/HorizontalMetricsTable.java create mode 100644 src/main/java/org/pdfbox/ttf/IndexToLocationTable.java create mode 100644 src/main/java/org/pdfbox/ttf/MaximumProfileTable.java create mode 100644 src/main/java/org/pdfbox/ttf/MemoryTTFDataStream.java create mode 100644 src/main/java/org/pdfbox/ttf/NameRecord.java create mode 100644 src/main/java/org/pdfbox/ttf/NamingTable.java create mode 100644 src/main/java/org/pdfbox/ttf/OS2WindowsMetricsTable.java create mode 100644 src/main/java/org/pdfbox/ttf/PostScriptTable.java create mode 100644 src/main/java/org/pdfbox/ttf/RAFDataStream.java create mode 100644 src/main/java/org/pdfbox/ttf/TTFDataStream.java create mode 100644 src/main/java/org/pdfbox/ttf/TTFParser.java create mode 100644 src/main/java/org/pdfbox/ttf/TTFTable.java create mode 100644 src/main/java/org/pdfbox/ttf/TrueTypeFont.java create mode 100644 src/main/java/org/pdfbox/ttf/package.html create mode 100644 src/main/java/org/pdfbox/util/BitFlagHelper.java create mode 100644 src/main/java/org/pdfbox/util/BoundingBox.java create mode 100644 src/main/java/org/pdfbox/util/DateConverter.java create mode 100644 src/main/java/org/pdfbox/util/DefaultFileFilter.java create mode 100644 src/main/java/org/pdfbox/util/ErrorLogger.java create mode 100644 src/main/java/org/pdfbox/util/ImageParameters.java create mode 100644 src/main/java/org/pdfbox/util/Matrix.java create mode 100644 src/main/java/org/pdfbox/util/PDFHighlighter.java create mode 100644 src/main/java/org/pdfbox/util/PDFOperator.java create mode 100644 src/main/java/org/pdfbox/util/PDFStreamEngine.java create mode 100644 src/main/java/org/pdfbox/util/PDFText2HTML.java create mode 100644 src/main/java/org/pdfbox/util/PDFTextStripper.java create mode 100644 src/main/java/org/pdfbox/util/PDFTextStripperByArea.java create mode 100644 src/main/java/org/pdfbox/util/ResourceLoader.java create mode 100644 src/main/java/org/pdfbox/util/SimpleConfigurator.java create mode 100644 src/main/java/org/pdfbox/util/Splitter.java create mode 100644 src/main/java/org/pdfbox/util/TextPosition.java create mode 100644 src/main/java/org/pdfbox/util/TextPositionComparator.java create mode 100644 src/main/java/org/pdfbox/util/XMLUtil.java create mode 100644 src/main/java/org/pdfbox/util/operator/BeginText.java create mode 100644 src/main/java/org/pdfbox/util/operator/Concatenate.java create mode 100644 src/main/java/org/pdfbox/util/operator/EndText.java create mode 100644 src/main/java/org/pdfbox/util/operator/GRestore.java create mode 100644 src/main/java/org/pdfbox/util/operator/GSave.java create mode 100644 src/main/java/org/pdfbox/util/operator/Invoke.java create mode 100644 src/main/java/org/pdfbox/util/operator/MoveAndShow.java create mode 100644 src/main/java/org/pdfbox/util/operator/MoveText.java create mode 100644 src/main/java/org/pdfbox/util/operator/MoveTextSetLeading.java create mode 100644 src/main/java/org/pdfbox/util/operator/NextLine.java create mode 100644 src/main/java/org/pdfbox/util/operator/OperatorProcessor.java create mode 100644 src/main/java/org/pdfbox/util/operator/SetCharSpacing.java create mode 100644 src/main/java/org/pdfbox/util/operator/SetGraphicsStateParameters.java create mode 100644 src/main/java/org/pdfbox/util/operator/SetHorizontalTextScaling.java create mode 100644 src/main/java/org/pdfbox/util/operator/SetLineWidth.java create mode 100644 src/main/java/org/pdfbox/util/operator/SetMatrix.java create mode 100644 src/main/java/org/pdfbox/util/operator/SetMoveAndShow.java create mode 100644 src/main/java/org/pdfbox/util/operator/SetNonStrokingCMYKColor.java create mode 100644 src/main/java/org/pdfbox/util/operator/SetNonStrokingColorSpace.java create mode 100644 src/main/java/org/pdfbox/util/operator/SetNonStrokingRGBColor.java create mode 100644 src/main/java/org/pdfbox/util/operator/SetStrokingCMYKColor.java create mode 100644 src/main/java/org/pdfbox/util/operator/SetStrokingColorSpace.java create mode 100644 src/main/java/org/pdfbox/util/operator/SetStrokingRGBColor.java create mode 100644 src/main/java/org/pdfbox/util/operator/SetTextFont.java create mode 100644 src/main/java/org/pdfbox/util/operator/SetTextLeading.java create mode 100644 src/main/java/org/pdfbox/util/operator/SetTextRenderingMode.java create mode 100644 src/main/java/org/pdfbox/util/operator/SetTextRise.java create mode 100644 src/main/java/org/pdfbox/util/operator/SetWordSpacing.java create mode 100644 src/main/java/org/pdfbox/util/operator/ShowText.java create mode 100644 src/main/java/org/pdfbox/util/operator/ShowTextGlyph.java create mode 100644 src/main/java/org/pdfbox/util/operator/package.html create mode 100644 src/main/java/org/pdfbox/util/operator/pagedrawer/AppendRectangleToPath.java create mode 100644 src/main/java/org/pdfbox/util/operator/pagedrawer/BeginInlineImage.java create mode 100644 src/main/java/org/pdfbox/util/operator/pagedrawer/ClosePath.java create mode 100644 src/main/java/org/pdfbox/util/operator/pagedrawer/CurveTo.java create mode 100644 src/main/java/org/pdfbox/util/operator/pagedrawer/CurveToReplicateFinalPoint.java create mode 100644 src/main/java/org/pdfbox/util/operator/pagedrawer/CurveToReplicateInitialPoint.java create mode 100644 src/main/java/org/pdfbox/util/operator/pagedrawer/FillEvenOddRule.java create mode 100644 src/main/java/org/pdfbox/util/operator/pagedrawer/FillNonZeroRule.java create mode 100644 src/main/java/org/pdfbox/util/operator/pagedrawer/Invoke.java create mode 100644 src/main/java/org/pdfbox/util/operator/pagedrawer/LineTo.java create mode 100644 src/main/java/org/pdfbox/util/operator/pagedrawer/MoveTo.java create mode 100644 src/main/java/org/pdfbox/util/operator/pagedrawer/SetLineWidth.java create mode 100644 src/main/java/org/pdfbox/util/operator/pagedrawer/SetNonStrokingCMYKColor.java create mode 100644 src/main/java/org/pdfbox/util/operator/pagedrawer/SetNonStrokingColorSpace.java create mode 100644 src/main/java/org/pdfbox/util/operator/pagedrawer/SetNonStrokingRGBColor.java create mode 100644 src/main/java/org/pdfbox/util/operator/pagedrawer/SetStrokingCMYKColor.java create mode 100644 src/main/java/org/pdfbox/util/operator/pagedrawer/SetStrokingColorSpace.java create mode 100644 src/main/java/org/pdfbox/util/operator/pagedrawer/SetStrokingRGBColor.java create mode 100644 src/main/java/org/pdfbox/util/operator/pagedrawer/StrokePath.java create mode 100644 src/main/java/org/pdfbox/util/operator/pagedrawer/package.html create mode 100644 src/main/java/org/pdfbox/util/package.html (limited to 'src/main/java/org') diff --git a/src/main/java/org/pdfbox/Decrypt.java b/src/main/java/org/pdfbox/Decrypt.java new file mode 100644 index 0000000..b338552 --- /dev/null +++ b/src/main/java/org/pdfbox/Decrypt.java @@ -0,0 +1,122 @@ +/** + * Copyright (c) 2003-2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox; + +import java.io.IOException; + +import org.pdfbox.pdmodel.PDDocument; + +/** + * This will read a document from the filesystem, decrypt it and and then write + * the results to the filesystem.

+ * + * usage: java org.pdfbox.Decrypt <password> <inputfile> <outputfile> + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.3 $ + */ +public class Decrypt +{ + + /** + * This is the entry point for the application. + * + * @param args The command-line arguments. + * + * @throws Exception If there is an error decrypting the document. + */ + public static void main( String[] args ) throws Exception + { + Decrypt decrypt = new Decrypt(); + decrypt.decrypt( args ); + } + + private void decrypt( String[] args ) throws Exception + { + if( args.length < 2 || args.length > 3 ) + { + usage(); + } + else + { + String password = args[0]; + String infile = args[1]; + String outfile = args[1]; + if( args.length == 3 ) + { + outfile = args[2]; + } + + + PDDocument document = null; + + try + { + document = PDDocument.load( infile ); + + if( document.isEncrypted() ) + { + if( document.isOwnerPassword( password ) ) + { + document.decrypt( password ); + document.save( outfile ); + } + else + { + throw new IOException( + "Error: You are only allowed to decrypt a document with the owner password." ); + } + } + else + { + System.err.println( "Error: Document is not encrypted." ); + } + } + finally + { + if( document != null ) + { + document.close(); + } + } + } + } + + /** + * This will print a usage message. + */ + private static void usage() + { + System.err.println( "usage: java org.pdfbox.Decrypt " + + " [outputfile]" ); + } + +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/Encrypt.java b/src/main/java/org/pdfbox/Encrypt.java new file mode 100644 index 0000000..9038e61 --- /dev/null +++ b/src/main/java/org/pdfbox/Encrypt.java @@ -0,0 +1,234 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox; + +import org.pdfbox.pdmodel.PDDocument; + +import org.pdfbox.pdmodel.encryption.PDStandardEncryption; +import org.pdfbox.pdmodel.encryption.PDEncryptionDictionary; + +/** + * This will read a document from the filesystem, encrypt it and and then write + * the results to the filesystem.

+ * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.5 $ + */ +public class Encrypt +{ + + /** + * This is the entry point for the application. + * + * @param args The command-line arguments. + * + * @throws Exception If there is an error decrypting the document. + */ + public static void main( String[] args ) throws Exception + { + Encrypt encrypt = new Encrypt(); + encrypt.encrypt( args ); + } + + private void encrypt( String[] args ) throws Exception + { + if( args.length < 1 ) + { + usage(); + } + else + { + String infile = null; + String outfile = null; + String userPassword = ""; + String ownerPassword = ""; + + PDDocument document = null; + + try + { + + PDStandardEncryption enc = new PDStandardEncryption(); + enc.setVersion( PDEncryptionDictionary.VERSION1_40_BIT_ALGORITHM ); + enc.setRevision( PDStandardEncryption.REVISION2 ); + for( int i=0; i [outputfile]" ); + System.err.println( " -O Set the owner password" ); + System.err.println( " -U Set the user password" ); + System.err.println( " -canAssemble Set the assemble permission" ); + System.err.println( " -canExtractContent Set the extraction permission" ); + System.err.println( " -canExtractForAccessibility Set the extraction permission" ); + System.err.println( " -canFillInForm Set the fill in form permission" ); + System.err.println( " -canModify Set the modify permission" ); + System.err.println( " -canModifyAnnotations Set the modify annots permission" ); + System.err.println( " -canPrint Set the print permission" ); + System.err.println( " -canPrintDegraded Set the print degraded permission" ); + System.err.println( " -keyLength The length of the key in bits(40)" ); + System.err.println( " -version <0|1|2|3|4> The encryption version(1)" ); + System.err.println( " 0 - Undocumented/Unpublished" ); + System.err.println( " 1 - Allows for 40 bit encryption" ); + System.err.println( " 2 - Allows for variable length encryption" ); + System.err.println( " 3 - Unpublished but allows for key lengths from 40 to 128" ); + System.err.println( " 4 - Security handler defines encryption" ); + System.err.println( " -revision <2|3|4> The encryption revision(2)" ); + System.err.println( " 2 - version less than 2" ); + System.err.println( " 3 - version 2 or 3 or uses a revision 3 permission" ); + System.err.println( " 4 - version of 4" ); + System.err.println( "\nNote: By default all permissions are set to true!" ); + System.exit( 1 ); + } + +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/ExportFDF.java b/src/main/java/org/pdfbox/ExportFDF.java new file mode 100644 index 0000000..d8f6246 --- /dev/null +++ b/src/main/java/org/pdfbox/ExportFDF.java @@ -0,0 +1,155 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox; + +import java.io.IOException; + +import org.pdfbox.pdmodel.PDDocument; + +import org.pdfbox.pdmodel.interactive.form.PDAcroForm; + +import org.pdfbox.pdmodel.fdf.FDFDocument; + +/** + * This example will take a PDF document and fill the fields with data from the + * FDF fields. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.2 $ + */ +public class ExportFDF +{ + /** + * Creates a new instance of ImportFDF. + */ + public ExportFDF() + { + } + + /** + * This will import an fdf document and write out another pdf. + *
+ * see usage() for commandline + * + * @param args command line arguments + * + * @throws Exception If there is an error importing the FDF document. + */ + public static void main(String[] args) throws Exception + { + ExportFDF exporter = new ExportFDF(); + exporter.exportFDF( args ); + } + + private void exportFDF( String[] args ) throws Exception + { + PDDocument pdf = null; + FDFDocument fdf = null; + + try + { + if( args.length != 1 && args.length != 2 ) + { + usage(); + } + else + { + pdf = PDDocument.load( args[0] ); + PDAcroForm form = pdf.getDocumentCatalog().getAcroForm(); + if( form == null ) + { + System.err.println( "Error: This PDF does not contain a form." ); + } + else + { + String fdfName = null; + if( args.length == 2 ) + { + fdfName = args[1]; + } + else + { + if( args[0].length() > 4 ) + { + fdfName = args[0].substring( 0, args[0].length() -4 ) + ".fdf"; + } + } + fdf = form.exportFDF(); + fdf.save( fdfName ); + } + } + } + finally + { + close( fdf ); + close( pdf ); + } + } + + /** + * This will print out a message telling how to use this example. + */ + private static void usage() + { + System.err.println( "usage: org.pdfbox.ExortFDF [output-fdf-file]" ); + System.err.println( " [output-fdf-file] - Default is pdf name, test.pdf->test.fdf" ); + } + + /** + * Close the document. + * + * @param doc The doc to close. + * + * @throws IOException If there is an error closing the document. + */ + public void close( FDFDocument doc ) throws IOException + { + if( doc != null ) + { + doc.close(); + } + } + + /** + * Close the document. + * + * @param doc The doc to close. + * + * @throws IOException If there is an error closing the document. + */ + public void close( PDDocument doc ) throws IOException + { + if( doc != null ) + { + doc.close(); + } + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/ExportXFDF.java b/src/main/java/org/pdfbox/ExportXFDF.java new file mode 100644 index 0000000..a1cfcf2 --- /dev/null +++ b/src/main/java/org/pdfbox/ExportXFDF.java @@ -0,0 +1,155 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox; + +import java.io.IOException; + +import org.pdfbox.pdmodel.PDDocument; + +import org.pdfbox.pdmodel.interactive.form.PDAcroForm; + +import org.pdfbox.pdmodel.fdf.FDFDocument; + +/** + * This example will take a PDF document and fill the fields with data from the + * FDF fields. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.2 $ + */ +public class ExportXFDF +{ + /** + * Creates a new instance of ImportFDF. + */ + public ExportXFDF() + { + } + + /** + * This will import an fdf document and write out another pdf. + *
+ * see usage() for commandline + * + * @param args command line arguments + * + * @throws Exception If there is an error importing the FDF document. + */ + public static void main(String[] args) throws Exception + { + ExportXFDF exporter = new ExportXFDF(); + exporter.exportXFDF( args ); + } + + private void exportXFDF( String[] args ) throws Exception + { + PDDocument pdf = null; + FDFDocument fdf = null; + + try + { + if( args.length != 1 && args.length != 2 ) + { + usage(); + } + else + { + pdf = PDDocument.load( args[0] ); + PDAcroForm form = pdf.getDocumentCatalog().getAcroForm(); + if( form == null ) + { + System.err.println( "Error: This PDF does not contain a form." ); + } + else + { + String fdfName = null; + if( args.length == 2 ) + { + fdfName = args[1]; + } + else + { + if( args[0].length() > 4 ) + { + fdfName = args[0].substring( 0, args[0].length() -4 ) + ".xfdf"; + } + } + fdf = form.exportFDF(); + fdf.saveXFDF( fdfName ); + } + } + } + finally + { + close( fdf ); + close( pdf ); + } + } + + /** + * This will print out a message telling how to use this example. + */ + private static void usage() + { + System.err.println( "usage: org.pdfbox.ExortXFDF [output-xfdf-file]" ); + System.err.println( " [output-xfdf-file] - Default is pdf name, test.pdf->test.xfdf" ); + } + + /** + * Close the document. + * + * @param doc The doc to close. + * + * @throws IOException If there is an error closing the document. + */ + public void close( FDFDocument doc ) throws IOException + { + if( doc != null ) + { + doc.close(); + } + } + + /** + * Close the document. + * + * @param doc The doc to close. + * + * @throws IOException If there is an error closing the document. + */ + public void close( PDDocument doc ) throws IOException + { + if( doc != null ) + { + doc.close(); + } + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/ExtractImages.java b/src/main/java/org/pdfbox/ExtractImages.java new file mode 100644 index 0000000..a8e46ee --- /dev/null +++ b/src/main/java/org/pdfbox/ExtractImages.java @@ -0,0 +1,210 @@ +/** + * Copyright (c) 2003-2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox; + +import java.io.File; +import java.io.IOException; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.pdfbox.pdmodel.PDDocument; +import org.pdfbox.pdmodel.PDPage; +import org.pdfbox.pdmodel.PDResources; + +import org.pdfbox.pdmodel.encryption.PDEncryptionDictionary; +import org.pdfbox.pdmodel.encryption.PDStandardEncryption; +import org.pdfbox.pdmodel.graphics.xobject.PDXObjectImage; + +/** + * This will read a read pdf and extract images.

+ * + * usage: java org.pdfbox.ExtractImages <pdffile> <password> [imageprefix] + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.3 $ + */ +public class ExtractImages +{ + private int imageCounter = 1; + + private static final String PASSWORD = "-password"; + private static final String PREFIX = "-prefix"; + + /** + * This is the entry point for the application. + * + * @param args The command-line arguments. + * + * @throws Exception If there is an error decrypting the document. + */ + public static void main( String[] args ) throws Exception + { + ExtractImages extractor = new ExtractImages(); + extractor.extractImages( args ); + } + + private void extractImages( String[] args ) throws Exception + { + if( args.length < 1 || args.length > 3 ) + { + usage(); + } + else + { + String pdfFile = null; + String password = ""; + String prefix = null; + for( int i=0; i= args.length ) + { + usage(); + } + password = args[i]; + } + else if( args[i].equals( PREFIX ) ) + { + i++; + if( i >= args.length ) + { + usage(); + } + prefix = args[i]; + } + else + { + if( pdfFile == null ) + { + pdfFile = args[i]; + } + } + } + if( prefix == null && pdfFile.length() >4 ) + { + prefix = pdfFile.substring( 0, pdfFile.length() -4 ); + } + + PDDocument document = null; + + try + { + document = PDDocument.load( pdfFile ); + + if( document.isEncrypted() ) + { + if( document.isOwnerPassword( password ) ) + { + document.decrypt( password ); + } + else + { + throw new IOException( + "Error: You are only allowed to extract images with the owner password." ); + } + } + + PDEncryptionDictionary encDictionary = document.getEncryptionDictionary(); + + //only care about standard encryption and if it was decrypted with the + //user password + if( encDictionary instanceof PDStandardEncryption && + !document.wasDecryptedWithOwnerPassword() ) + { + PDStandardEncryption stdEncryption = (PDStandardEncryption)encDictionary; + if( !stdEncryption.canExtractContent() ) + { + throw new IOException( "You do not have permission to extract images." ); + } + } + + List pages = document.getDocumentCatalog().getAllPages(); + Iterator iter = pages.iterator(); + while( iter.hasNext() ) + { + PDPage page = (PDPage)iter.next(); + PDResources resources = page.getResources(); + Map images = resources.getImages(); + if( images != null ) + { + Iterator imageIter = images.keySet().iterator(); + while( imageIter.hasNext() ) + { + String key = (String)imageIter.next(); + PDXObjectImage image = (PDXObjectImage)images.get( key ); + String name = getUniqueFileName( key, image.getSuffix() ); + System.out.println( "Writing image:" + name ); + image.write2file( name ); + } + } + } + } + finally + { + if( document != null ) + { + document.close(); + } + } + } + } + + private String getUniqueFileName( String prefix, String suffix ) + { + String uniqueName = null; + File f = null; + while( f == null || f.exists() ) + { + uniqueName = prefix + "-" + imageCounter; + f = new File( uniqueName + "." + suffix ); + imageCounter++; + } + return uniqueName; + } + + /** + * This will print the usage requirements and exit. + */ + private static void usage() + { + System.err.println( "Usage: java org.pdfbox.ExtractImages [OPTIONS] \n" + + " -password Password to decrypt document\n" + + " -suffix Image suffix(default to pdf name)\n" + + " The PDF document to use\n" + ); + System.exit( 1 ); + } + +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/ExtractText.java b/src/main/java/org/pdfbox/ExtractText.java new file mode 100644 index 0000000..5f5a328 --- /dev/null +++ b/src/main/java/org/pdfbox/ExtractText.java @@ -0,0 +1,270 @@ +/** + * Copyright (c) 2003-2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox; + +import java.io.FileOutputStream; +import java.io.OutputStreamWriter; +import java.io.Writer; + +import org.pdfbox.exceptions.InvalidPasswordException; + +import org.pdfbox.pdmodel.PDDocument; + +import org.pdfbox.util.PDFText2HTML; +import org.pdfbox.util.PDFTextStripper; + +import org.apache.log4j.Logger; + +/** + * This is the main program that simply parses the pdf document and transforms it + * into text. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.9 $ + */ +public class ExtractText +{ + private static final Logger LOG = Logger.getLogger( ExtractText.class ); + + /** + * This is the default encoding of the text to be output. + */ + public static final String DEFAULT_ENCODING = + null; + //"ISO-8859-1"; + //"ISO-8859-6"; //arabic + //"US-ASCII"; + //"UTF-8"; + //"UTF-16"; + //"UTF-16BE"; + //"UTF-16LE"; + + + private static final String PASSWORD = "-password"; + private static final String ENCODING = "-encoding"; + private static final String CONSOLE = "-console"; + private static final String START_PAGE = "-startPage"; + private static final String END_PAGE = "-endPage"; + private static final String SORT = "-sort"; + private static final String HTML = "-html"; // jjb - added simple HTML output + + /** + * private constructor. + */ + private ExtractText() + { + //static class + } + + /** + * Infamous main method. + * + * @param args Command line arguments, should be one and a reference to a file. + * + * @throws Exception If there is an error parsing the document. + */ + public static void main( String[] args ) throws Exception + { + boolean toConsole = false; + boolean toHTML = false; + boolean sort = false; + String password = ""; + String encoding = DEFAULT_ENCODING; + String pdfFile = null; + String textFile = null; + int startPage = 1; + int endPage = Integer.MAX_VALUE; + for( int i=0; i= args.length ) + { + usage(); + } + password = args[i]; + } + else if( args[i].equals( ENCODING ) ) + { + i++; + if( i >= args.length ) + { + usage(); + } + encoding = args[i]; + } + else if( args[i].equals( START_PAGE ) ) + { + i++; + if( i >= args.length ) + { + usage(); + } + startPage = Integer.parseInt( args[i] ); + } + else if( args[i].equals( HTML ) ) + { + toHTML = true; + } + else if( args[i].equals( SORT ) ) + { + sort = true; + } + else if( args[i].equals( END_PAGE ) ) + { + i++; + if( i >= args.length ) + { + usage(); + } + endPage = Integer.parseInt( args[i] ); + } + else if( args[i].equals( CONSOLE ) ) + { + toConsole = true; + } + else + { + if( pdfFile == null ) + { + pdfFile = args[i]; + } + else + { + textFile = args[i]; + } + } + } + + if( pdfFile == null ) + { + usage(); + } + + if( textFile == null && pdfFile.length() >4 ) + { + textFile = pdfFile.substring( 0, pdfFile.length() -4 ) + ".txt"; + } + + Writer output = null; + PDDocument document = null; + try + { + document = PDDocument.load( pdfFile ); + + //document.print(); + if( document.isEncrypted() ) + { + try + { + document.decrypt( password ); + } + catch( InvalidPasswordException e ) + { + if( args.length == 4 )//they supplied the wrong password + { + System.err.println( "Error: The supplied password is incorrect." ); + System.exit( 2 ); + } + else + { + //they didn't suppply a password and the default of "" was wrong. + System.err.println( "Error: The document is encrypted." ); + usage(); + } + } + } + if( toConsole ) + { + output = new OutputStreamWriter( System.out ); + } + else + { + if( encoding != null ) + { + output = new OutputStreamWriter( + new FileOutputStream( textFile ), encoding ); + } + else + { + //use default encoding + output = new OutputStreamWriter( + new FileOutputStream( textFile ) ); + } + } + + PDFTextStripper stripper = null; + if(toHTML) + { + stripper = new PDFText2HTML(); + } + else + { + stripper = new PDFTextStripper(); + } + stripper.setSortByPosition( sort ); + stripper.setStartPage( startPage ); + stripper.setEndPage( endPage ); + stripper.writeText( document, output ); + } + finally + { + if( output != null ) + { + output.close(); + } + if( document != null ) + { + document.close(); + } + } + } + + /** + * This will print the usage requirements and exit. + */ + private static void usage() + { + System.err.println( "Usage: java org.pdfbox.ExtractText [OPTIONS] [Text File]\n" + + " -password Password to decrypt document\n" + + " -encoding (ISO-8859-1,UTF-16BE,UTF-16LE,...)\n" + + " -console Send text to console instead of file\n" + + " -html Output in HTML format instead of raw text\n" + + " -sort Sort the text before writing\n" + + " -startPage The first page to start extraction(1 based)\n" + + " -endPage The last page to extract(inclusive)\n" + + " The PDF document to use\n" + + " [Text File] The file to write the text to\n" + ); + System.exit( 1 ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/ImportFDF.java b/src/main/java/org/pdfbox/ImportFDF.java new file mode 100644 index 0000000..5a0cf27 --- /dev/null +++ b/src/main/java/org/pdfbox/ImportFDF.java @@ -0,0 +1,156 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox; + +import java.io.IOException; + +import org.pdfbox.pdmodel.PDDocument; +import org.pdfbox.pdmodel.PDDocumentCatalog; + +import org.pdfbox.pdmodel.fdf.FDFDocument; + +import org.pdfbox.pdmodel.interactive.form.PDAcroForm; + +/** + * This example will take a PDF document and fill the fields with data from the + * FDF fields. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.1 $ + */ +public class ImportFDF +{ + /** + * Creates a new instance of ImportFDF. + */ + public ImportFDF() + { + } + + /** + * This will takes the values from the fdf document and import them into the + * PDF document. + * + * @param pdfDocument The document to put the fdf data into. + * @param fdfDocument The FDF document to get the data from. + * + * @throws IOException If there is an error setting the data in the field. + */ + public void importFDF( PDDocument pdfDocument, FDFDocument fdfDocument ) throws IOException + { + PDDocumentCatalog docCatalog = pdfDocument.getDocumentCatalog(); + PDAcroForm acroForm = docCatalog.getAcroForm(); + acroForm.setCacheFields( true ); + acroForm.importFDF( fdfDocument ); + } + + /** + * This will import an fdf document and write out another pdf. + *
+ * see usage() for commandline + * + * @param args command line arguments + * + * @throws Exception If there is an error importing the FDF document. + */ + public static void main(String[] args) throws Exception + { + ImportFDF importer = new ImportFDF(); + importer.importFDF( args ); + } + + private void importFDF( String[] args ) throws Exception + { + PDDocument pdf = null; + FDFDocument fdf = null; + + try + { + if( args.length != 3 ) + { + usage(); + } + else + { + ImportFDF importer = new ImportFDF(); + + pdf = PDDocument.load( args[0] ); + fdf = FDFDocument.load( args[1] ); + importer.importFDF( pdf, fdf ); + + pdf.save( args[2] ); + } + } + finally + { + close( fdf ); + close( pdf ); + } + } + + /** + * This will print out a message telling how to use this example. + */ + private static void usage() + { + System.err.println( "usage: org.pdfbox.ImportFDF " ); + } + + /** + * Close the document. + * + * @param doc The doc to close. + * + * @throws IOException If there is an error closing the document. + */ + public void close( FDFDocument doc ) throws IOException + { + if( doc != null ) + { + doc.close(); + } + } + + /** + * Close the document. + * + * @param doc The doc to close. + * + * @throws IOException If there is an error closing the document. + */ + public void close( PDDocument doc ) throws IOException + { + if( doc != null ) + { + doc.close(); + } + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/ImportXFDF.java b/src/main/java/org/pdfbox/ImportXFDF.java new file mode 100644 index 0000000..24987a4 --- /dev/null +++ b/src/main/java/org/pdfbox/ImportXFDF.java @@ -0,0 +1,157 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox; + +import org.pdfbox.pdmodel.PDDocument; +import org.pdfbox.pdmodel.PDDocumentCatalog; + +import org.pdfbox.pdmodel.fdf.FDFDocument; + +import org.pdfbox.pdmodel.interactive.form.PDAcroForm; + +import java.io.IOException; + + +/** + * This example will take a PDF document and fill the fields with data from the + * XFDF fields. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.1 $ + */ +public class ImportXFDF +{ + /** + * Creates a new instance of ImportFDF. + */ + public ImportXFDF() + { + } + + /** + * This will takes the values from the fdf document and import them into the + * PDF document. + * + * @param pdfDocument The document to put the fdf data into. + * @param fdfDocument The FDF document to get the data from. + * + * @throws IOException If there is an error setting the data in the field. + */ + public void importFDF( PDDocument pdfDocument, FDFDocument fdfDocument ) throws IOException + { + PDDocumentCatalog docCatalog = pdfDocument.getDocumentCatalog(); + PDAcroForm acroForm = docCatalog.getAcroForm(); + acroForm.setCacheFields( true ); + acroForm.importFDF( fdfDocument ); + } + + /** + * This will import an fdf document and write out another pdf. + *
+ * see usage() for commandline + * + * @param args command line arguments + * + * @throws Exception If there is an error importing the FDF document. + */ + public static void main(String[] args) throws Exception + { + ImportXFDF importer = new ImportXFDF(); + importer.importXFDF( args ); + } + + private void importXFDF( String[] args ) throws Exception + { + PDDocument pdf = null; + FDFDocument fdf = null; + + try + { + if( args.length != 3 ) + { + usage(); + } + else + { + ImportFDF importer = new ImportFDF(); + pdf = PDDocument.load( args[0] ); + fdf = FDFDocument.loadXFDF( args[1] ); + + importer.importFDF( pdf, fdf ); + pdf.save( args[2] ); + fdf.save( "tmp/outputXFDFtoPDF.fdf"); + } + } + finally + { + close( fdf ); + close( pdf ); + } + } + + /** + * This will print out a message telling how to use this example. + */ + private static void usage() + { + System.err.println( "usage: org.pdfbox.ImportXFDF " ); + } + + /** + * Close the document. + * + * @param doc The doc to close. + * + * @throws IOException If there is an error closing the document. + */ + public void close( FDFDocument doc ) throws IOException + { + if( doc != null ) + { + doc.close(); + } + } + + /** + * Close the document. + * + * @param doc The doc to close. + * + * @throws IOException If there is an error closing the document. + */ + public void close( PDDocument doc ) throws IOException + { + if( doc != null ) + { + doc.close(); + } + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/Overlay.java b/src/main/java/org/pdfbox/Overlay.java new file mode 100644 index 0000000..7850d89 --- /dev/null +++ b/src/main/java/org/pdfbox/Overlay.java @@ -0,0 +1,530 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox; + +import org.apache.log4j.Logger; +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSName; +import org.pdfbox.cos.COSStream; +import org.pdfbox.cos.COSInteger; +import org.pdfbox.exceptions.COSVisitorException; +import org.pdfbox.pdfparser.PDFParser; +import org.pdfbox.pdfwriter.COSWriter; + +import org.pdfbox.pdmodel.PDDocument; +import org.pdfbox.pdmodel.PDDocumentCatalog; +import org.pdfbox.pdmodel.PDPage; +import org.pdfbox.pdmodel.PDResources; + +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.ByteArrayOutputStream; +import java.io.OutputStream; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.TreeMap; +import java.util.Map; + +/** + * Overlay on document with another one.
+ * e.g. Overlay an invoice with your company layout
+ *
+ * How it (should) work:
+ * If the document has 10 pages, and the layout 2 the following is the result:
+ *
+ * Document: 1234567890
+ * Layout  : 1212121212
+ * 
+ *
+ * + * @author Mario Ivankovits (mario@ops.co.at) + * @author Ben Litchfield (ben@csh.rit.edu) + * + * @version $Revision: 1.4 $ + */ +public class Overlay +{ + /** + * COSName constant. + */ + public static final COSName XOBJECT = COSName.getPDFName("XObject"); + /** + * COSName constant. + */ + public static final COSName PROC_SET = COSName.getPDFName("ProcSet"); + /** + * COSName constant. + */ + public static final COSName EXT_G_STATE = COSName.getPDFName("ExtGState" ); + + private static Logger log = Logger.getLogger(Overlay.class); + + private List layoutPages = new ArrayList(10); + + private PDDocument pdfOverlay; + private PDDocument pdfDocument; + private int pageCount = 0; + private COSStream saveGraphicsStateStream; + private COSStream restoreGraphicsStateStream; + + /** + * This will overlay a document and write out the results.

+ * + * usage: java org.pdfbox.Overlay <overlay.pdf> <document.pdf> <result.pdf> + * + * @param args The command line arguments. + * + * @throws IOException If there is an error reading/writing the document. + * @throws COSVisitorException If there is an error writing the document. + */ + public static void main( String[] args ) throws IOException, COSVisitorException + { + if( args.length != 3 ) + { + usage(); + System.exit(1); + } + else + { + PDDocument overlay = null; + PDDocument pdf = null; + + try + { + overlay = getDocument( args[0] ); + pdf = getDocument( args[1] ); + Overlay overlayer = new Overlay(); + overlayer.overlay( overlay, pdf ); + writeDocument( pdf, args[2] ); + } + finally + { + if( overlay != null ) + { + overlay.close(); + } + if( pdf != null ) + { + pdf.close(); + } + } + } + } + + private static void writeDocument( PDDocument pdf, String filename ) throws IOException, COSVisitorException + { + FileOutputStream output = null; + COSWriter writer = null; + try + { + output = new FileOutputStream( filename ); + writer = new COSWriter( output ); + writer.write( pdf ); + } + finally + { + if( writer != null ) + { + writer.close(); + } + if( output != null ) + { + output.close(); + } + } + } + + private static PDDocument getDocument( String filename ) throws IOException + { + FileInputStream input = null; + PDFParser parser = null; + PDDocument result = null; + try + { + input = new FileInputStream( filename ); + parser = new PDFParser( input ); + parser.parse(); + result = parser.getPDDocument(); + } + finally + { + if( input != null ) + { + input.close(); + } + } + return result; + } + + private static void usage() + { + System.err.println( "usage: java " + Overlay.class.getName() + " " ); + } + + /** + * Private class. + */ + private static class LayoutPage + { + private final COSBase contents; + private final COSDictionary res; + private final Map objectNameMap; + + /** + * Constructor. + * + * @param contentsValue The contents. + * @param resValue The resource dictionary + * @param objectNameMapValue The map + */ + public LayoutPage(COSBase contentsValue, COSDictionary resValue, Map objectNameMapValue) + { + contents = contentsValue; + res = resValue; + objectNameMap = objectNameMapValue; + } + } + + /** + * This will overlay two documents onto each other. The overlay document is + * repeatedly overlayed onto the destination document for every page in the + * destination. + * + * @param overlay The document to copy onto the destination + * @param destination The file that the overlay should be placed on. + * + * @return The destination pdf, same as argument passed in. + * + * @throws IOException If there is an error accessing data. + */ + public PDDocument overlay( PDDocument overlay, PDDocument destination ) throws IOException + { + pdfOverlay = overlay; + pdfDocument = destination; + + PDDocumentCatalog overlayCatalog = pdfOverlay.getDocumentCatalog(); + collectLayoutPages( overlayCatalog.getAllPages() ); + + COSDictionary saveGraphicsStateDic = new COSDictionary(); + saveGraphicsStateStream = new COSStream( saveGraphicsStateDic, pdfDocument.getDocument().getScratchFile() ); + OutputStream saveStream = saveGraphicsStateStream.createUnfilteredStream(); + saveStream.write( " q\n".getBytes() ); + saveStream.flush(); + + restoreGraphicsStateStream = new COSStream( saveGraphicsStateDic, pdfDocument.getDocument().getScratchFile() ); + OutputStream restoreStream = restoreGraphicsStateStream.createUnfilteredStream(); + restoreStream.write( " Q\n".getBytes() ); + restoreStream.flush(); + + + PDDocumentCatalog pdfCatalog = pdfDocument.getDocumentCatalog(); + processPages( pdfCatalog.getAllPages() ); + + return pdfDocument; + } + + private void collectLayoutPages( List pages) throws IOException + { + Iterator pagesIter = pages.iterator(); + while( pagesIter.hasNext() ) + { + PDPage page = (PDPage)pagesIter.next(); + COSBase contents = page.getCOSDictionary().getDictionaryObject( COSName.CONTENTS ); + PDResources resources = page.findResources(); + if( resources == null ) + { + resources = new PDResources(); + page.setResources( resources ); + } + COSDictionary res = resources.getCOSDictionary(); + + if( contents instanceof COSStream ) + { + COSStream stream = (COSStream) contents; + Map objectNameMap = new TreeMap(); + stream = makeUniqObjectNames(objectNameMap, stream); + + layoutPages.add(new LayoutPage(stream, res, objectNameMap)); + } + else if( contents instanceof COSArray ) + { + throw new UnsupportedOperationException("Layout pages with COSArray currently not supported."); + // layoutPages.add(new LayoutPage(contents, res)); + } + else + { + throw new IOException( "Contents are unknown type:" + contents.getClass().getName() ); + } + } + } + + private COSStream makeUniqObjectNames(Map objectNameMap, COSStream stream) throws IOException + { + ByteArrayOutputStream baos = new ByteArrayOutputStream(10240); + + byte[] buf = new byte[10240]; + int read; + InputStream is = stream.getUnfilteredStream(); + while ((read = is.read(buf)) > -1) + { + baos.write(buf, 0, read); + } + + buf = baos.toByteArray(); + baos = new ByteArrayOutputStream(buf.length + 100); + StringBuffer sbObjectName = new StringBuffer(10); + boolean bInObjectIdent = false; + boolean bInText = false; + boolean bInEscape = false; + for (int i = 0; i + // + // + // + array.add(0, saveGraphicsStateStream ); + array.add( restoreGraphicsStateStream ); + array.add(layoutPage.contents); + } + + /** + * merges two dictionaries. + * + * @param dest + * @param source + */ + private void mergeDictionary(COSName name, COSDictionary dest, COSDictionary source, Map objectNameMap) + { + COSDictionary destDict = (COSDictionary) dest.getDictionaryObject(name); + COSDictionary sourceDict = (COSDictionary) source.getDictionaryObject(name); + + if (destDict == null) + { + destDict = new COSDictionary(); + dest.setItem(name, destDict); + } + if( sourceDict != null ) + { + + Iterator iterKeys = sourceDict.keyList().iterator(); + while (iterKeys.hasNext()) + { + COSName key = (COSName) iterKeys.next(); + COSName mappedKey = (COSName) objectNameMap.get(key.getName()); + if (mappedKey == null) + { + // object not needet + if (log.isDebugEnabled()) + { + log.debug("MergeDict " + name.getName() + + ": Object " + key.getName() + " not used by content. Discarded."); + } + continue; + } + + destDict.setItem(mappedKey, sourceDict.getItem(key)); + } + } + } + + /** + * merges two arrays. + * + * @param dest + * @param source + */ + private void mergeArray(COSName name, COSDictionary dest, COSDictionary source) + { + COSArray destDict = (COSArray) dest.getDictionaryObject(name); + COSArray sourceDict = (COSArray) source.getDictionaryObject(name); + + if (destDict == null) + { + destDict = new COSArray(); + dest.setItem(name, destDict); + } + + for (int sourceDictIdx = 0; sourceDict != null && sourceDictIdx0 ) + { + viewer.readPDFFile( args[0] ); + } + viewer.show(); + } + + private void readPDFFile(String file) throws Exception + { + InputStream input = null; + File f = new File( file ); + input = new FileInputStream(f); + PDDocument document = parseDocument( input ); + TreeModel model=new PDFTreeModel(document); + jTree1.setModel(model); + setTitle( "PDFBox - " + f.getAbsolutePath() ); + /* + List pages = document.getDocumentCatalog().getAllPages(); + for( int i=0; i0 ) + { + viewer.openPDFFile( args[0] ); + } + viewer.show(); + } + + private void openPDFFile(String file) throws Exception + { + if( document != null ) + { + document.close(); + documentPanel.removeAll(); + } + InputStream input = null; + File f = new File( file ); + input = new FileInputStream(f); + document = parseDocument( input ); + setTitle( "PDFBox - " + f.getAbsolutePath() ); + + List pages = document.getDocumentCatalog().getAllPages(); + for( int i=0; i= args.length ) + { + usage(); + } + password = args[i]; + } + else if( args[i].equals( SPLIT ) ) + { + i++; + if( i >= args.length ) + { + usage(); + } + split = args[i]; + } + else + { + if( pdfFile == null ) + { + pdfFile = args[i]; + } + } + } + + if( pdfFile == null ) + { + usage(); + } + + InputStream input = null; + PDDocument document = null; + List documents = null; + try + { + input = new FileInputStream( pdfFile ); + document = parseDocument( input ); + + if( document.isEncrypted() ) + { + try + { + document.decrypt( password ); + } + catch( InvalidPasswordException e ) + { + if( args.length == 4 )//they supplied the wrong password + { + System.err.println( "Error: The supplied password is incorrect." ); + System.exit( 2 ); + } + else + { + //they didn't suppply a password and the default of "" was wrong. + System.err.println( "Error: The document is encrypted." ); + usage(); + } + } + } + + splitter.setSplitAtPage( Integer.parseInt( split ) ); + documents = splitter.split( document ); + for( int i=0; i\n" + + " -password Password to decrypt document\n" + + " -split split after this many pages\n" + + " The PDF document to use\n" + ); + System.exit( 1 ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/PDFToImage.java b/src/main/java/org/pdfbox/PDFToImage.java new file mode 100644 index 0000000..7a6df6b --- /dev/null +++ b/src/main/java/org/pdfbox/PDFToImage.java @@ -0,0 +1,270 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox; + +import java.awt.image.BufferedImage; +import java.io.File; +import java.util.Iterator; +import java.util.List; + +import javax.imageio.IIOException; +import javax.imageio.IIOImage; +import javax.imageio.ImageIO; +import javax.imageio.ImageWriteParam; +import javax.imageio.ImageWriter; +import javax.imageio.stream.ImageOutputStream; + +import org.pdfbox.exceptions.InvalidPasswordException; + +import org.pdfbox.pdmodel.PDDocument; +import org.pdfbox.pdmodel.PDPage; + +/** + * Convert a PDF document to an image. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.3 $ + */ +public class PDFToImage +{ + + + + private static final String PASSWORD = "-password"; + private static final String START_PAGE = "-startPage"; + private static final String END_PAGE = "-endPage"; + private static final String IMAGE_TYPE = "-imageType"; + private static final String OUTPUT_PREFIX = "-outputPrefix"; + + /** + * private constructor. + */ + private PDFToImage() + { + //static class + } + + /** + * Infamous main method. + * + * @param args Command line arguments, should be one and a reference to a file. + * + * @throws Exception If there is an error parsing the document. + */ + public static void main( String[] args ) throws Exception + { + String password = ""; + String pdfFile = null; + String outputPrefix = null; + String imageType = "jpg"; + int startPage = 1; + int endPage = Integer.MAX_VALUE; + for( int i=0; i= args.length ) + { + usage(); + } + password = args[i]; + } + else if( args[i].equals( START_PAGE ) ) + { + i++; + if( i >= args.length ) + { + usage(); + } + startPage = Integer.parseInt( args[i] ); + } + else if( args[i].equals( END_PAGE ) ) + { + i++; + if( i >= args.length ) + { + usage(); + } + endPage = Integer.parseInt( args[i] ); + } + else if( args[i].equals( IMAGE_TYPE ) ) + { + i++; + imageType = args[i]; + } + else if( args[i].equals( OUTPUT_PREFIX ) ) + { + i++; + outputPrefix = args[i]; + } + else + { + if( pdfFile == null ) + { + pdfFile = args[i]; + } + } + } + + if( pdfFile == null ) + { + usage(); + } + if(outputPrefix == null) + { + outputPrefix = pdfFile.substring( 0, pdfFile.lastIndexOf( '.' )); + } + + PDDocument document = null; + try + { + document = PDDocument.load( pdfFile ); + + + //document.print(); + if( document.isEncrypted() ) + { + try + { + document.decrypt( password ); + } + catch( InvalidPasswordException e ) + { + if( args.length == 4 )//they supplied the wrong password + { + System.err.println( "Error: The supplied password is incorrect." ); + System.exit( 2 ); + } + else + { + //they didn't suppply a password and the default of "" was wrong. + System.err.println( "Error: The document is encrypted." ); + usage(); + } + } + } + List pages = document.getDocumentCatalog().getAllPages(); + for( int i=startPage-1; i [Text File]\n" + + " -password Password to decrypt document\n" + + " -imageType (" + getImageFormats() + ")\n" + + " -outputPrefix Filename prefix for image files\n" + + " -startPage The first page to start extraction(1 based)\n" + + " -endPage The last page to extract(inclusive)\n" + + " The PDF document to use\n" + ); + System.exit( 1 ); + } + + private static String getImageFormats() + { + StringBuffer retval = new StringBuffer(); + String[] formats = ImageIO.getReaderFormatNames(); + for( int i=0; i= args.length ) + { + usage(); + } + password = args[i]; + } + else + { + pdfFile = args[i]; + } + } + + if( pdfFile == null ) + { + usage(); + } + + PDDocument document = null; + try + { + document = PDDocument.load( pdfFile ); + + if( document.isEncrypted() ) + { + document.decrypt( password ); + } + + document.print(); + } + finally + { + if( document != null ) + { + document.close(); + } + } + } + + /** + * This will print the usage requirements and exit. + */ + private static void usage() + { + System.err.println( "Usage: java org.pdfbox.PrintPDF [OPTIONS] \n" + + " -password Password to decrypt document\n" + ); + System.exit( 1 ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/TextToPDF.java b/src/main/java/org/pdfbox/TextToPDF.java new file mode 100644 index 0000000..413d981 --- /dev/null +++ b/src/main/java/org/pdfbox/TextToPDF.java @@ -0,0 +1,259 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.Reader; + +import org.pdfbox.pdmodel.PDDocument; +import org.pdfbox.pdmodel.PDPage; + +import org.pdfbox.pdmodel.edit.PDPageContentStream; +import org.pdfbox.pdmodel.font.PDSimpleFont; +import org.pdfbox.pdmodel.font.PDTrueTypeFont; +import org.pdfbox.pdmodel.font.PDType1Font; + + +/** + * This will take a text file and ouput a pdf with that text. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.3 $ + */ +public class TextToPDF +{ + private int fontSize = 10; + private PDSimpleFont font = PDType1Font.HELVETICA; + + /** + * Create a PDF document with some text. + * + * @param text The stream of text data. + * + * @return The document with the text in it. + * + * @throws IOException If there is an error writing the data. + */ + public PDDocument createPDFFromText( Reader text ) throws IOException + { + PDDocument doc = null; + try + { + + int margin = 40; + float height = font.getFontDescriptor().getFontBoundingBox().getHeight()/1000; + + //calculate font height and increase by 5 percent. + height = height*fontSize*1.05f; + doc = new PDDocument(); + BufferedReader data = new BufferedReader( text ); + String nextLine = null; + PDPage page = new PDPage(); + PDPageContentStream contentStream = null; + float y = -1; + float maxStringLength = page.getMediaBox().getWidth() - 2*margin; + while( (nextLine = data.readLine()) != null ) + { + + String[] lineWords = nextLine.trim().split( " " ); + int lineIndex = 0; + while( lineIndex < lineWords.length ) + { + StringBuffer nextLineToDraw = new StringBuffer(); + float lengthIfUsingNextWord = 0; + do + { + nextLineToDraw.append( lineWords[lineIndex] ); + nextLineToDraw.append( " " ); + lineIndex++; + if( lineIndex < lineWords.length ) + { + String lineWithNextWord = nextLineToDraw.toString() + lineWords[lineIndex]; + lengthIfUsingNextWord = + (font.getStringWidth( lineWithNextWord )/1000) * fontSize; + } + } + while( lineIndex < lineWords.length && + lengthIfUsingNextWord < maxStringLength ); + if( y < margin ) + { + page = new PDPage(); + doc.addPage( page ); + if( contentStream != null ) + { + contentStream.endText(); + contentStream.close(); + } + contentStream = new PDPageContentStream(doc, page); + contentStream.setFont( font, fontSize ); + contentStream.beginText(); + y = page.getMediaBox().getHeight() - margin + height; + contentStream.moveTextPositionByAmount( + margin, y ); + + } + //System.out.println( "Drawing string at " + x + "," + y ); + + + contentStream.moveTextPositionByAmount( 0, -height); + y -= height; + contentStream.drawString( nextLineToDraw.toString() ); + } + + + } + if( contentStream != null ) + { + contentStream.endText(); + contentStream.close(); + } + } + catch( IOException io ) + { + if( doc != null ) + { + doc.close(); + } + throw io; + } + return doc; + } + + /** + * This will create a PDF document with a single image on it. + *
+ * see usage() for commandline + * + * @param args Command line arguments. + * + * @throws IOException If there is an error with the PDF. + */ + public static void main(String[] args) throws IOException + { + TextToPDF app = new TextToPDF(); + PDDocument doc = null; + try + { + if( args.length < 2 ) + { + app.usage(); + } + else + { + for( int i=0; i " ); + System.err.println( " -standardFont default:" + PDType1Font.HELVETICA.getBaseFont() ); + for( int i=0; i The TTF font to use."); + System.err.println( " -fontSize default:10" ); + + + } + /** + * @return Returns the font. + */ + public PDSimpleFont getFont() + { + return font; + } + /** + * @param aFont The font to set. + */ + public void setFont(PDSimpleFont aFont) + { + this.font = aFont; + } + /** + * @return Returns the fontSize. + */ + public int getFontSize() + { + return fontSize; + } + /** + * @param aFontSize The fontSize to set. + */ + public void setFontSize(int aFontSize) + { + this.fontSize = aFontSize; + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/Version.java b/src/main/java/org/pdfbox/Version.java new file mode 100644 index 0000000..b2e2f34 --- /dev/null +++ b/src/main/java/org/pdfbox/Version.java @@ -0,0 +1,100 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox; + +import java.io.IOException; + +import java.util.Properties; + +import org.pdfbox.util.ResourceLoader; + + +/** + * A simple command line utility to get the version of PDFBox. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.3 $ + */ +public class Version +{ + private static final String PDFBOX_VERSION_PROPERTIES = "Resources/pdfbox.version"; + + private Version() + { + //should not be constructed. + } + + /** + * Get the version of PDFBox or unknown if it is not known. + * + * @return The version of pdfbox that is being used. + */ + public static String getVersion() + { + String version = "unknown"; + try + { + Properties props = ResourceLoader.loadProperties( PDFBOX_VERSION_PROPERTIES ); + version = props.getProperty( "pdfbox.version", version ); + } + catch( IOException io ) + { + //if there is a problem loading the properties then don't throw an + //exception, 'unknown' will be returned instead. + io.printStackTrace(); + } + return version; + } + + /** + * This will print out the version of PDF to System.out. + * + * @param args Command line arguments. + */ + public static void main(String[] args) + { + if( args.length != 0 ) + { + usage(); + return; + } + System.out.println( "Version:" + getVersion() ); + } + + /** + * This will print out a message telling how to use this example. + */ + private static void usage() + { + System.err.println( "usage: " + Version.class.getName() ); + } + +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/afmparser/AFMParser.java b/src/main/java/org/pdfbox/afmparser/AFMParser.java new file mode 100644 index 0000000..44c594d --- /dev/null +++ b/src/main/java/org/pdfbox/afmparser/AFMParser.java @@ -0,0 +1,1084 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.afmparser; + +import java.io.InputStream; +import java.io.IOException; + +import java.util.StringTokenizer; + +import org.pdfbox.afmtypes.Composite; +import org.pdfbox.afmtypes.CompositePart; +import org.pdfbox.afmtypes.CharMetric; +import org.pdfbox.afmtypes.FontMetric; +import org.pdfbox.afmtypes.KernPair; +import org.pdfbox.afmtypes.Ligature; +import org.pdfbox.afmtypes.TrackKern; + +import org.pdfbox.util.BoundingBox; + +/** + * This class is used to parse AFM(Adobe Font Metrics) documents. + * + * @see AFM Documentation + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.9 $ + */ +public class AFMParser +{ + /** + * This is a comment in a AFM file. + */ + public static final String COMMENT = "Comment"; + /** + * This is the constant used in the AFM file to start a font metrics item. + */ + public static final String START_FONT_METRICS = "StartFontMetrics"; + /** + * This is the constant used in the AFM file to end a font metrics item. + */ + public static final String END_FONT_METRICS = "EndFontMetrics"; + /** + * This is the font name. + */ + public static final String FONT_NAME = "FontName"; + /** + * This is the full name. + */ + public static final String FULL_NAME = "FullName"; + /** + * This is the Family name. + */ + public static final String FAMILY_NAME = "FamilyName"; + /** + * This is the weight. + */ + public static final String WEIGHT = "Weight"; + /** + * This is the font bounding box. + */ + public static final String FONT_BBOX = "FontBBox"; + /** + * This is the version of the font. + */ + public static final String VERSION = "Version"; + /** + * This is the notice. + */ + public static final String NOTICE = "Notice"; + /** + * This is the encoding scheme. + */ + public static final String ENCODING_SCHEME = "EncodingScheme"; + /** + * This is the mapping scheme. + */ + public static final String MAPPING_SCHEME = "MappingScheme"; + /** + * This is the escape character. + */ + public static final String ESC_CHAR = "EscChar"; + /** + * This is the character set. + */ + public static final String CHARACTER_SET = "CharacterSet"; + /** + * This is the characters attribute. + */ + public static final String CHARACTERS = "Characters"; + /** + * This will determine if this is a base font. + */ + public static final String IS_BASE_FONT = "IsBaseFont"; + /** + * This is the V Vector attribute. + */ + public static final String V_VECTOR = "VVector"; + /** + * This will tell if the V is fixed. + */ + public static final String IS_FIXED_V = "IsFixedV"; + /** + * This is the cap height attribute. + */ + public static final String CAP_HEIGHT = "CapHeight"; + /** + * This is the X height. + */ + public static final String X_HEIGHT = "XHeight"; + /** + * This is ascender attribute. + */ + public static final String ASCENDER = "Ascender"; + /** + * This is the descender attribute. + */ + public static final String DESCENDER = "Descender"; + + /** + * The underline position. + */ + public static final String UNDERLINE_POSITION = "UnderlinePosition"; + /** + * This is the Underline thickness. + */ + public static final String UNDERLINE_THICKNESS = "UnderlineThickness"; + /** + * This is the italic angle. + */ + public static final String ITALIC_ANGLE = "ItalicAngle"; + /** + * This is the char width. + */ + public static final String CHAR_WIDTH = "CharWidth"; + /** + * This will determine if this is fixed pitch. + */ + public static final String IS_FIXED_PITCH = "IsFixedPitch"; + /** + * This is the start of character metrics. + */ + public static final String START_CHAR_METRICS = "StartCharMetrics"; + /** + * This is the end of character metrics. + */ + public static final String END_CHAR_METRICS = "EndCharMetrics"; + /** + * The character metrics c value. + */ + public static final String CHARMETRICS_C = "C"; + /** + * The character metrics c value. + */ + public static final String CHARMETRICS_CH = "CH"; + /** + * The character metrics value. + */ + public static final String CHARMETRICS_WX = "WX"; + /** + * The character metrics value. + */ + public static final String CHARMETRICS_W0X = "W0X"; + /** + * The character metrics value. + */ + public static final String CHARMETRICS_W1X = "W1X"; + /** + * The character metrics value. + */ + public static final String CHARMETRICS_WY = "WY"; + /** + * The character metrics value. + */ + public static final String CHARMETRICS_W0Y = "W0Y"; + /** + * The character metrics value. + */ + public static final String CHARMETRICS_W1Y = "W1Y"; + /** + * The character metrics value. + */ + public static final String CHARMETRICS_W = "W"; + /** + * The character metrics value. + */ + public static final String CHARMETRICS_W0 = "W0"; + /** + * The character metrics value. + */ + public static final String CHARMETRICS_W1 = "W1"; + /** + * The character metrics value. + */ + public static final String CHARMETRICS_VV = "VV"; + /** + * The character metrics value. + */ + public static final String CHARMETRICS_N = "N"; + /** + * The character metrics value. + */ + public static final String CHARMETRICS_B = "B"; + /** + * The character metrics value. + */ + public static final String CHARMETRICS_L = "L"; + /** + * The character metrics value. + */ + public static final String STD_HW = "StdHW"; + /** + * The character metrics value. + */ + public static final String STD_VW = "StdVW"; + /** + * This is the start of track kern data. + */ + public static final String START_TRACK_KERN = "StartTrackKern"; + /** + * This is the end of track kern data. + */ + public static final String END_TRACK_KERN = "EndTrackKern"; + /** + * This is the start of kern data. + */ + public static final String START_KERN_DATA = "StartKernData"; + /** + * This is the end of kern data. + */ + public static final String END_KERN_DATA = "EndKernData"; + /** + * This is the start of kern pairs data. + */ + public static final String START_KERN_PAIRS = "StartKernPairs"; + /** + * This is the end of kern pairs data. + */ + public static final String END_KERN_PAIRS = "EndKernPairs"; + /** + * This is the start of kern pairs data. + */ + public static final String START_KERN_PAIRS0 = "StartKernPairs0"; + /** + * This is the start of kern pairs data. + */ + public static final String START_KERN_PAIRS1 = "StartKernPairs1"; + /** + * This is the start compisites data section. + */ + public static final String START_COMPOSITES = "StartComposites"; + /** + * This is the end compisites data section. + */ + public static final String END_COMPOSITES = "EndComposites"; + /** + * This is a composite character. + */ + public static final String CC = "CC"; + /** + * This is a composite charater part. + */ + public static final String PCC = "PCC"; + /** + * This is a kern pair. + */ + public static final String KERN_PAIR_KP = "KP"; + /** + * This is a kern pair. + */ + public static final String KERN_PAIR_KPH = "KPH"; + /** + * This is a kern pair. + */ + public static final String KERN_PAIR_KPX = "KPX"; + /** + * This is a kern pair. + */ + public static final String KERN_PAIR_KPY = "KPY"; + + private static final int BITS_IN_HEX = 16; + + + private InputStream input; + private FontMetric result; + + /** + * A method to test parsing of all AFM documents in the resources + * directory. + * + * @param args Ignored. + * + * @throws IOException If there is an error parsing one of the documents. + */ + public static void main( String[] args ) throws IOException + { + java.io.File afmDir = new java.io.File( "Resources/afm" ); + java.io.File[] files = afmDir.listFiles(); + for( int i=0; i< files.length; i++ ) + { + if( files[i].getPath().toUpperCase().endsWith( ".AFM" ) ) + { + long start = System.currentTimeMillis(); + java.io.FileInputStream input = new java.io.FileInputStream( files[i] ); + AFMParser parser = new AFMParser( input ); + parser.parse(); + long stop = System.currentTimeMillis(); + System.out.println( "Parsing:" + files[i].getPath() + " " + (stop-start) ); + } + } + } + + /** + * Constructor. + * + * @param in The input stream to read the AFM document from. + */ + public AFMParser( InputStream in ) + { + input = in; + } + + /** + * This will parse the AFM document. This will close the Input stream + * when the parsing is finished. + * + * @throws IOException If there is an IO error reading the document. + */ + public void parse() throws IOException + { + result = parseFontMetric(); + } + + /** + * This will get the result of the parsing. + * + * @return The parsed java object. + */ + public FontMetric getResult() + { + return result; + } + + /** + * This will parse a font metrics item. + * + * @return The parse font metrics item. + * + * @throws IOException If there is an error reading the AFM file. + */ + private FontMetric parseFontMetric() throws IOException + { + FontMetric fontMetrics = new FontMetric(); + String startFontMetrics = readString(); + if( !START_FONT_METRICS.equals( startFontMetrics ) ) + { + throw new IOException( "Error: The AFM file should start with " + START_FONT_METRICS + + " and not '" + startFontMetrics + "'" ); + } + fontMetrics.setAFMVersion( readFloat() ); + String nextCommand = null; + while( !END_FONT_METRICS.equals( (nextCommand = readString() ) ) ) + { + if( FONT_NAME.equals( nextCommand ) ) + { + fontMetrics.setFontName( readLine() ); + } + else if( FULL_NAME.equals( nextCommand ) ) + { + fontMetrics.setFullName( readLine() ); + } + else if( FAMILY_NAME.equals( nextCommand ) ) + { + fontMetrics.setFamilyName( readLine() ); + } + else if( WEIGHT.equals( nextCommand ) ) + { + fontMetrics.setWeight( readLine() ); + } + else if( FONT_BBOX.equals( nextCommand ) ) + { + BoundingBox bBox = new BoundingBox(); + bBox.setLowerLeftX( readFloat() ); + bBox.setLowerLeftY( readFloat() ); + bBox.setUpperRightX( readFloat() ); + bBox.setUpperRightY( readFloat() ); + fontMetrics.setFontBBox( bBox ); + } + else if( VERSION.equals( nextCommand ) ) + { + fontMetrics.setFontVersion( readLine() ); + } + else if( NOTICE.equals( nextCommand ) ) + { + fontMetrics.setNotice( readLine() ); + } + else if( ENCODING_SCHEME.equals( nextCommand ) ) + { + fontMetrics.setEncodingScheme( readLine() ); + } + else if( MAPPING_SCHEME.equals( nextCommand ) ) + { + fontMetrics.setMappingScheme( readInt() ); + } + else if( ESC_CHAR.equals( nextCommand ) ) + { + fontMetrics.setEscChar( readInt() ); + } + else if( CHARACTER_SET.equals( nextCommand ) ) + { + fontMetrics.setCharacterSet( readLine() ); + } + else if( CHARACTERS.equals( nextCommand ) ) + { + fontMetrics.setCharacters( readInt() ); + } + else if( IS_BASE_FONT.equals( nextCommand ) ) + { + fontMetrics.setIsBaseFont( readBoolean() ); + } + else if( V_VECTOR.equals( nextCommand ) ) + { + float[] vector = new float[2]; + vector[0] = readFloat(); + vector[1] = readFloat(); + fontMetrics.setVVector( vector ); + } + else if( IS_FIXED_V.equals( nextCommand ) ) + { + fontMetrics.setIsFixedV( readBoolean() ); + } + else if( CAP_HEIGHT.equals( nextCommand ) ) + { + fontMetrics.setCapHeight( readFloat() ); + } + else if( X_HEIGHT.equals( nextCommand ) ) + { + fontMetrics.setXHeight( readFloat() ); + } + else if( ASCENDER.equals( nextCommand ) ) + { + fontMetrics.setAscender( readFloat() ); + } + else if( DESCENDER.equals( nextCommand ) ) + { + fontMetrics.setDescender( readFloat() ); + } + else if( STD_HW.equals( nextCommand ) ) + { + fontMetrics.setStandardHorizontalWidth( readFloat() ); + } + else if( STD_VW.equals( nextCommand ) ) + { + fontMetrics.setStandardVerticalWidth( readFloat() ); + } + else if( COMMENT.equals( nextCommand ) ) + { + fontMetrics.addComment( readLine() ); + } + else if( UNDERLINE_POSITION.equals( nextCommand ) ) + { + fontMetrics.setUnderlinePosition( readFloat() ); + } + else if( UNDERLINE_THICKNESS.equals( nextCommand ) ) + { + fontMetrics.setUnderlineThickness( readFloat() ); + } + else if( ITALIC_ANGLE.equals( nextCommand ) ) + { + fontMetrics.setItalicAngle( readFloat() ); + } + else if( CHAR_WIDTH.equals( nextCommand ) ) + { + float[] widths = new float[2]; + widths[0] = readFloat(); + widths[1] = readFloat(); + fontMetrics.setCharWidth( widths ); + } + else if( IS_FIXED_PITCH.equals( nextCommand ) ) + { + fontMetrics.setFixedPitch( readBoolean() ); + } + else if( START_CHAR_METRICS.equals( nextCommand ) ) + { + int count = readInt(); + for( int i=0; i= 2 not='" + hexString ); + } + if( hexString.charAt( 0 ) != '<' || + hexString.charAt( hexString.length() -1 ) != '>' ) + { + throw new IOException( "String should be enclosed by angle brackets '" + hexString+ "'" ); + } + hexString = hexString.substring( 1, hexString.length() -1 ); + byte[] data = new byte[ (hexString.length() / 2) ]; + for( int i=0; i or FF, the spec is a little + //unclear, wait and see if it breaks anything. + String charCode = metricsTokenizer.nextToken(); + charMetric.setCharacterCode( Integer.parseInt( charCode, BITS_IN_HEX ) ); + verifySemicolon( metricsTokenizer ); + } + else if( nextCommand.equals( CHARMETRICS_WX ) ) + { + String wx = metricsTokenizer.nextToken(); + charMetric.setWx( Float.parseFloat( wx ) ); + verifySemicolon( metricsTokenizer ); + } + else if( nextCommand.equals( CHARMETRICS_W0X ) ) + { + String w0x = metricsTokenizer.nextToken(); + charMetric.setW0x( Float.parseFloat( w0x ) ); + verifySemicolon( metricsTokenizer ); + } + else if( nextCommand.equals( CHARMETRICS_W1X ) ) + { + String w1x = metricsTokenizer.nextToken(); + charMetric.setW0x( Float.parseFloat( w1x ) ); + verifySemicolon( metricsTokenizer ); + } + else if( nextCommand.equals( CHARMETRICS_WY ) ) + { + String wy = metricsTokenizer.nextToken(); + charMetric.setWy( Float.parseFloat( wy ) ); + verifySemicolon( metricsTokenizer ); + } + else if( nextCommand.equals( CHARMETRICS_W0Y ) ) + { + String w0y = metricsTokenizer.nextToken(); + charMetric.setW0y( Float.parseFloat( w0y ) ); + verifySemicolon( metricsTokenizer ); + } + else if( nextCommand.equals( CHARMETRICS_W1Y ) ) + { + String w1y = metricsTokenizer.nextToken(); + charMetric.setW0y( Float.parseFloat( w1y ) ); + verifySemicolon( metricsTokenizer ); + } + else if( nextCommand.equals( CHARMETRICS_W ) ) + { + String w0 = metricsTokenizer.nextToken(); + String w1 = metricsTokenizer.nextToken(); + float[] w = new float[2]; + w[0] = Float.parseFloat( w0 ); + w[1] = Float.parseFloat( w1 ); + charMetric.setW( w ); + verifySemicolon( metricsTokenizer ); + } + else if( nextCommand.equals( CHARMETRICS_W0 ) ) + { + String w00 = metricsTokenizer.nextToken(); + String w01 = metricsTokenizer.nextToken(); + float[] w0 = new float[2]; + w0[0] = Float.parseFloat( w00 ); + w0[1] = Float.parseFloat( w01 ); + charMetric.setW0( w0 ); + verifySemicolon( metricsTokenizer ); + } + else if( nextCommand.equals( CHARMETRICS_W1 ) ) + { + String w10 = metricsTokenizer.nextToken(); + String w11 = metricsTokenizer.nextToken(); + float[] w1 = new float[2]; + w1[0] = Float.parseFloat( w10 ); + w1[1] = Float.parseFloat( w11 ); + charMetric.setW1( w1 ); + verifySemicolon( metricsTokenizer ); + } + else if( nextCommand.equals( CHARMETRICS_VV ) ) + { + String vv0 = metricsTokenizer.nextToken(); + String vv1 = metricsTokenizer.nextToken(); + float[] vv = new float[2]; + vv[0] = Float.parseFloat( vv0 ); + vv[1] = Float.parseFloat( vv1 ); + charMetric.setVv( vv ); + verifySemicolon( metricsTokenizer ); + } + else if( nextCommand.equals( CHARMETRICS_N ) ) + { + String name = metricsTokenizer.nextToken(); + charMetric.setName( name ); + verifySemicolon( metricsTokenizer ); + } + else if( nextCommand.equals( CHARMETRICS_B ) ) + { + String llx = metricsTokenizer.nextToken(); + String lly = metricsTokenizer.nextToken(); + String urx = metricsTokenizer.nextToken(); + String ury = metricsTokenizer.nextToken(); + BoundingBox box = new BoundingBox(); + box.setLowerLeftX( Float.parseFloat( llx ) ); + box.setLowerLeftY( Float.parseFloat( lly ) ); + box.setUpperRightX( Float.parseFloat( urx ) ); + box.setUpperRightY( Float.parseFloat( ury ) ); + charMetric.setBoundingBox( box ); + verifySemicolon( metricsTokenizer ); + } + else if( nextCommand.equals( CHARMETRICS_L ) ) + { + String successor = metricsTokenizer.nextToken(); + String ligature = metricsTokenizer.nextToken(); + Ligature lig = new Ligature(); + lig.setSuccessor( successor ); + lig.setLigature( ligature ); + charMetric.addLigature( lig ); + verifySemicolon( metricsTokenizer ); + } + else + { + throw new IOException( "Unknown CharMetrics command '" + nextCommand + "'" ); + } + } + } + catch( NumberFormatException e ) + { + throw new IOException( "Error: Corrupt AFM document:" + e ); + } + return charMetric; + } + + /** + * This is used to verify that a semicolon is the next token in the stream. + * + * @param tokenizer The tokenizer to read from. + * + * @throws IOException If the semicolon is missing. + */ + private void verifySemicolon( StringTokenizer tokenizer ) throws IOException + { + if( tokenizer.hasMoreTokens() ) + { + String semicolon = tokenizer.nextToken(); + if( !semicolon.equals( ";" ) ) + { + throw new IOException( "Error: Expected semicolon in stream actual='" + + semicolon + "'" ); + } + } + else + { + throw new IOException( "CharMetrics is missing a semicolon after a command" ); + } + } + + /** + * This will read a boolean from the stream. + * + * @return The boolean in the stream. + */ + private boolean readBoolean() throws IOException + { + String theBoolean = readString(); + return Boolean.valueOf( theBoolean ).booleanValue(); + } + + /** + * This will read an integer from the stream. + * + * @return The integer in the stream. + */ + private int readInt() throws IOException + { + String theInt = readString(); + try + { + return Integer.parseInt( theInt ); + } + catch( NumberFormatException e ) + { + throw new IOException( "Error parsing AFM document:" + e ); + } + } + + /** + * This will read a float from the stream. + * + * @return The float in the stream. + */ + private float readFloat() throws IOException + { + String theFloat = readString(); + return Float.parseFloat( theFloat ); + } + + /** + * This will read until the end of a line. + * + * @return The string that is read. + */ + private String readLine() throws IOException + { + //First skip the whitespace + StringBuffer buf = new StringBuffer(); + int nextByte = input.read(); + while( isWhitespace( nextByte ) ) + { + nextByte = input.read(); + //do nothing just skip the whitespace. + } + buf.append( (char)nextByte ); + + //now read the data + while( !isEOL(nextByte = input.read()) ) + { + buf.append( (char)nextByte ); + } + return buf.toString(); + } + + /** + * This will read a string from the input stream and stop at any whitespace. + * + * @return The string read from the stream. + * + * @throws IOException If an IO error occurs when reading from the stream. + */ + private String readString() throws IOException + { + //First skip the whitespace + StringBuffer buf = new StringBuffer(); + int nextByte = input.read(); + while( isWhitespace( nextByte ) ) + { + nextByte = input.read(); + //do nothing just skip the whitespace. + } + buf.append( (char)nextByte ); + + //now read the data + while( !isWhitespace(nextByte = input.read()) ) + { + buf.append( (char)nextByte ); + } + return buf.toString(); + } + + /** + * This will determine if the byte is a whitespace character or not. + * + * @param character The character to test for whitespace. + * + * @return true If the character is whitespace as defined by the AFM spec. + */ + private boolean isEOL( int character ) + { + return character == 0x0D || + character == 0x0A; + } + + /** + * This will determine if the byte is a whitespace character or not. + * + * @param character The character to test for whitespace. + * + * @return true If the character is whitespace as defined by the AFM spec. + */ + private boolean isWhitespace( int character ) + { + return character == ' ' || + character == '\t' || + character == 0x0D || + character == 0x0A; + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/afmparser/package.html b/src/main/java/org/pdfbox/afmparser/package.html new file mode 100644 index 0000000..0785815 --- /dev/null +++ b/src/main/java/org/pdfbox/afmparser/package.html @@ -0,0 +1,12 @@ + + + + + + +This package holds classes used to parse AFM(Adobe Font Metrics) files. +
+More information about AFM files can be found at +http://partners.adobe.com/asn/developer/type/ + + diff --git a/src/main/java/org/pdfbox/afmtypes/CharMetric.java b/src/main/java/org/pdfbox/afmtypes/CharMetric.java new file mode 100644 index 0000000..7615845 --- /dev/null +++ b/src/main/java/org/pdfbox/afmtypes/CharMetric.java @@ -0,0 +1,299 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.afmtypes; + +import java.util.ArrayList; +import java.util.List; + +import org.pdfbox.util.BoundingBox; + +/** + * This class represents a single character metric. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.4 $ + */ +public class CharMetric +{ + private int characterCode; + + private float wx; + private float w0x; + private float w1x; + + private float wy; + private float w0y; + private float w1y; + + private float[] w; + private float[] w0; + private float[] w1; + private float[] vv; + + private String name; + private BoundingBox boundingBox; + private List ligatures = new ArrayList(); + + /** Getter for property boundingBox. + * @return Value of property boundingBox. + */ + public BoundingBox getBoundingBox() + { + return boundingBox; + } + + /** Setter for property boundingBox. + * @param bBox New value of property boundingBox. + */ + public void setBoundingBox(BoundingBox bBox) + { + boundingBox = bBox; + } + + /** Getter for property characterCode. + * @return Value of property characterCode. + */ + public int getCharacterCode() + { + return characterCode; + } + + /** Setter for property characterCode. + * @param cCode New value of property characterCode. + */ + public void setCharacterCode(int cCode) + { + characterCode = cCode; + } + + /** + * This will add an entry to the list of ligatures. + * + * @param ligature The ligature to add. + */ + public void addLigature( Ligature ligature ) + { + ligatures.add( ligature ); + } + + /** Getter for property ligatures. + * @return Value of property ligatures. + */ + public List getLigatures() + { + return ligatures; + } + + /** Setter for property ligatures. + * @param lig New value of property ligatures. + */ + public void setLigatures(List lig) + { + this.ligatures = lig; + } + + /** Getter for property name. + * @return Value of property name. + */ + public String getName() + { + return name; + } + + /** Setter for property name. + * @param n New value of property name. + */ + public void setName(String n) + { + this.name = n; + } + + /** Getter for property vv. + * @return Value of property vv. + */ + public float[] getVv() + { + return this.vv; + } + + /** Setter for property vv. + * @param vvValue New value of property vv. + */ + public void setVv(float[] vvValue) + { + this.vv = vvValue; + } + + /** Getter for property w. + * @return Value of property w. + */ + public float[] getW() + { + return this.w; + } + + /** Setter for property w. + * @param wValue New value of property w. + */ + public void setW(float[] wValue) + { + this.w = wValue; + } + + /** Getter for property w0. + * @return Value of property w0. + */ + public float[] getW0() + { + return this.w0; + } + + /** Setter for property w0. + * @param w0Value New value of property w0. + */ + public void setW0(float[] w0Value) + { + w0 = w0Value; + } + + /** Getter for property w0x. + * @return Value of property w0x. + */ + public float getW0x() + { + return w0x; + } + + /** Setter for property w0x. + * @param w0xValue New value of property w0x. + */ + public void setW0x(float w0xValue) + { + w0x = w0xValue; + } + + /** Getter for property w0y. + * @return Value of property w0y. + */ + public float getW0y() + { + return w0y; + } + + /** Setter for property w0y. + * @param w0yValue New value of property w0y. + */ + public void setW0y(float w0yValue) + { + w0y = w0yValue; + } + + /** Getter for property w1. + * @return Value of property w1. + */ + public float[] getW1() + { + return this.w1; + } + + /** Setter for property w1. + * @param w1Value New value of property w1. + */ + public void setW1(float[] w1Value) + { + w1 = w1Value; + } + + /** Getter for property w1x. + * @return Value of property w1x. + */ + public float getW1x() + { + return w1x; + } + + /** Setter for property w1x. + * @param w1xValue New value of property w1x. + */ + public void setW1x(float w1xValue) + { + w1x = w1xValue; + } + + /** Getter for property w1y. + * @return Value of property w1y. + */ + public float getW1y() + { + return w1y; + } + + /** Setter for property w1y. + * @param w1yValue New value of property w1y. + */ + public void setW1y(float w1yValue) + { + w1y = w1yValue; + } + + /** Getter for property wx. + * @return Value of property wx. + */ + public float getWx() + { + return wx; + } + + /** Setter for property wx. + * @param wxValue New value of property wx. + */ + public void setWx(float wxValue) + { + wx = wxValue; + } + + /** Getter for property wy. + * @return Value of property wy. + */ + public float getWy() + { + return wy; + } + + /** Setter for property wy. + * @param wyValue New value of property wy. + */ + public void setWy(float wyValue) + { + this.wy = wyValue; + } + +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/afmtypes/Composite.java b/src/main/java/org/pdfbox/afmtypes/Composite.java new file mode 100644 index 0000000..874e373 --- /dev/null +++ b/src/main/java/org/pdfbox/afmtypes/Composite.java @@ -0,0 +1,89 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.afmtypes; + +import java.util.ArrayList; +import java.util.List; + +/** + * This class represents composite character data. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.4 $ + */ +public class Composite +{ + private String name; + private List parts = new ArrayList(); + + /** Getter for property name. + * @return Value of property name. + */ + public String getName() + { + return name; + } + + /** Setter for property name. + * @param nameValue New value of property name. + */ + public void setName(String nameValue) + { + this.name = nameValue; + } + + /** + * This will add a composite part. + * + * @param part The composite part to add. + */ + public void addPart( CompositePart part ) + { + parts.add( part ); + } + + /** Getter for property parts. + * @return Value of property parts. + */ + public List getParts() + { + return parts; + } + + /** Setter for property parts. + * @param partsList New value of property parts. + */ + public void setParts(List partsList) + { + this.parts = partsList; + } + +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/afmtypes/CompositePart.java b/src/main/java/org/pdfbox/afmtypes/CompositePart.java new file mode 100644 index 0000000..b88ac9e --- /dev/null +++ b/src/main/java/org/pdfbox/afmtypes/CompositePart.java @@ -0,0 +1,93 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.afmtypes; + +/** + * This class represents a part of composite character data. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.5 $ + */ +public class CompositePart +{ + private String name; + private int xDisplacement; + private int yDisplacement; + + /** Getter for property name. + * @return Value of property name. + */ + public java.lang.String getName() + { + return name; + } + + /** Setter for property name. + * @param nameValue New value of property name. + */ + public void setName(String nameValue) + { + name = nameValue; + } + + /** Getter for property xDisplacement. + * @return Value of property xDisplacement. + */ + public int getXDisplacement() + { + return xDisplacement; + } + + /** Setter for property xDisplacement. + * @param xDisp New value of property xDisplacement. + */ + public void setXDisplacement(int xDisp) + { + xDisplacement = xDisp; + } + + /** Getter for property yDisplacement. + * @return Value of property yDisplacement. + */ + public int getYDisplacement() + { + return yDisplacement; + } + + /** Setter for property yDisplacement. + * @param yDisp New value of property yDisplacement. + */ + public void setYDisplacement(int yDisp) + { + yDisplacement = yDisp; + } + +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/afmtypes/FontMetric.java b/src/main/java/org/pdfbox/afmtypes/FontMetric.java new file mode 100644 index 0000000..b9fbeb8 --- /dev/null +++ b/src/main/java/org/pdfbox/afmtypes/FontMetric.java @@ -0,0 +1,891 @@ +/** + * Copyright (c) 2003-2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.afmtypes; + +import java.io.IOException; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.pdfbox.util.BoundingBox; + +/** + * This is the outermost AFM type. This can be created by the afmparser with a valid + * AFM document. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.7 $ + */ +public class FontMetric +{ + /** + * This is the version of the FontMetrics. + */ + private float afmVersion; + private int metricSets = 0; + private String fontName; + private String fullName; + private String familyName; + private String weight; + private BoundingBox fontBBox; + private String fontVersion; + private String notice; + private String encodingScheme; + private int mappingScheme; + private int escChar; + private String characterSet; + private int characters; + private boolean isBaseFont; + private float[] vVector; + private boolean isFixedV; + private float capHeight; + private float xHeight; + private float ascender; + private float descender; + private List comments = new ArrayList(); + + private float underlinePosition; + private float underlineThickness; + private float italicAngle; + private float[] charWidth; + private boolean isFixedPitch; + private float standardHorizontalWidth; + private float standardVerticalWidth; + + private List charMetrics = new ArrayList(); + private Map charMetricsMap = new HashMap(); + private List trackKern = new ArrayList(); + private List composites = new ArrayList(); + private List kernPairs = new ArrayList(); + private List kernPairs0 = new ArrayList(); + private List kernPairs1 = new ArrayList(); + + /** + * Constructor. + */ + public FontMetric() + { + } + + /** + * This will get the width of a character. + * + * @param name The character to get the width for. + * + * @return The width of the character. + * + * @throws IOException If this AFM file does not handle the character. + */ + public float getCharacterWidth( String name ) throws IOException + { + float result = 0; + CharMetric metric = (CharMetric)charMetricsMap.get( name ); + if( metric == null ) + { + result=0; + //don't throw an exception right away. + //throw new IOException( "Unknown AFM(" + getFullName() + ") characer '" + name + "'" ); + } + else + { + result = metric.getWx(); + } + return result; + } + + /** + * This will get the average width of a character. + * + * @return The width of the character. + * + * @throws IOException If this AFM file does not handle the character. + */ + public float getAverageCharacterWidth() throws IOException + { + float average = 0; + float totalWidths = 0; + float characterCount = 0; + Iterator iter = charMetricsMap.values().iterator(); + while( iter.hasNext() ) + { + CharMetric metric = (CharMetric)iter.next(); + if( metric.getWx() > 0 ) + { + totalWidths += metric.getWx(); + characterCount += 1; + } + } + if( totalWidths > 0 ) + { + average = totalWidths / characterCount; + } + + return average; + } + + /** + * This will add a new comment. + * + * @param comment The comment to add to this metric. + */ + public void addComment( String comment ) + { + comments.add( comment ); + } + + /** + * This will get all comments. + * + * @return The list of all comments. + */ + public List getComments() + { + return comments; + } + + /** + * This will get the version of the AFM document. + * + * @return The version of the document. + */ + public float getAFMVersion() + { + return afmVersion; + } + + /** + * This will get the metricSets attribute. + * + * @return The value of the metric sets. + */ + public int getMetricSets() + { + return metricSets; + } + + /** + * This will set the version of the AFM document. + * + * @param afmVersionValue The version of the document. + */ + public void setAFMVersion( float afmVersionValue ) + { + afmVersion = afmVersionValue; + } + + /** + * This will set the metricSets attribute. This value must be 0,1, or 2. + * + * @param metricSetsValue The new metric sets attribute. + */ + public void setMetricSets( int metricSetsValue ) + { + if( metricSetsValue < 0 || metricSetsValue > 2 ) + { + throw new RuntimeException( "The metricSets attribute must be in the " + + "set {0,1,2} and not '" + metricSetsValue + "'" ); + } + metricSets = metricSetsValue; + } + + /** + * Getter for property fontName. + * + * @return Value of property fontName. + */ + public String getFontName() + { + return fontName; + } + + /** + * Setter for property fontName. + * + * @param name New value of property fontName. + */ + public void setFontName(String name) + { + fontName = name; + } + + /** + * Getter for property fullName. + * + * @return Value of property fullName. + */ + public String getFullName() + { + return fullName; + } + + /** + * Setter for property fullName. + * + * @param fullNameValue New value of property fullName. + */ + public void setFullName(String fullNameValue) + { + fullName = fullNameValue; + } + + /** + * Getter for property familyName. + * + * @return Value of property familyName. + */ + public String getFamilyName() + { + return familyName; + } + + /** + * Setter for property familyName. + * + * @param familyNameValue New value of property familyName. + */ + public void setFamilyName(String familyNameValue) + { + familyName = familyNameValue; + } + + /** + * Getter for property weight. + * + * @return Value of property weight. + */ + public String getWeight() + { + return weight; + } + + /** + * Setter for property weight. + * + * @param weightValue New value of property weight. + */ + public void setWeight(String weightValue) + { + weight = weightValue; + } + + /** + * Getter for property fontBBox. + * + * @return Value of property fontBBox. + */ + public BoundingBox getFontBBox() + { + return fontBBox; + } + + /** + * Setter for property fontBBox. + * + * @param bBox New value of property fontBBox. + */ + public void setFontBBox(BoundingBox bBox) + { + this.fontBBox = bBox; + } + + /** + * Getter for property notice. + * + * @return Value of property notice. + */ + public String getNotice() + { + return notice; + } + + /** + * Setter for property notice. + * + * @param noticeValue New value of property notice. + */ + public void setNotice(String noticeValue) + { + notice = noticeValue; + } + + /** + * Getter for property encodingScheme. + * + * @return Value of property encodingScheme. + */ + public String getEncodingScheme() + { + return encodingScheme; + } + + /** + * Setter for property encodingScheme. + * + * @param encodingSchemeValue New value of property encodingScheme. + */ + public void setEncodingScheme(String encodingSchemeValue) + { + encodingScheme = encodingSchemeValue; + } + + /** + * Getter for property mappingScheme. + * + * @return Value of property mappingScheme. + */ + public int getMappingScheme() + { + return mappingScheme; + } + + /** + * Setter for property mappingScheme. + * + * @param mappingSchemeValue New value of property mappingScheme. + */ + public void setMappingScheme(int mappingSchemeValue) + { + mappingScheme = mappingSchemeValue; + } + + /** + * Getter for property escChar. + * + * @return Value of property escChar. + */ + public int getEscChar() + { + return escChar; + } + + /** + * Setter for property escChar. + * + * @param escCharValue New value of property escChar. + */ + public void setEscChar(int escCharValue) + { + escChar = escCharValue; + } + + /** + * Getter for property characterSet. + * + * @return Value of property characterSet. + */ + public String getCharacterSet() + { + return characterSet; + } + + /** + * Setter for property characterSet. + * + * @param characterSetValue New value of property characterSet. + */ + public void setCharacterSet(String characterSetValue) + { + characterSet = characterSetValue; + } + + /** + * Getter for property characters. + * + * @return Value of property characters. + */ + public int getCharacters() + { + return characters; + } + + /** + * Setter for property characters. + * + * @param charactersValue New value of property characters. + */ + public void setCharacters(int charactersValue) + { + characters = charactersValue; + } + + /** + * Getter for property isBaseFont. + * + * @return Value of property isBaseFont. + */ + public boolean isBaseFont() + { + return isBaseFont; + } + + /** + * Setter for property isBaseFont. + * + * @param isBaseFontValue New value of property isBaseFont. + */ + public void setIsBaseFont(boolean isBaseFontValue) + { + isBaseFont = isBaseFontValue; + } + + /** + * Getter for property vVector. + * + * @return Value of property vVector. + */ + public float[] getVVector() + { + return this.vVector; + } + + /** + * Setter for property vVector. + * + * @param vVectorValue New value of property vVector. + */ + public void setVVector(float[] vVectorValue) + { + vVector = vVectorValue; + } + + /** + * Getter for property isFixedV. + * + * @return Value of property isFixedV. + */ + public boolean isFixedV() + { + return isFixedV; + } + + /** + * Setter for property isFixedV. + * + * @param isFixedVValue New value of property isFixedV. + */ + public void setIsFixedV(boolean isFixedVValue) + { + isFixedV = isFixedVValue; + } + + /** + * Getter for property capHeight. + * + * @return Value of property capHeight. + */ + public float getCapHeight() + { + return capHeight; + } + + /** + * Setter for property capHeight. + * + * @param capHeightValue New value of property capHeight. + */ + public void setCapHeight(float capHeightValue) + { + capHeight = capHeightValue; + } + + /** + * Getter for property xHeight. + * + * @return Value of property xHeight. + */ + public float getXHeight() + { + return xHeight; + } + + /** + * Setter for property xHeight. + * + * @param xHeightValue New value of property xHeight. + */ + public void setXHeight( float xHeightValue ) + { + xHeight = xHeightValue; + } + + /** + * Getter for property ascender. + * + * @return Value of property ascender. + */ + public float getAscender() + { + return ascender; + } + + /** + * Setter for property ascender. + * + * @param ascenderValue New value of property ascender. + */ + public void setAscender( float ascenderValue ) + { + ascender = ascenderValue; + } + + /** + * Getter for property descender. + * + * @return Value of property descender. + */ + public float getDescender() + { + return descender; + } + + /** + * Setter for property descender. + * + * @param descenderValue New value of property descender. + */ + public void setDescender( float descenderValue ) + { + descender = descenderValue; + } + + /** + * Getter for property fontVersion. + * + * @return Value of property fontVersion. + */ + public String getFontVersion() + { + return fontVersion; + } + + /** + * Setter for property fontVersion. + * + * @param fontVersionValue New value of property fontVersion. + */ + public void setFontVersion(String fontVersionValue) + { + fontVersion = fontVersionValue; + } + + /** + * Getter for property underlinePosition. + * + * @return Value of property underlinePosition. + */ + public float getUnderlinePosition() + { + return underlinePosition; + } + + /** + * Setter for property underlinePosition. + * + * @param underlinePositionValue New value of property underlinePosition. + */ + public void setUnderlinePosition(float underlinePositionValue) + { + underlinePosition = underlinePositionValue; + } + + /** + * Getter for property underlineThickness. + * + * @return Value of property underlineThickness. + */ + public float getUnderlineThickness() + { + return underlineThickness; + } + + /** + * Setter for property underlineThickness. + * + * @param underlineThicknessValue New value of property underlineThickness. + */ + public void setUnderlineThickness(float underlineThicknessValue) + { + underlineThickness = underlineThicknessValue; + } + + /** + * Getter for property italicAngle. + * + * @return Value of property italicAngle. + */ + public float getItalicAngle() + { + return italicAngle; + } + + /** + * Setter for property italicAngle. + * + * @param italicAngleValue New value of property italicAngle. + */ + public void setItalicAngle(float italicAngleValue) + { + italicAngle = italicAngleValue; + } + + /** + * Getter for property charWidth. + * + * @return Value of property charWidth. + */ + public float[] getCharWidth() + { + return this.charWidth; + } + + /** + * Setter for property charWidth. + * + * @param charWidthValue New value of property charWidth. + */ + public void setCharWidth(float[] charWidthValue) + { + charWidth = charWidthValue; + } + + /** + * Getter for property isFixedPitch. + * + * @return Value of property isFixedPitch. + */ + public boolean isFixedPitch() + { + return isFixedPitch; + } + + /** + * Setter for property isFixedPitch. + * + * @param isFixedPitchValue New value of property isFixedPitch. + */ + public void setFixedPitch(boolean isFixedPitchValue) + { + isFixedPitch = isFixedPitchValue; + } + + /** Getter for property charMetrics. + * @return Value of property charMetrics. + */ + public List getCharMetrics() + { + return charMetrics; + } + + /** Setter for property charMetrics. + * @param charMetricsValue New value of property charMetrics. + */ + public void setCharMetrics(List charMetricsValue) + { + charMetrics = charMetricsValue; + } + + /** + * This will add another character metric. + * + * @param metric The character metric to add. + */ + public void addCharMetric( CharMetric metric ) + { + charMetrics.add( metric ); + charMetricsMap.put( metric.getName(), metric ); + } + + /** Getter for property trackKern. + * @return Value of property trackKern. + */ + public List getTrackKern() + { + return trackKern; + } + + /** Setter for property trackKern. + * @param trackKernValue New value of property trackKern. + */ + public void setTrackKern(List trackKernValue) + { + trackKern = trackKernValue; + } + + /** + * This will add another track kern. + * + * @param kern The track kerning data. + */ + public void addTrackKern( TrackKern kern ) + { + trackKern.add( kern ); + } + + /** Getter for property composites. + * @return Value of property composites. + */ + public List getComposites() + { + return composites; + } + + /** Setter for property composites. + * @param compositesList New value of property composites. + */ + public void setComposites(List compositesList) + { + composites = compositesList; + } + + /** + * This will add a single composite part to the picture. + * + * @param composite The composite info to add. + */ + public void addComposite( Composite composite ) + { + composites.add( composite ); + } + + /** Getter for property kernPairs. + * @return Value of property kernPairs. + */ + public java.util.List getKernPairs() + { + return kernPairs; + } + + /** + * This will add a kern pair. + * + * @param kernPair The kern pair to add. + */ + public void addKernPair( KernPair kernPair ) + { + kernPairs.add( kernPair ); + } + + /** Setter for property kernPairs. + * @param kernPairsList New value of property kernPairs. + */ + public void setKernPairs(java.util.List kernPairsList) + { + kernPairs = kernPairsList; + } + + /** Getter for property kernPairs0. + * @return Value of property kernPairs0. + */ + public java.util.List getKernPairs0() + { + return kernPairs0; + } + + /** + * This will add a kern pair. + * + * @param kernPair The kern pair to add. + */ + public void addKernPair0( KernPair kernPair ) + { + kernPairs0.add( kernPair ); + } + + /** Setter for property kernPairs0. + * @param kernPairs0List New value of property kernPairs0. + */ + public void setKernPairs0(java.util.List kernPairs0List) + { + kernPairs0 = kernPairs0List; + } + + /** Getter for property kernPairs1. + * @return Value of property kernPairs1. + */ + public java.util.List getKernPairs1() + { + return kernPairs1; + } + + /** + * This will add a kern pair. + * + * @param kernPair The kern pair to add. + */ + public void addKernPair1( KernPair kernPair ) + { + kernPairs1.add( kernPair ); + } + + /** Setter for property kernPairs1. + * @param kernPairs1List New value of property kernPairs1. + */ + public void setKernPairs1(java.util.List kernPairs1List) + { + kernPairs1 = kernPairs1List; + } + + /** Getter for property standardHorizontalWidth. + * @return Value of property standardHorizontalWidth. + */ + public float getStandardHorizontalWidth() + { + return standardHorizontalWidth; + } + + /** Setter for property standardHorizontalWidth. + * @param standardHorizontalWidthValue New value of property standardHorizontalWidth. + */ + public void setStandardHorizontalWidth(float standardHorizontalWidthValue) + { + standardHorizontalWidth = standardHorizontalWidthValue; + } + + /** Getter for property standardVerticalWidth. + * @return Value of property standardVerticalWidth. + */ + public float getStandardVerticalWidth() + { + return standardVerticalWidth; + } + + /** Setter for property standardVerticalWidth. + * @param standardVerticalWidthValue New value of property standardVerticalWidth. + */ + public void setStandardVerticalWidth(float standardVerticalWidthValue) + { + standardVerticalWidth = standardVerticalWidthValue; + } + +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/afmtypes/KernPair.java b/src/main/java/org/pdfbox/afmtypes/KernPair.java new file mode 100644 index 0000000..a822d22 --- /dev/null +++ b/src/main/java/org/pdfbox/afmtypes/KernPair.java @@ -0,0 +1,110 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.afmtypes; + +/** + * This represents some kern pair data. + * + * @author Ben Litchfied (ben@csh.rit.edu) + * @version $Revision: 1.4 $ + */ +public class KernPair +{ + private String firstKernCharacter; + private String secondKernCharacter; + private float x; + private float y; + + /** Getter for property firstKernCharacter. + * @return Value of property firstKernCharacter. + */ + public java.lang.String getFirstKernCharacter() + { + return firstKernCharacter; + } + + /** Setter for property firstKernCharacter. + * @param firstKernCharacterValue New value of property firstKernCharacter. + */ + public void setFirstKernCharacter(String firstKernCharacterValue) + { + firstKernCharacter = firstKernCharacterValue; + } + + /** Getter for property secondKernCharacter. + * @return Value of property secondKernCharacter. + */ + public java.lang.String getSecondKernCharacter() + { + return secondKernCharacter; + } + + /** Setter for property secondKernCharacter. + * @param secondKernCharacterValue New value of property secondKernCharacter. + */ + public void setSecondKernCharacter(String secondKernCharacterValue) + { + secondKernCharacter = secondKernCharacterValue; + } + + /** Getter for property x. + * @return Value of property x. + */ + public float getX() + { + return x; + } + + /** Setter for property x. + * @param xValue New value of property x. + */ + public void setX(float xValue) + { + x = xValue; + } + + /** Getter for property y. + * @return Value of property y. + */ + public float getY() + { + return y; + } + + /** Setter for property y. + * @param yValue New value of property y. + */ + public void setY(float yValue) + { + y = yValue; + } + +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/afmtypes/Ligature.java b/src/main/java/org/pdfbox/afmtypes/Ligature.java new file mode 100644 index 0000000..99e6ae9 --- /dev/null +++ b/src/main/java/org/pdfbox/afmtypes/Ligature.java @@ -0,0 +1,76 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.afmtypes; + +/** + * This class represents a ligature, which is an entry of the CharMetrics. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.4 $ + */ +public class Ligature +{ + private String successor; + private String ligature; + + /** Getter for property ligature. + * @return Value of property ligature. + */ + public String getLigature() + { + return ligature; + } + + /** Setter for property ligature. + * @param lig New value of property ligature. + */ + public void setLigature(String lig) + { + ligature = lig; + } + + /** Getter for property successor. + * @return Value of property successor. + */ + public String getSuccessor() + { + return successor; + } + + /** Setter for property successor. + * @param successorValue New value of property successor. + */ + public void setSuccessor(String successorValue) + { + successor = successorValue; + } + +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/afmtypes/TrackKern.java b/src/main/java/org/pdfbox/afmtypes/TrackKern.java new file mode 100644 index 0000000..a806850 --- /dev/null +++ b/src/main/java/org/pdfbox/afmtypes/TrackKern.java @@ -0,0 +1,127 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.afmtypes; + +/** + * This class represents a piece of track kerning data. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.4 $ + */ +public class TrackKern +{ + private int degree; + private float minPointSize; + private float minKern; + private float maxPointSize; + private float maxKern; + + /** Getter for property degree. + * @return Value of property degree. + */ + public int getDegree() + { + return degree; + } + + /** Setter for property degree. + * @param degreeValue New value of property degree. + */ + public void setDegree(int degreeValue) + { + degree = degreeValue; + } + + /** Getter for property maxKern. + * @return Value of property maxKern. + */ + public float getMaxKern() + { + return maxKern; + } + + /** Setter for property maxKern. + * @param maxKernValue New value of property maxKern. + */ + public void setMaxKern(float maxKernValue) + { + maxKern = maxKernValue; + } + + /** Getter for property maxPointSize. + * @return Value of property maxPointSize. + */ + public float getMaxPointSize() + { + return maxPointSize; + } + + /** Setter for property maxPointSize. + * @param maxPointSizeValue New value of property maxPointSize. + */ + public void setMaxPointSize(float maxPointSizeValue) + { + maxPointSize = maxPointSizeValue; + } + + /** Getter for property minKern. + * @return Value of property minKern. + */ + public float getMinKern() + { + return minKern; + } + + /** Setter for property minKern. + * @param minKernValue New value of property minKern. + */ + public void setMinKern(float minKernValue) + { + minKern = minKernValue; + } + + /** Getter for property minPointSize. + * @return Value of property minPointSize. + */ + public float getMinPointSize() + { + return minPointSize; + } + + /** Setter for property minPointSize. + * @param minPointSizeValue New value of property minPointSize. + */ + public void setMinPointSize(float minPointSizeValue) + { + minPointSize = minPointSizeValue; + } + +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/afmtypes/package.html b/src/main/java/org/pdfbox/afmtypes/package.html new file mode 100644 index 0000000..e565720 --- /dev/null +++ b/src/main/java/org/pdfbox/afmtypes/package.html @@ -0,0 +1,9 @@ + + + + + + +This package contains all the base types that can be found in an AFM file. + + diff --git a/src/main/java/org/pdfbox/ant/PDFToTextTask.java b/src/main/java/org/pdfbox/ant/PDFToTextTask.java new file mode 100644 index 0000000..56ef42b --- /dev/null +++ b/src/main/java/org/pdfbox/ant/PDFToTextTask.java @@ -0,0 +1,100 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.ant; + +import java.io.File; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.apache.tools.ant.DirectoryScanner; +import org.apache.tools.ant.Task; + +import org.apache.tools.ant.types.FileSet; + +/** + * This is an ant task that will allow pdf documents to be converted using an + * and task. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.7 $ + */ +public class PDFToTextTask extends Task +{ + private List fileSets = new ArrayList(); + + /** + * Adds a set of files (nested fileset attribute). + * + * @param set Another fileset to add. + */ + public void addFileset( FileSet set ) + { + fileSets.add( set ); + } + + /** + * This will perform the execution. + */ + public void execute() + { + log( "PDFToTextTask executing" ); + Iterator fileSetIter = fileSets.iterator(); + while( fileSetIter.hasNext() ) + { + FileSet next = (FileSet)fileSetIter.next(); + DirectoryScanner dirScanner = next.getDirectoryScanner( getProject() ); + dirScanner.scan(); + String[] files = dirScanner.getIncludedFiles(); + for( int i=0; i + + + + + +ANT tasks that utilize PDFBox features can be found in this package. +This is an example of using the PDF2Text task:

+ +<taskdef name="pdf2text" classname="org.pdfbox.ant.PDFToTextTask" classpathref="build.classpath" />
+ +<pdf2text>
+   <fileset dir="test">
+     <include name="**/*.pdf" />
+   </fileset>
+</pdf2text>
+ + diff --git a/src/main/java/org/pdfbox/cmapparser/CMapParser.java b/src/main/java/org/pdfbox/cmapparser/CMapParser.java new file mode 100644 index 0000000..5434bb7 --- /dev/null +++ b/src/main/java/org/pdfbox/cmapparser/CMapParser.java @@ -0,0 +1,285 @@ +/** + * Copyright (c) 2003-2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.cmapparser; + +import java.io.FileInputStream; +import java.io.InputStream; +import java.io.IOException; +import java.io.RandomAccessFile; + +import java.util.List; + +import org.pdfbox.cmaptypes.CMap; +import org.pdfbox.cmaptypes.CodespaceRange; + +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSName; +import org.pdfbox.cos.COSNumber; +import org.pdfbox.cos.COSString; + +import org.pdfbox.pdfparser.PDFStreamParser; + +import org.pdfbox.util.PDFOperator; + +/** + * This will parser a CMap stream. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.10 $ + */ +public class CMapParser +{ + private static final String BEGIN_CODESPACE_RANGE = "begincodespacerange"; + private static final String BEGIN_BASE_FONT_CHAR = "beginbfchar"; + private static final String BEGIN_BASE_FONT_RANGE = "beginbfrange"; + + private InputStream input; + private CMap result; + private RandomAccessFile file; + + /** + * Creates a new instance of CMapParser. + * + * @param in The input stream to read data from. + * @param raf The random access file from the document + */ + public CMapParser( InputStream in, RandomAccessFile raf ) + { + input = in; + file = raf; + } + + /** + * This will get the results of the parsing. parse() must be called first. + * + * @return The parsed CMap file. + */ + public CMap getResult() + { + return result; + } + + /** + * This will parse the stream and create a cmap object. + * + * @throws IOException If there is an error parsing the stream. + */ + public void parse() throws IOException + { + result = new CMap(); + PDFStreamParser parser = new PDFStreamParser( input, file ); + parser.parse(); + List tokens = parser.getTokens(); + for( int i=0; i= 0 ) + { + done = true; + } + value = createStringFromBytes( tokenBytes ); + result.addMapping( startBytes, value ); + increment( startBytes ); + + if( array == null ) + { + increment( tokenBytes ); + } + else + { + if( arrayIndex < array.size() ) + { + tokenBytes = ((COSString)array.getObject( arrayIndex++ )).getBytes(); + } + } + } + } + } + } + } + } + + private void increment( byte[] data ) + { + increment( data, data.length-1 ); + } + + private void increment( byte[] data, int position ) + { + if( position > 0 && (data[position]+256)%256 == 255 ) + { + data[position]=0; + increment( data, position-1); + } + else + { + data[position] = (byte)(data[position]+1); + } + } + + private String createStringFromBytes( byte[] bytes ) throws IOException + { + String retval = null; + if( bytes.length == 1 ) + { + retval = new String( bytes ); + } + else + { + retval = new String( bytes, "UTF-16BE" ); + } + return retval; + } + + private int compare( byte[] first, byte[] second ) + { + int retval = 1; + boolean done = false; + for( int i=0; i" ); + System.exit( -1 ); + } + CMapParser parser = new CMapParser( new FileInputStream( args[0] ), null ); + parser.parse(); + CMap result = parser.getResult(); + System.out.println( "Result:" + result ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/cmapparser/package.html b/src/main/java/org/pdfbox/cmapparser/package.html new file mode 100644 index 0000000..929bcb2 --- /dev/null +++ b/src/main/java/org/pdfbox/cmapparser/package.html @@ -0,0 +1,9 @@ + + + + + + +This package holds classes that are necessary to parse cmap files. + + diff --git a/src/main/java/org/pdfbox/cmaptypes/CMap.java b/src/main/java/org/pdfbox/cmaptypes/CMap.java new file mode 100644 index 0000000..a8f7fec --- /dev/null +++ b/src/main/java/org/pdfbox/cmaptypes/CMap.java @@ -0,0 +1,161 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.cmaptypes; + +import java.io.IOException; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * This class represents a CMap file. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.6 $ + */ +public class CMap +{ + private List codeSpaceRanges = new ArrayList(); + private Map singleByteMappings = new HashMap(); + private Map doubleByteMappings = new HashMap(); + + /** + * Creates a new instance of CMap. + */ + public CMap() + { + //default constructor + } + + /** + * This will tell if this cmap has any one byte mappings. + * + * @return true If there are any one byte mappings, false otherwise. + */ + public boolean hasOneByteMappings() + { + return singleByteMappings.size() > 0; + } + + /** + * This will tell if this cmap has any two byte mappings. + * + * @return true If there are any two byte mappings, false otherwise. + */ + public boolean hasTwoByteMappings() + { + return doubleByteMappings.size() > 0; + } + + /** + * This will perform a lookup into the map. + * + * @param code The code used to lookup. + * @param offset The offset into the byte array. + * @param length The length of the data we are getting. + * + * @return The string that matches the lookup. + */ + public String lookup( byte[] code, int offset, int length ) + { + + String result = null; + Integer key = null; + if( length == 1 ) + { + + key = new Integer( (code[offset]+256)%256 ); + result = (String)singleByteMappings.get( key ); + } + else if( length == 2 ) + { + int intKey = (code[offset]+256)%256; + intKey <<= 8; + intKey += (code[offset+1]+256)%256; + key = new Integer( intKey ); + + result = (String)doubleByteMappings.get( key ); + } + + return result; + } + + /** + * This will add a mapping. + * + * @param src The src to the mapping. + * @param dest The dest to the mapping. + * + * @throws IOException if the src is invalid. + */ + public void addMapping( byte[] src, String dest ) throws IOException + { + if( src.length == 1 ) + { + singleByteMappings.put( new Integer( src[0] ), dest ); + } + else if( src.length == 2 ) + { + int intSrc = src[0]; + intSrc <<= 8; + intSrc |= (src[1]&0xFF); + doubleByteMappings.put( new Integer( intSrc ), dest ); + } + else + { + throw new IOException( "Mapping code should be 1 or two bytes and not " + src.length ); + } + } + + + /** + * This will add a codespace range. + * + * @param range A single codespace range. + */ + public void addCodespaceRange( CodespaceRange range ) + { + codeSpaceRanges.add( range ); + } + + /** + * Getter for property codeSpaceRanges. + * + * @return Value of property codeSpaceRanges. + */ + public List getCodeSpaceRanges() + { + return codeSpaceRanges; + } + +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/cmaptypes/CodespaceRange.java b/src/main/java/org/pdfbox/cmaptypes/CodespaceRange.java new file mode 100644 index 0000000..0f1ab2e --- /dev/null +++ b/src/main/java/org/pdfbox/cmaptypes/CodespaceRange.java @@ -0,0 +1,88 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.cmaptypes; + +/** + * This represents a single entry in the codespace range. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.3 $ + */ +public class CodespaceRange +{ + + private byte[] start; + private byte[] end; + + /** + * Creates a new instance of CodespaceRange. + */ + public CodespaceRange() + { + } + + /** Getter for property end. + * @return Value of property end. + * + */ + public byte[] getEnd() + { + return this.end; + } + + /** Setter for property end. + * @param endBytes New value of property end. + * + */ + public void setEnd(byte[] endBytes) + { + end = endBytes; + } + + /** Getter for property start. + * @return Value of property start. + * + */ + public byte[] getStart() + { + return this.start; + } + + /** Setter for property start. + * @param startBytes New value of property start. + * + */ + public void setStart(byte[] startBytes) + { + start = startBytes; + } + +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/cmaptypes/package.html b/src/main/java/org/pdfbox/cmaptypes/package.html new file mode 100644 index 0000000..f1bfcac --- /dev/null +++ b/src/main/java/org/pdfbox/cmaptypes/package.html @@ -0,0 +1,9 @@ + + + + + + +This package holds classes that are used to represent cmap files as java objects. + + diff --git a/src/main/java/org/pdfbox/cos/COSArray.java b/src/main/java/org/pdfbox/cos/COSArray.java new file mode 100644 index 0000000..cb7d278 --- /dev/null +++ b/src/main/java/org/pdfbox/cos/COSArray.java @@ -0,0 +1,492 @@ +/** + * Copyright (c) 2003-2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.cos; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; + + + +import org.pdfbox.exceptions.COSVisitorException; +import org.pdfbox.pdmodel.common.COSObjectable; + +/** + * An array of PDFBase objects as part of the PDF document. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.22 $ + */ +public class COSArray extends COSBase +{ + private List objects = new ArrayList(); + + /** + * Constructor. + */ + public COSArray() + { + //default constructor + } + + /** + * This will add an object to the array. + * + * @param object The object to add to the array. + */ + public void add( COSBase object ) + { + objects.add( object ); + } + + /** + * This will add an object to the array. + * + * @param object The object to add to the array. + */ + public void add( COSObjectable object ) + { + objects.add( object.getCOSObject() ); + } + + /** + * Add the specified object at the ith location and push the rest to the + * right. + * + * @param i The index to add at. + * @param object The object to add at that index. + */ + public void add( int i, COSBase object) + { + objects.add( i, object ); + } + + /** + * This will remove all of the objects in the collection. + */ + public void clear() + { + objects.clear(); + } + + /** + * This will remove all of the objects in the collection. + * + * @param objectsList The list of objects to remove from the collection. + */ + public void removeAll( Collection objectsList ) + { + objects.removeAll( objectsList ); + } + + /** + * This will retain all of the objects in the collection. + * + * @param objectsList The list of objects to retain from the collection. + */ + public void retainAll( Collection objectsList ) + { + objects.retainAll( objectsList ); + } + + /** + * This will add an object to the array. + * + * @param objectsList The object to add to the array. + */ + public void addAll( Collection objectsList ) + { + objects.addAll( objectsList ); + } + + /** + * This will add all objects to this array. + * + * @param objectList The objects to add. + */ + public void addAll( COSArray objectList ) + { + objects.addAll( objectList.objects ); + } + + /** + * Add the specified object at the ith location and push the rest to the + * right. + * + * @param i The index to add at. + * @param objectList The object to add at that index. + */ + public void addAll( int i, Collection objectList ) + { + objects.addAll( i, objectList ); + } + + /** + * This will set an object at a specific index. + * + * @param index zero based index into array. + * @param object The object to set. + */ + public void set( int index, COSBase object ) + { + objects.set( index, object ); + } + + /** + * This will set an object at a specific index. + * + * @param index zero based index into array. + * @param intVal The object to set. + */ + public void set( int index, int intVal ) + { + objects.set( index, new COSInteger( intVal ) ); + } + + /** + * This will set an object at a specific index. + * + * @param index zero based index into array. + * @param object The object to set. + */ + public void set( int index, COSObjectable object ) + { + COSBase base = null; + if( object != null ) + { + base = object.getCOSObject(); + } + objects.set( index, base ); + } + + /** + * This will get an object from the array. This will dereference the object. + * If the object is COSNull then null will be returned. + * + * @param index The index into the array to get the object. + * + * @return The object at the requested index. + */ + public COSBase getObject( int index ) + { + Object obj = objects.get( index ); + if( obj instanceof COSObject ) + { + obj = ((COSObject)obj).getObject(); + } + if( obj instanceof COSNull ) + { + obj = null; + } + return (COSBase)obj; + } + + /** + * This will get an object from the array. This will NOT derefernce + * the COS object. + * + * @param index The index into the array to get the object. + * + * @return The object at the requested index. + */ + public COSBase get( int index ) + { + return (COSBase)objects.get( index ); + } + + /** + * Get the value of the array as an integer. + * + * @param index The index into the list. + * + * @return The value at that index or -1 if it is null. + */ + public int getInt( int index ) + { + return getInt( index, -1 ); + } + + /** + * Get the value of the array as an integer, return the default if it does + * not exist. + * + * @param index The value of the array. + * @param defaultValue The value to return if the value is null. + * @return The value at the index or the defaultValue. + */ + public int getInt( int index, int defaultValue ) + { + int retval = defaultValue; + if( defaultValue < size() ) + { + COSNumber number = (COSNumber)get( index ); + if( number != null ) + { + retval = number.intValue(); + } + } + return retval; + } + + /** + * Set the value in the array as an integer. + * + * @param index The index into the array. + * @param value The value to set. + */ + public void setInt( int index, int value ) + { + set( index, new COSInteger( value ) ); + } + + /** + * Set the value in the array as a name. + * @param index The index into the array. + * @param name The name to set in the array. + */ + public void setName( int index, String name ) + { + set( index, COSName.getPDFName( name ) ); + } + + /** + * Get the value of the array as a string. + * + * @param index The index into the array. + * @return The name converted to a string or null if it does not exist. + */ + public String getName( int index ) + { + return getName( index, null ); + } + + /** + * Get an entry in the array that is expected to be a COSName. + * @param index The index into the array. + * @param defaultValue The value to return if it is null. + * @return The value at the index or defaultValue if none is found. + */ + public String getName( int index, String defaultValue ) + { + String retval = defaultValue; + if( index < size() ) + { + COSName name = (COSName)get( index ); + if( name != null ) + { + retval = name.getName(); + } + } + return retval; + } + + /** + * Set the value in the array as a string. + * @param index The index into the array. + * @param string The string to set in the array. + */ + public void setString( int index, String string ) + { + set( index, new COSString( string ) ); + } + + /** + * Get the value of the array as a string. + * + * @param index The index into the array. + * @return The string or null if it does not exist. + */ + public String getString( int index ) + { + return getString( index, null ); + } + + /** + * Get an entry in the array that is expected to be a COSName. + * @param index The index into the array. + * @param defaultValue The value to return if it is null. + * @return The value at the index or defaultValue if none is found. + */ + public String getString( int index, String defaultValue ) + { + String retval = defaultValue; + if( index < size() ) + { + COSString string = (COSString)get( index ); + if( string != null ) + { + retval = string.getString(); + } + } + return retval; + } + + /** + * This will get the size of this array. + * + * @return The number of elements in the array. + */ + public int size() + { + return objects.size(); + } + + /** + * This will remove an element from the array. + * + * @param i The index of the object to remove. + * + * @return The object that was removed. + */ + public COSBase remove( int i ) + { + return (COSBase)objects.remove( i ); + } + + /** + * This will remove an element from the array. + * + * @param o The object to remove. + * + * @return The object that was removed. + */ + public boolean remove( COSBase o ) + { + return objects.remove( o ); + } + + /** + * @see Object#toString() + */ + public String toString() + { + return "COSArray{" + objects + "}"; + } + + /** + * Get access to the list. + * + * @return an iterator over the array elements + */ + public Iterator iterator() + { + return objects.iterator(); + } + + /** + * This will return the index of the entry or -1 if it is not found. + * + * @param object The object to search for. + * @return The index of the object or -1. + */ + public int indexOf( COSBase object ) + { + int retval = -1; + for( int i=0; retval < 0 && i> 32)); + } + + /** + * @see Object#toString() + */ + public String toString() + { + return "COSInt{" + value + "}"; + } + + /** + * Change the value of this reference. + * + * @param newValue The new value. + */ + public void setValue( long newValue ) + { + value = newValue; + } + + + + /** + * polymorphic access to value as float. + * + * @return The float value of this object. + */ + public float floatValue() + { + return (float)value; + } + + /** + * polymorphic access to value as float. + * + * @return The double value of this object. + */ + public double doubleValue() + { + return (double)value; + } + + /** + * Polymorphic access to value as int + * This will get the integer value of this object. + * + * @return The int value of this object, + */ + public int intValue() + { + return (int)value; + } + + /** + * Polymorphic access to value as int + * This will get the integer value of this object. + * + * @return The int value of this object, + */ + public long longValue() + { + return value; + } + + /** + * visitor pattern double dispatch method. + * + * @param visitor The object to notify when visiting this object. + * @return any object, depending on the visitor implementation, or null + * @throws COSVisitorException If an error occurs while visiting this object. + */ + public Object accept(ICOSVisitor visitor) throws COSVisitorException + { + return visitor.visitFromInt(this); + } + + /** + * This will output this string as a PDF object. + * + * @param output The stream to write to. + * @throws IOException If there is an error writing to the stream. + */ + public void writePDF( OutputStream output ) throws IOException + { + output.write(String.valueOf(value).getBytes()); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/cos/COSName.java b/src/main/java/org/pdfbox/cos/COSName.java new file mode 100644 index 0000000..8532cc4 --- /dev/null +++ b/src/main/java/org/pdfbox/cos/COSName.java @@ -0,0 +1,572 @@ +/** + * Copyright (c) 2003-2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.cos; + +import java.io.IOException; +import java.io.OutputStream; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.pdfbox.exceptions.COSVisitorException; +import org.pdfbox.persistence.util.COSHEXTable; + + +/** + * This class represents a PDF named object. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.38 $ + */ +public final class COSName extends COSBase implements Comparable +{ + /** + * Note: This is synchronized because a HashMap must be synchronized if accessed by + * multiple threads. + */ + private static Map nameMap = Collections.synchronizedMap( new HashMap(8192) ); + + + /** + * A common COSName value. + */ + public static final COSName AA = new COSName( "AA" ); + /** + * A common COSName value. + */ + public static final COSName ACRO_FORM = new COSName( "AcroForm" ); + /** + * A common COSName value. + */ + public static final COSName ANNOTS = new COSName( "Annots" ); + /** + * A common COSName value. + */ + public static final COSName ART_BOX = new COSName("ArtBox" ); + /** + * A common COSName value. + */ + public static final COSName ASCII85_DECODE = new COSName( "ASCII85Decode" ); + /** + * A common COSName value. + */ + public static final COSName ASCII85_DECODE_ABBREVIATION = new COSName( "A85" ); + /** + * A common COSName value. + */ + public static final COSName ASCII_HEX_DECODE = new COSName( "ASCIIHexDecode" ); + /** + * A common COSName value. + */ + public static final COSName ASCII_HEX_DECODE_ABBREVIATION = new COSName( "AHx" ); + /** + * A common COSName value. + */ + public static final COSName AP = new COSName( "AP" ); + /** + * A common COSName value. + */ + public static final COSName B = new COSName( "B" ); + /** + * A common COSName value. + */ + public static final COSName BASE_ENCODING = new COSName( "BaseEncoding" ); + /** + * A common COSName value. + */ + public static final COSName BASE_FONT = new COSName( "BaseFont" ); + /** + * A common COSName value. + */ + public static final COSName BBOX = new COSName( "BBox" ); + /** + * A common COSName value. + */ + public static final COSName BLEED_BOX = new COSName("BleedBox" ); + /** + * A common COSName value. + */ + public static final COSName CATALOG = new COSName( "Catalog" ); + /** + * A common COSName value. + */ + public static final COSName CALGRAY = new COSName( "CalGray" ); + /** + * A common COSName value. + */ + public static final COSName CALRGB = new COSName( "CalRGB" ); + /** + * A common COSName value. + */ + public static final COSName CCITTFAX_DECODE = new COSName( "CCITTFaxDecode" ); + /** + * A common COSName value. + */ + public static final COSName CCITTFAX_DECODE_ABBREVIATION = new COSName( "CCF" ); + /** + * A common COSName value. + */ + public static final COSName COLORSPACE = new COSName( "ColorSpace" ); + /** + * A common COSName value. + */ + public static final COSName CONTENTS = new COSName( "Contents" ); + /** + * A common COSName value. + */ + public static final COSName COUNT = new COSName( "Count" ); + /** + * A common COSName value. + */ + public static final COSName CROP_BOX = new COSName( "CropBox" ); + /** + * A common COSName value. + */ + public static final COSName DESCENDANT_FONTS = new COSName( "DescendantFonts" ); + /** + * A common COSName value. + */ + public static final COSName DIFFERENCES = new COSName( "Differences" ); + /** + * A common COSName value. + */ + public static final COSName DCT_DECODE = new COSName( "DCTDecode" ); + /** + * A common COSName value. + */ + public static final COSName DCT_DECODE_ABBREVIATION = new COSName( "DCT" ); + /** + * A common COSName value. + */ + public static final COSName DEVICECMYK = new COSName( "DeviceCMYK" ); + /** + * A common COSName value. + */ + public static final COSName DEVICEGRAY = new COSName( "DeviceGray" ); + /** + * A common COSName value. + */ + public static final COSName DEVICEN = new COSName( "DeviceN" ); + /** + * A common COSName value. + */ + public static final COSName DEVICERGB = new COSName( "DeviceRGB" ); + /** + * A common COSName value. + */ + public static final COSName DV = new COSName( "DV" ); + /** + * A common COSName value. + */ + public static final COSName ENCODING = new COSName( "Encoding" ); + /** + * A common COSName value. + */ + public static final COSName FIELDS = new COSName( "Fields" ); + /** + * A common COSName value. + */ + public static final COSName FILTER = new COSName( "Filter" ); + /** + * A common COSName value. + */ + public static final COSName FIRST_CHAR = new COSName( "FirstChar" ); + /** + * A common COSName value. + */ + public static final COSName FLATE_DECODE = new COSName( "FlateDecode" ); + /** + * A common COSName value. + */ + public static final COSName FLATE_DECODE_ABBREVIATION = new COSName( "Fl" ); + /** + * A common COSName value. + */ + public static final COSName FONT = new COSName( "Font" ); + /** + * A common COSName value. + */ + public static final COSName FONT_FILE = new COSName("FontFile"); + /** + * A common COSName value. + */ + public static final COSName FONT_FILE2 = new COSName("FontFile2"); + /** + * A common COSName value. + */ + public static final COSName FONT_FILE3 = new COSName("FontFile3"); + /** + * A common COSName value. + */ + public static final COSName FONT_DESC = new COSName("FontDescriptor"); + /** + * A common COSName value. + */ + public static final COSName FONT_MATRIX = new COSName("FontMatrix" ); + /** + * A common COSName value. + */ + public static final COSName FORMTYPE = new COSName( "FormType" ); + /** + * A common COSName value. + */ + public static final COSName FRM = new COSName( "FRM" ); + /** + * A common COSName value. + */ + public static final COSName HEIGHT = new COSName( "Height" ); + /** + * A common COSName value. + */ + public static final COSName ICCBASED = new COSName( "ICCBased" ); + /** + * A common COSName value. + */ + public static final COSName IDENTITY_H = new COSName( "Identity-H" ); + /** + * A common COSName value. + */ + public static final COSName IMAGE = new COSName( "Image" ); + /** + * A common COSName value. + */ + public static final COSName INDEXED = new COSName( "Indexed" ); + /** + * A common COSName value. + */ + public static final COSName INFO = new COSName( "Info" ); + /** + * A common COSName value. + */ + public static final COSName JPX_DECODE = new COSName( "JPXDecode" ); + /** + * A common COSName value. + */ + public static final COSName KIDS = new COSName( "Kids" ); + /** + * A common COSName value. + */ + public static final COSName LAB = new COSName( "Lab" ); + /** + * A common COSName value. + */ + public static final COSName LAST_CHAR = new COSName( "LastChar" ); + /** + * A common COSName value. + */ + public static final COSName LENGTH = new COSName( "Length" ); + /** + * A common COSName value. + */ + public static final COSName LENGTH1 = new COSName( "Length1" ); + /** + * A common COSName value. + */ + public static final COSName LZW_DECODE = new COSName( "LZWDecode" ); + /** + * A common COSName value. + */ + public static final COSName LZW_DECODE_ABBREVIATION = new COSName( "LZW" ); + /** + * A common COSName value. + */ + public static final COSName MAC_ROMAN_ENCODING = new COSName( "MacRomanEncoding" ); + /** + * A common COSName value. + */ + public static final COSName MATRIX = new COSName( "Matrix" ); + /** + * A common COSName value. + */ + public static final COSName MEDIA_BOX = new COSName( "MediaBox" ); + /** + * A common COSName value. + */ + public static final COSName METADATA = new COSName( "Metadata" ); + /** + * A common COSName value. + */ + public static final COSName N = new COSName( "N" ); + /** + * A common COSName value. + */ + public static final COSName NAME = new COSName( "Name" ); + /** + * A common COSName value. + */ + public static final COSName P = new COSName( "P" ); + /** + * A common COSName value. + */ + public static final COSName PAGE = new COSName( "Page" ); + /** + * A common COSName value. + */ + public static final COSName PAGES = new COSName( "Pages" ); + /** + * A common COSName value. + */ + public static final COSName PARENT = new COSName( "Parent" ); + /** + * A common COSName value. + */ + public static final COSName PATTERN = new COSName( "Pattern" ); + /** + * A common COSName value. + */ + public static final COSName PDF_DOC_ENCODING = new COSName( "PDFDocEncoding" ); + /** + * A common COSName value. + */ + public static final COSName PREV = new COSName( "Prev" ); + /** + * A common COSName value. + */ + public static final COSName R = new COSName( "R" ); + /** + * A common COSName value. + */ + public static final COSName RESOURCES = new COSName( "Resources" ); + /** + * A common COSName value. + */ + public static final COSName ROOT = new COSName( "Root" ); + /** + * A common COSName value. + */ + public static final COSName ROTATE = new COSName( "Rotate" ); + /** + * A common COSName value. + */ + public static final COSName RUN_LENGTH_DECODE = new COSName( "RunLengthDecode" ); + /** + * A common COSName value. + */ + public static final COSName RUN_LENGTH_DECODE_ABBREVIATION = new COSName( "RL" ); + /** + * A common COSName value. + */ + public static final COSName SEPARATION = new COSName( "Separation" ); + /** + * A common COSName value. + */ + public static final COSName STANDARD_ENCODING = new COSName( "StandardEncoding" ); + /** + * A common COSName value. + */ + public static final COSName SUBTYPE = new COSName( "Subtype" ); + /** + * A common COSName value. + */ + public static final COSName TRIM_BOX = new COSName("TrimBox" ); + /** + * A common COSName value. + */ + public static final COSName TRUE_TYPE = new COSName("TrueType" ); + /** + * A common COSName value. + */ + public static final COSName TO_UNICODE = new COSName( "ToUnicode" ); + /** + * A common COSName value. + */ + public static final COSName TYPE = new COSName( "Type" ); + /** + * A common COSName value. + */ + public static final COSName TYPE0 = new COSName( "Type0" ); + /** + * A common COSName value. + */ + public static final COSName V = new COSName( "V" ); + /** + * A common COSName value. + */ + public static final COSName VERSION = new COSName( "Version" ); + /** + * A common COSName value. + */ + public static final COSName WIDTHS = new COSName( "Widths" ); + /** + * A common COSName value. + */ + public static final COSName WIN_ANSI_ENCODING = new COSName( "WinAnsiEncoding" ); + /** + * A common COSName value. + */ + public static final COSName XOBJECT = new COSName( "XObject" ); + + /** + * The prefix to a PDF name. + */ + public static final byte[] NAME_PREFIX = new byte[] { 47 }; // The / character + /** + * The escape character for a name. + */ + public static final byte[] NAME_ESCAPE = new byte[] { 35 }; //The # character + + private String name; + private int hashCode; + + /** + * This will get a COSName object with that name. + * + * @param aName The name of the object. + * + * @return A COSName with the specified name. + */ + public static final COSName getPDFName( String aName ) + { + COSName name = null; + if( aName != null ) + { + name = (COSName)nameMap.get( aName ); + if( name == null ) + { + //name is added to map in the constructor + name = new COSName( aName ); + } + } + return name; + } + + /** + * Private constructor. This will limit the number of COSName objects. + * that are created. + * + * @param aName The name of the COSName object. + */ + private COSName( String aName ) + { + name = aName; + nameMap.put( aName, this ); + hashCode = name.hashCode(); + } + + /** + * This will get the name of this COSName object. + * + * @return The name of the object. + */ + public String getName() + { + return name; + } + + /** + * @see Object#toString() + */ + public String toString() + { + return "COSName{" + name + "}"; + } + + /** + * @see Object#equals( Object ) + */ + public boolean equals( Object o ) + { + boolean retval = this == o; + if( !retval && o instanceof COSName ) + { + COSName other = (COSName)o; + retval = name == other.name || name.equals( other.name ); + } + return retval; + } + + /** + * @see Object#hashCode() + */ + public int hashCode() + { + return hashCode; + } + + /** + * @see Comparable#compareTo( Object ) + */ + public int compareTo(Object o) + { + COSName other = (COSName)o; + return this.name.compareTo( other.name ); + } + + + + /** + * visitor pattern double dispatch method. + * + * @param visitor The object to notify when visiting this object. + * @return any object, depending on the visitor implementation, or null + * @throws COSVisitorException If an error occurs while visiting this object. + */ + public Object accept(ICOSVisitor visitor) throws COSVisitorException + { + return visitor.visitFromName(this); + } + + /** + * This will output this string as a PDF object. + * + * @param output The stream to write to. + * @throws IOException If there is an error writing to the stream. + */ + public void writePDF( OutputStream output ) throws IOException + { + output.write(NAME_PREFIX); + byte[] bytes = getName().getBytes(); + for (int i = 0; i < bytes.length;i++) + { + int current = ((bytes[i]+256)%256); + + if(current <= 32 || current >= 127 || + current == '(' || + current == ')' || + current == '[' || + current == ']' || + current == '/' || + current == '%' || + current == '<' || + current == '>' || + current == NAME_ESCAPE[0] ) + { + output.write(NAME_ESCAPE); + output.write(COSHEXTable.TABLE[current]); + } + else + { + output.write(current); + } + } + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/cos/COSNull.java b/src/main/java/org/pdfbox/cos/COSNull.java new file mode 100644 index 0000000..15356b5 --- /dev/null +++ b/src/main/java/org/pdfbox/cos/COSNull.java @@ -0,0 +1,88 @@ +/** + * Copyright (c) 2003-2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.cos; + + + +import java.io.IOException; +import java.io.OutputStream; + +import org.pdfbox.exceptions.COSVisitorException; + +/** + * This class represents a null PDF object. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.12 $ + */ +public class COSNull extends COSBase +{ + /** + * The null token. + */ + public static final byte[] NULL_BYTES = new byte[] {110, 117, 108, 108}; //"null".getBytes( "ISO-8859-1" ); + + /** + * The one null object in the system. + */ + public static final COSNull NULL = new COSNull(); + + /** + * Constructor. + */ + private COSNull() + { + //limit creation to one instance. + } + + /** + * visitor pattern double dispatch method. + * + * @param visitor The object to notify when visiting this object. + * @return any object, depending on the visitor implementation, or null + * @throws COSVisitorException If an error occurs while visiting this object. + */ + public Object accept( ICOSVisitor visitor ) throws COSVisitorException + { + return visitor.visitFromNull( this ); + } + + /** + * This will output this string as a PDF object. + * + * @param output The stream to write to. + * @throws IOException If there is an error writing to the stream. + */ + public void writePDF( OutputStream output ) throws IOException + { + output.write(NULL_BYTES); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/cos/COSNumber.java b/src/main/java/org/pdfbox/cos/COSNumber.java new file mode 100644 index 0000000..c629f66 --- /dev/null +++ b/src/main/java/org/pdfbox/cos/COSNumber.java @@ -0,0 +1,115 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.cos; + +import java.io.IOException; + +import java.util.HashMap; +import java.util.Map; + +/** + * This class represents an abstract number in a PDF document. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.9 $ + */ +public abstract class COSNumber extends COSBase +{ + /** + * ZERO. + */ + public static final COSInteger ZERO = new COSInteger( 0 ); + /** + * ONE. + */ + public static final COSInteger ONE = new COSInteger( 1 ); + private static final Map COMMON_NUMBERS = new HashMap(); + + static + { + COMMON_NUMBERS.put( "0", ZERO ); + COMMON_NUMBERS.put( "1", ONE ); + } + + /** + * This will get the float value of this number. + * + * @return The float value of this object. + */ + public abstract float floatValue(); + + /** + * This will get the double value of this number. + * + * @return The double value of this number. + */ + public abstract double doubleValue(); + + /** + * This will get the integer value of this number. + * + * @return The integer value of this number. + */ + public abstract int intValue(); + + /** + * This will get the long value of this number. + * + * @return The long value of this number. + */ + public abstract long longValue(); + + /** + * This factory method will get the appropriate number object. + * + * @param number The string representation of the number. + * + * @return A number object, either float or int. + * + * @throws IOException If the string is not a number. + */ + public static COSNumber get( String number ) throws IOException + { + COSNumber result = (COSNumber)COMMON_NUMBERS.get( number ); + if( result == null ) + { + if (number.indexOf('.') >= 0) + { + result = new COSFloat( number ); + } + else + { + result = new COSInteger( number ); + } + } + return result; + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/cos/COSObject.java b/src/main/java/org/pdfbox/cos/COSObject.java new file mode 100644 index 0000000..28f2316 --- /dev/null +++ b/src/main/java/org/pdfbox/cos/COSObject.java @@ -0,0 +1,226 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.cos; + +import org.pdfbox.exceptions.COSVisitorException; + +import java.io.IOException; + +import org.apache.log4j.Logger; + +/** + * This class represents a PDF object. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.35 $ + */ +public class COSObject extends COSBase +{ + private static Logger log = Logger.getLogger(COSObject.class); + + private COSBase baseObject; + private COSInteger objectNumber; + private COSInteger generationNumber; + + /** + * Constructor. + * + * @param object The object that this encapsulates. + * + * @throws IOException If there is an error with the object passed in. + */ + public COSObject( COSBase object ) throws IOException + { + setObject( object ); + } + + /** + * This will get the dictionary object in this object that has the name key and + * if it is a pdfobjref then it will dereference that and return it. + * + * @param key The key to the value that we are searching for. + * + * @return The pdf object that matches the key. + */ + public COSBase getDictionaryObject( COSName key ) + { + COSBase retval =null; + if( baseObject instanceof COSDictionary ) + { + retval = ((COSDictionary)baseObject).getDictionaryObject( key ); + } + return retval; + } + + /** + * This will get the dictionary object in this object that has the name key. + * + * @param key The key to the value that we are searching for. + * + * @return The pdf object that matches the key. + */ + public COSBase getItem( COSName key ) + { + COSBase retval =null; + if( baseObject instanceof COSDictionary ) + { + retval = ((COSDictionary)baseObject).getItem( key ); + } + return retval; + } + + /** + * This will get the object that this object encapsulates. + * + * @return The encapsulated object. + */ + public COSBase getObject() + { + return baseObject; + } + + /** + * This will set the object that this object encapsulates. + * + * @param object The new object to encapsulate. + * + * @throws IOException If there is an error setting the updated object. + */ + public void setObject( COSBase object ) throws IOException + { + baseObject = object; + /*if( baseObject == null ) + { + baseObject = object; + } + else + { + //This is for when an object appears twice in the + //pdf file we really want to replace it such that + //object references still work correctly. + //see owcp-as-received.pdf for an example + if( baseObject instanceof COSDictionary ) + { + COSDictionary dic = (COSDictionary)baseObject; + COSDictionary dicObject = (COSDictionary)object; + dic.clear(); + dic.addAll( dicObject ); + } + else if( baseObject instanceof COSArray ) + { + COSArray array = (COSArray)baseObject; + COSArray arrObject = (COSArray)object; + array.clear(); + for( int i=0; i 0) ) +// { +// retval = new RandomAccessFileInputStream( file, +// 0, +// file.length() ); +// } +// else +// { + //if there is no stream data then simply return an empty stream. + retval = new ByteArrayInputStream( new byte[0] ); +// } + } + return retval; + } + + /** + * visitor pattern double dispatch method. + * + * @param visitor The object to notify when visiting this object. + * @return any object, depending on the visitor implementation, or null + * @throws COSVisitorException If an error occurs while visiting this object. + */ + public Object accept(ICOSVisitor visitor) throws COSVisitorException + { + return visitor.visitFromStream(this); + } + + /** + * This will decode the physical byte stream applying all of the filters to the stream. + * + * @throws IOException If there is an error applying a filter to the stream. + */ + private void doDecode() throws IOException + { + if( log.isDebugEnabled() ) + { + log.debug("doDecode() start"); + } +// FIXME: We shouldn't keep the same reference? + unFilteredStream = filteredStream; + + COSBase filters = getFilters(); + if( filters == null ) + { + if( log.isDebugEnabled() ) + { + log.debug("doDecode() - No filter to apply"); + } + } + else if( filters instanceof COSName ) + { + if( log.isDebugEnabled() ) + { + log.debug("doDecode( COSName )"); + } + doDecode( (COSName)filters ); + } + else if( filters instanceof COSArray ) + { + if( log.isDebugEnabled() ) + { + log.debug("doDecode( COSArray )"); + } + COSArray filterArray = (COSArray)filters; + for( int i=0; i=0; i-- ) + { + COSName filterName = (COSName)filterArray.get( i ); + doEncode( filterName ); + } + } + } + + /** + * This will encode applying a single filter on the stream. + * + * @param filterName The name of the filter. + * + * @throws IOException If there is an error parsing the stream. + */ + private void doEncode( COSName filterName ) throws IOException + { + FilterManager manager = getFilterManager(); + Filter filter = manager.getFilter( filterName ); + InputStream input; + + input = new BufferedInputStream( + new RandomAccessFileInputStream( file, filteredStream.getPosition(), + filteredStream.getLength() ), BUFFER_SIZE ); + filteredStream = new RandomAccessFileOutputStream( file ); + filter.encode( input, filteredStream, this ); + } + + /** + * This will return the filters to apply to the byte stream. + * The method will return + * - null if no filters are to be applied + * - a COSName if one filter is to be applied + * - a COSArray containing COSNames if multiple filters are to be applied + * + * @return the COSBase object representing the filters + */ + public COSBase getFilters() + { + return getDictionaryObject(COSName.FILTER); + } + + /** + * This will create a new stream for which filtered byte should be + * written to. You probably don't want this but want to use the + * createUnfilteredStream, which is used to write raw bytes to. + * + * @return A stream that can be written to. + * + * @throws IOException If there is an error creating the stream. + */ + public OutputStream createFilteredStream() throws IOException + { + filteredStream = new RandomAccessFileOutputStream( file ); + unFilteredStream = null; + return new BufferedOutputStream( filteredStream, BUFFER_SIZE ); + } + + /** + * This will create a new stream for which filtered byte should be + * written to. You probably don't want this but want to use the + * createUnfilteredStream, which is used to write raw bytes to. + * + * @param expectedLength An entry where a length is expected. + * + * @return A stream that can be written to. + * + * @throws IOException If there is an error creating the stream. + */ + public OutputStream createFilteredStream( COSBase expectedLength ) throws IOException + { + filteredStream = new RandomAccessFileOutputStream( file ); + filteredStream.setExpectedLength( expectedLength ); + unFilteredStream = null; + return new BufferedOutputStream( filteredStream, BUFFER_SIZE ); + } + + /** + * set the filters to be applied to the stream. + * + * @param filters The filters to set on this stream. + * + * @throws IOException If there is an error clearing the old filters. + */ + public void setFilters(COSBase filters) throws IOException + { + setItem(COSName.FILTER, filters); + // kill cached filtered streams + filteredStream = null; + } + + /** + * This will create an output stream that can be written to. + * + * @return An output stream which raw data bytes should be written to. + * + * @throws IOException If there is an error creating the stream. + */ + public OutputStream createUnfilteredStream() throws IOException + { + unFilteredStream = new RandomAccessFileOutputStream( file ); + filteredStream = null; + return new BufferedOutputStream( unFilteredStream, BUFFER_SIZE ); + } + + /** + * This will print a byte array as a hex string to standard output. + * + * @param data The array to print. + */ + private static void printHexString( byte[] data ) + { + for( int i=0; i".getBytes( "ISO-8859-1" ); + /** + * the escape character in strings. + */ + public static final byte[] ESCAPE = new byte[]{ 92 }; //"\\".getBytes( "ISO-8859-1" ); + + /** + * CR escape characters. + */ + public static final byte[] CR_ESCAPE = new byte[]{ 92, 114 }; //"\\r".getBytes( "ISO-8859-1" ); + /** + * LF escape characters. + */ + public static final byte[] LF_ESCAPE = new byte[]{ 92, 110 }; //"\\n".getBytes( "ISO-8859-1" ); + /** + * HT escape characters. + */ + public static final byte[] HT_ESCAPE = new byte[]{ 92, 116 }; //"\\t".getBytes( "ISO-8859-1" ); + /** + * BS escape characters. + */ + public static final byte[] BS_ESCAPE = new byte[]{ 92, 98 }; //"\\b".getBytes( "ISO-8859-1" ); + /** + * FF escape characters. + */ + public static final byte[] FF_ESCAPE = new byte[]{ 92, 102 }; //"\\f".getBytes( "ISO-8859-1" ); + + private ByteArrayOutputStream out = new ByteArrayOutputStream(); + + /** + * Constructor. + */ + public COSString() + { + } + + /** + * Explicit constructor for ease of manual PDF construction. + * + * @param value The string value of the object. + */ + public COSString( String value ) + { + try + { + boolean unicode16 = false; + char[] chars = value.toCharArray(); + for( int i=0; i 255 ) + { + unicode16 = true; + } + } + if( unicode16 ) + { + out.write( 0xFE ); + out.write( 0xFF ); + out.write( value.getBytes( "UTF-16BE" ) ); + } + else + { + out.write(value.getBytes()); + } + } + catch (IOException ignore) + { + ignore.printStackTrace(); + //should never happen + } + } + + /** + * Explicit constructor for ease of manual PDF construction. + * + * @param value The string value of the object. + */ + public COSString( byte[] value ) + { + try + { + out.write( value ); + } + catch (IOException ignore) + { + ignore.printStackTrace(); + //should never happen + } + } + + /** + * This will create a COS string from a string of hex characters. + * + * @param hex A hex string. + * @return A cos string with the hex characters converted to their actual bytes. + * @throws IOException If there is an error with the hex string. + */ + public static COSString createFromHexString( String hex ) throws IOException + { + COSString retval = new COSString(); + StringBuffer hexBuffer = new StringBuffer( hex.trim() ); + //if odd number then the last hex digit is assumed to be 0 + if( hexBuffer.length() % 2 == 1 ) + { + hexBuffer.append( "0" ); + } + for( int i=0; i 2 ) + { + if( data[0] == (byte)0xFF && data[1] == (byte)0xFE ) + { + encoding = "UTF-16LE"; + start=2; + } + else if( data[0] == (byte)0xFE && data[1] == (byte)0xFF ) + { + encoding = "UTF-16BE"; + start=2; + } + } + try + { + if( encoding != null ) + { + retval = new String( getBytes(), start, data.length-start, encoding ); + } + else + { + retval = new String( getBytes() ); + } + } + catch( UnsupportedEncodingException e ) + { + //should never happen + e.printStackTrace(); + retval = new String( getBytes() ); + } + return retval; + } + + /** + * This will append a byte[] to the string. + * + * @param data The byte[] to add to this string. + * + * @throws IOException If an IO error occurs while writing the byte. + */ + public void append( byte[] data ) throws IOException + { + out.write( data ); + } + + /** + * This will append a byte to the string. + * + * @param in The byte to add to this string. + * + * @throws IOException If an IO error occurs while writing the byte. + */ + public void append( int in ) throws IOException + { + out.write( in ); + } + + /** + * This will reset the internal buffer. + */ + public void reset() + { + out.reset(); + } + + /** + * This will get the bytes of the string. + * + * @return A byte array that represents the string. + */ + public byte[] getBytes() + { + return out.toByteArray(); + } + + /** + * @see Object#toString() + */ + public String toString() + { + return "COSString{" + new String( getBytes() ) + "}"; + } + + /** + * This will output this string as a PDF object. + * + * @param output The stream to write to. + * @throws IOException If there is an error writing to the stream. + */ + public void writePDF( OutputStream output ) throws IOException + { + boolean outsideASCII = false; + //Lets first check if we need to escape this string. + byte[] bytes = getBytes(); + for( int i=0; i + + + + + +These are the low level objects that make up a PDF document. +

+ +See the PDF Reference 1.4. + + diff --git a/src/main/java/org/pdfbox/encoding/AFMEncoding.java b/src/main/java/org/pdfbox/encoding/AFMEncoding.java new file mode 100644 index 0000000..badb7bf --- /dev/null +++ b/src/main/java/org/pdfbox/encoding/AFMEncoding.java @@ -0,0 +1,76 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.encoding; + +import java.util.Iterator; + +import org.pdfbox.afmtypes.CharMetric; +import org.pdfbox.afmtypes.FontMetric; + +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSName; + +/** + * This will handle the encoding from an AFM font. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.6 $ + */ +public class AFMEncoding extends Encoding +{ + private FontMetric metric = null; + + /** + * Constructor. + * + * @param fontInfo The font metric information. + */ + public AFMEncoding( FontMetric fontInfo ) + { + metric = fontInfo; + Iterator characters = metric.getCharMetrics().iterator(); + while( characters.hasNext() ) + { + CharMetric nextMetric = (CharMetric)characters.next(); + addCharacterEncoding( nextMetric.getCharacterCode(), COSName.getPDFName( nextMetric.getName() ) ); + } + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSBase getCOSObject() + { + return null; + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/encoding/DictionaryEncoding.java b/src/main/java/org/pdfbox/encoding/DictionaryEncoding.java new file mode 100644 index 0000000..4378898 --- /dev/null +++ b/src/main/java/org/pdfbox/encoding/DictionaryEncoding.java @@ -0,0 +1,112 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.encoding; + +import java.io.IOException; + +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSName; +import org.pdfbox.cos.COSNumber; + +/** + * This will perform the encoding from a dictionary. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.12 $ + */ +public class DictionaryEncoding extends Encoding +{ + private COSDictionary encoding = null; + + /** + * Constructor. + * + * @param fontEncoding The encoding dictionary. + * + * @throws IOException If there is a problem getting the base font. + */ + public DictionaryEncoding( COSDictionary fontEncoding ) throws IOException + { + encoding = fontEncoding; + + //first set up the base encoding + //The previious value WinAnsiEncoding() has been changed to StandardEnding + //see p 389 of the PDF 1.5 reférence table 5.11 entries in a dictionary encoding + //"If this entry is absent, the Differences entry describes differences from an implicit + //base encoding. For a font program that is embedded in the PDF file, the + //implicit base encoding is the font program’s built-in encoding, as described + //above and further elaborated in the sections on specific font types below. Otherwise, + //for a nonsymbolic font, it is StandardEncoding, and for a symbolic font, it + //is the font’s built-in encoding." + + //so the default base encoding is standardEncoding + Encoding baseEncoding = new StandardEncoding(); + COSName baseEncodingName = (COSName)encoding.getDictionaryObject( COSName.BASE_ENCODING ); + + if( baseEncodingName != null ) + { + EncodingManager manager = new EncodingManager(); + baseEncoding = manager.getEncoding( baseEncodingName ); + } + nameToCode.putAll( baseEncoding.nameToCode ); + codeToName.putAll( baseEncoding.codeToName ); + + + //now replace with the differences. + COSArray differences = (COSArray)encoding.getDictionaryObject( COSName.DIFFERENCES ); + int currentIndex = -1; + for( int i=0; differences != null && i= 0 ) + { + try + { + String characterName = line.substring( 0, semicolonIndex ); + String unicodeValue = line.substring( semicolonIndex+1, line.length() ); + StringTokenizer tokenizer = new StringTokenizer( unicodeValue, " ", false ); + String value = ""; + while(tokenizer.hasMoreTokens()) + { + int characterCode = Integer.parseInt( tokenizer.nextToken(), 16 ); + value += (char)characterCode; + } + + NAME_TO_CHARACTER.put( COSName.getPDFName( characterName ), value ); + } + catch( NumberFormatException nfe ) + { + log.error( "Error parsing line '" + line + "' ", nfe ); + } + } + } + } + } + catch( IOException io ) + { + log.error( "Error reading Resources/glyphlist.txt", io ); + } + finally + { + if( glyphStream != null ) + { + try + { + glyphStream.close(); + } + catch( IOException e ) + { + log.warn( "Error closing stream", e ); + } + + } + } + + + NAME_TO_CHARACTER.put( COSName.getPDFName( ".notdef" ), "" ); + NAME_TO_CHARACTER.put( COSName.getPDFName( "fi" ), "fi" ); + NAME_TO_CHARACTER.put( COSName.getPDFName( "fl" ), "fl" ); + NAME_TO_CHARACTER.put( COSName.getPDFName( "ffi" ), "ffi" ); + NAME_TO_CHARACTER.put( COSName.getPDFName( "ff" ), "ff" ); + NAME_TO_CHARACTER.put( COSName.getPDFName( "pi" ), "pi" ); + + Iterator keys = NAME_TO_CHARACTER.keySet().iterator(); + while( keys.hasNext() ) + { + Object key = keys.next(); + Object value = NAME_TO_CHARACTER.get( key ); + CHARACTER_TO_NAME.put( value, key ); + } + } + + + /** + * This will add a character encoding. + * + * @param code The character code that matches the character. + * @param name The name of the character. + */ + protected void addCharacterEncoding( int code, COSName name ) + { + Integer intCode = new Integer( code ); + codeToName.put( intCode, name ); + nameToCode.put( name, intCode ); + } + + /** + * This will get the character code for the name. + * + * @param name The name of the character. + * + * @return The code for the character. + * + * @throws IOException If there is no character code for the name. + */ + public int getCode( COSName name ) throws IOException + { + Integer code = (Integer)nameToCode.get( name ); + if( code == null ) + { + throw new IOException( "No character code for character name '" + name.getName() + "'" ); + } + return code.intValue(); + } + + /** + * This will take a character code and get the name from the code. + * + * @param code The character code. + * + * @return The name of the character. + * + * @throws IOException If there is no name for the code. + */ + public COSName getName( int code ) throws IOException + { + COSName name = (COSName)codeToName.get( new Integer( code ) ); + if( name == null ) + { + //lets be forgiving for now + name = COSName.getPDFName( "space" ); + //throw new IOException( getClass().getName() + + // ": No name for character code '" + code + "'" ); + } + if( log.isDebugEnabled() ) + { + log.debug( "Encoding.getName( " + code + " )=" + name ); + } + return name; + } + + /** + * This will take a character code and get the name from the code. + * + * @param c The character. + * + * @return The name of the character. + * + * @throws IOException If there is no name for the character. + */ + public COSName getNameFromCharacter( char c ) throws IOException + { + COSName name = (COSName)CHARACTER_TO_NAME.get( "" + c ); + if( name == null ) + { + throw new IOException( "No name for character '" + c + "'" ); + } + return name; + } + + /** + * This will get the character from the code. + * + * @param code The character code. + * + * @return The printable character for the code. + * + * @throws IOException If there is not name for the character. + */ + public String getCharacter( int code ) throws IOException + { + String character = getCharacter( getName( code ) ); + if( log.isDebugEnabled() ) + { + log.debug( "Encoding.getCharacter( " + code + " )=" + character ); + } + return character; + } + + /** + * This will get the character from the name. + * + * @param name The name of the character. + * + * @return The printable character for the code. + */ + public static String getCharacter( COSName name ) + { + String character = (String)NAME_TO_CHARACTER.get( name ); + if( character == null ) + { + character = name.getName(); + } + if( log.isDebugEnabled() ) + { + log.debug( "Encoding.getCharacter(" + name + ")=" + character ); + } + return character; + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/encoding/EncodingManager.java b/src/main/java/org/pdfbox/encoding/EncodingManager.java new file mode 100644 index 0000000..9e8e4b3 --- /dev/null +++ b/src/main/java/org/pdfbox/encoding/EncodingManager.java @@ -0,0 +1,87 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.encoding; + +import java.io.IOException; + +import java.util.HashMap; +import java.util.Map; + +import org.pdfbox.cos.COSName; + +/** + * This class will handle getting the appropriate encodings. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.5 $ + */ +public class EncodingManager +{ + private static final Map ENCODINGS = new HashMap(); + + static + { + ENCODINGS.put( COSName.MAC_ROMAN_ENCODING, new MacRomanEncoding() ); + ENCODINGS.put( COSName.PDF_DOC_ENCODING, new PdfDocEncoding() ); + ENCODINGS.put( COSName.STANDARD_ENCODING, new StandardEncoding() ); + ENCODINGS.put( COSName.WIN_ANSI_ENCODING, new WinAnsiEncoding() ); + + } + + /** + * This will get the standard encoding. + * + * @return The standard encoding. + */ + public Encoding getStandardEncoding() + { + return (Encoding)ENCODINGS.get( COSName.STANDARD_ENCODING ); + } + + /** + * This will get an encoding by name. + * + * @param name The name of the encoding to get. + * + * @return The encoding that matches the name. + * + * @throws IOException If there is not encoding with that name. + */ + public Encoding getEncoding( COSName name ) throws IOException + { + Encoding encoding = (Encoding)ENCODINGS.get( name ); + if( encoding == null ) + { + throw new IOException( "Unknown encoding for '" + name.getName() + "'" ); + } + return encoding; + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/encoding/MacRomanEncoding.java b/src/main/java/org/pdfbox/encoding/MacRomanEncoding.java new file mode 100644 index 0000000..6a560a2 --- /dev/null +++ b/src/main/java/org/pdfbox/encoding/MacRomanEncoding.java @@ -0,0 +1,267 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.encoding; + +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSName; + +/** + * This is an interface to a text encoder. + * + * @author Ben Litchfield + * @version $Revision: 1.9 $ + */ +public class MacRomanEncoding extends Encoding +{ + /** + * Constructor. + */ + public MacRomanEncoding() + { + addCharacterEncoding( 0101, COSName.getPDFName( "A" ) ); + addCharacterEncoding( 0256, COSName.getPDFName( "AE" ) ); + addCharacterEncoding( 0347, COSName.getPDFName( "Aacute" ) ); + addCharacterEncoding( 0345, COSName.getPDFName( "Acircumflex" ) ); + addCharacterEncoding( 0200, COSName.getPDFName( "Adieresis" ) ); + addCharacterEncoding( 0313, COSName.getPDFName( "Agrave" ) ); + addCharacterEncoding( 0201, COSName.getPDFName( "Aring" ) ); + addCharacterEncoding( 0314, COSName.getPDFName( "Atilde" ) ); + addCharacterEncoding( 0102, COSName.getPDFName( "B" ) ); + addCharacterEncoding( 0103, COSName.getPDFName( "C" ) ); + addCharacterEncoding( 0202, COSName.getPDFName( "Ccedilla" ) ); + addCharacterEncoding( 0104, COSName.getPDFName( "D" ) ); + addCharacterEncoding( 0105, COSName.getPDFName( "E" ) ); + addCharacterEncoding( 0203, COSName.getPDFName( "Eacute" ) ); + addCharacterEncoding( 0346, COSName.getPDFName( "Ecircumflex" ) ); + addCharacterEncoding( 0350, COSName.getPDFName( "Edieresis" ) ); + addCharacterEncoding( 0351, COSName.getPDFName( "Egrave" ) ); + addCharacterEncoding( 0106, COSName.getPDFName( "F" ) ); + addCharacterEncoding( 0107, COSName.getPDFName( "G" ) ); + addCharacterEncoding( 0110, COSName.getPDFName( "H" ) ); + addCharacterEncoding( 0111, COSName.getPDFName( "I" ) ); + addCharacterEncoding( 0352, COSName.getPDFName( "Iacute" ) ); + addCharacterEncoding( 0353, COSName.getPDFName( "Icircumflex" ) ); + addCharacterEncoding( 0354, COSName.getPDFName( "Idieresis" ) ); + addCharacterEncoding( 0355, COSName.getPDFName( "Igrave" ) ); + addCharacterEncoding( 0112, COSName.getPDFName( "J" ) ); + addCharacterEncoding( 0113, COSName.getPDFName( "K" ) ); + addCharacterEncoding( 0114, COSName.getPDFName( "L" ) ); + addCharacterEncoding( 0115, COSName.getPDFName( "M" ) ); + addCharacterEncoding( 0116, COSName.getPDFName( "N" ) ); + addCharacterEncoding( 0204, COSName.getPDFName( "Ntilde" ) ); + addCharacterEncoding( 0117, COSName.getPDFName( "O" ) ); + addCharacterEncoding( 0316, COSName.getPDFName( "OE" ) ); + addCharacterEncoding( 0356, COSName.getPDFName( "Oacute" ) ); + addCharacterEncoding( 0357, COSName.getPDFName( "Ocircumflex" ) ); + addCharacterEncoding( 0205, COSName.getPDFName( "Odieresis" ) ); + addCharacterEncoding( 0361, COSName.getPDFName( "Ograve" ) ); + addCharacterEncoding( 0257, COSName.getPDFName( "Oslash" ) ); + addCharacterEncoding( 0315, COSName.getPDFName( "Otilde" ) ); + addCharacterEncoding( 0120, COSName.getPDFName( "P" ) ); + addCharacterEncoding( 0121, COSName.getPDFName( "Q" ) ); + addCharacterEncoding( 0122, COSName.getPDFName( "R" ) ); + addCharacterEncoding( 0123, COSName.getPDFName( "S" ) ); + addCharacterEncoding( 0124, COSName.getPDFName( "T" ) ); + addCharacterEncoding( 0125, COSName.getPDFName( "U" ) ); + addCharacterEncoding( 0362, COSName.getPDFName( "Uacute" ) ); + addCharacterEncoding( 0363, COSName.getPDFName( "Ucircumflex" ) ); + addCharacterEncoding( 0206, COSName.getPDFName( "Udieresis" ) ); + addCharacterEncoding( 0364, COSName.getPDFName( "Ugrave" ) ); + addCharacterEncoding( 0126, COSName.getPDFName( "V" ) ); + addCharacterEncoding( 0127, COSName.getPDFName( "W" ) ); + addCharacterEncoding( 0130, COSName.getPDFName( "X" ) ); + addCharacterEncoding( 0131, COSName.getPDFName( "Y" ) ); + addCharacterEncoding( 0331, COSName.getPDFName( "Ydieresis" ) ); + addCharacterEncoding( 0132, COSName.getPDFName( "Z" ) ); + addCharacterEncoding( 0141, COSName.getPDFName( "a" ) ); + addCharacterEncoding( 0207, COSName.getPDFName( "aacute" ) ); + addCharacterEncoding( 0211, COSName.getPDFName( "acircumflex" ) ); + addCharacterEncoding( 0253, COSName.getPDFName( "acute" ) ); + addCharacterEncoding( 0212, COSName.getPDFName( "adieresis" ) ); + addCharacterEncoding( 0276, COSName.getPDFName( "ae" ) ); + addCharacterEncoding( 0210, COSName.getPDFName( "agrave" ) ); + addCharacterEncoding( 046, COSName.getPDFName( "ampersand" ) ); + addCharacterEncoding( 0214, COSName.getPDFName( "aring" ) ); + addCharacterEncoding( 0136, COSName.getPDFName( "asciicircum" ) ); + addCharacterEncoding( 0176, COSName.getPDFName( "asciitilde" ) ); + addCharacterEncoding( 052, COSName.getPDFName( "asterisk" ) ); + addCharacterEncoding( 0100, COSName.getPDFName( "at" ) ); + addCharacterEncoding( 0213, COSName.getPDFName( "atilde" ) ); + addCharacterEncoding( 0142, COSName.getPDFName( "b" ) ); + addCharacterEncoding( 0134, COSName.getPDFName( "backslash" ) ); + addCharacterEncoding( 0174, COSName.getPDFName( "bar" ) ); + addCharacterEncoding( 0173, COSName.getPDFName( "braceleft" ) ); + addCharacterEncoding( 0175, COSName.getPDFName( "braceright" ) ); + addCharacterEncoding( 0133, COSName.getPDFName( "bracketleft" ) ); + addCharacterEncoding( 0135, COSName.getPDFName( "bracketright" ) ); + addCharacterEncoding( 0371, COSName.getPDFName( "breve" ) ); + addCharacterEncoding( 0245, COSName.getPDFName( "bullet" ) ); + addCharacterEncoding( 0143, COSName.getPDFName( "c" ) ); + addCharacterEncoding( 0377, COSName.getPDFName( "caron" ) ); + addCharacterEncoding( 0215, COSName.getPDFName( "ccedilla" ) ); + addCharacterEncoding( 0374, COSName.getPDFName( "cedilla" ) ); + addCharacterEncoding( 0242, COSName.getPDFName( "cent" ) ); + addCharacterEncoding( 0366, COSName.getPDFName( "circumflex" ) ); + addCharacterEncoding( 072, COSName.getPDFName( "colon" ) ); + addCharacterEncoding( 054, COSName.getPDFName( "comma" ) ); + addCharacterEncoding( 0251, COSName.getPDFName( "copyright" ) ); + addCharacterEncoding( 0333, COSName.getPDFName( "currency1" ) ); + addCharacterEncoding( 0144, COSName.getPDFName( "d" ) ); + addCharacterEncoding( 0240, COSName.getPDFName( "dagger" ) ); + addCharacterEncoding( 0340, COSName.getPDFName( "daggerdbl" ) ); + addCharacterEncoding( 0241, COSName.getPDFName( "degree" ) ); + addCharacterEncoding( 0254, COSName.getPDFName( "dieresis" ) ); + addCharacterEncoding( 0326, COSName.getPDFName( "divide" ) ); + addCharacterEncoding( 044, COSName.getPDFName( "dollar" ) ); + addCharacterEncoding( 0372, COSName.getPDFName( "dotaccent" ) ); + addCharacterEncoding( 0365, COSName.getPDFName( "dotlessi" ) ); + addCharacterEncoding( 0145, COSName.getPDFName( "e" ) ); + addCharacterEncoding( 0216, COSName.getPDFName( "eacute" ) ); + addCharacterEncoding( 0220, COSName.getPDFName( "ecircumflex" ) ); + addCharacterEncoding( 0221, COSName.getPDFName( "edieresis" ) ); + addCharacterEncoding( 0217, COSName.getPDFName( "egrave" ) ); + addCharacterEncoding( 070, COSName.getPDFName( "eight" ) ); + addCharacterEncoding( 0311, COSName.getPDFName( "ellipsis" ) ); + addCharacterEncoding( 0321, COSName.getPDFName( "emdash" ) ); + addCharacterEncoding( 0320, COSName.getPDFName( "endash" ) ); + addCharacterEncoding( 075, COSName.getPDFName( "equal" ) ); + addCharacterEncoding( 041, COSName.getPDFName( "exclam" ) ); + addCharacterEncoding( 0301, COSName.getPDFName( "exclamdown" ) ); + addCharacterEncoding( 0146, COSName.getPDFName( "f" ) ); + addCharacterEncoding( 0336, COSName.getPDFName( "fi" ) ); + addCharacterEncoding( 065, COSName.getPDFName( "five" ) ); + addCharacterEncoding( 0337, COSName.getPDFName( "fl" ) ); + addCharacterEncoding( 0304, COSName.getPDFName( "florin" ) ); + addCharacterEncoding( 064, COSName.getPDFName( "four" ) ); + addCharacterEncoding( 0332, COSName.getPDFName( "fraction" ) ); + addCharacterEncoding( 0147, COSName.getPDFName( "g" ) ); + addCharacterEncoding( 0247, COSName.getPDFName( "germandbls" ) ); + addCharacterEncoding( 0140, COSName.getPDFName( "grave" ) ); + addCharacterEncoding( 076, COSName.getPDFName( "greater" ) ); + addCharacterEncoding( 0307, COSName.getPDFName( "guillemotleft" ) ); + addCharacterEncoding( 0310, COSName.getPDFName( "guillemotright" ) ); + addCharacterEncoding( 0334, COSName.getPDFName( "guilsinglleft" ) ); + addCharacterEncoding( 0335, COSName.getPDFName( "guilsinglright" ) ); + addCharacterEncoding( 0150, COSName.getPDFName( "h" ) ); + addCharacterEncoding( 0375, COSName.getPDFName( "hungarumlaut" ) ); + addCharacterEncoding( 055, COSName.getPDFName( "hyphen" ) ); + addCharacterEncoding( 0151, COSName.getPDFName( "i" ) ); + addCharacterEncoding( 0222, COSName.getPDFName( "iacute" ) ); + addCharacterEncoding( 0224, COSName.getPDFName( "icircumflex" ) ); + addCharacterEncoding( 0225, COSName.getPDFName( "idieresis" ) ); + addCharacterEncoding( 0223, COSName.getPDFName( "igrave" ) ); + addCharacterEncoding( 0152, COSName.getPDFName( "j" ) ); + addCharacterEncoding( 0153, COSName.getPDFName( "k" ) ); + addCharacterEncoding( 0154, COSName.getPDFName( "l" ) ); + addCharacterEncoding( 074, COSName.getPDFName( "less" ) ); + addCharacterEncoding( 0302, COSName.getPDFName( "logicalnot" ) ); + addCharacterEncoding( 0155, COSName.getPDFName( "m" ) ); + addCharacterEncoding( 0370, COSName.getPDFName( "macron" ) ); + addCharacterEncoding( 0265, COSName.getPDFName( "mu" ) ); + addCharacterEncoding( 0156, COSName.getPDFName( "n" ) ); + addCharacterEncoding( 071, COSName.getPDFName( "nine" ) ); + addCharacterEncoding( 0226, COSName.getPDFName( "ntilde" ) ); + addCharacterEncoding( 043, COSName.getPDFName( "numbersign" ) ); + addCharacterEncoding( 0157, COSName.getPDFName( "o" ) ); + addCharacterEncoding( 0227, COSName.getPDFName( "oacute" ) ); + addCharacterEncoding( 0231, COSName.getPDFName( "ocircumflex" ) ); + addCharacterEncoding( 0232, COSName.getPDFName( "odieresis" ) ); + addCharacterEncoding( 0317, COSName.getPDFName( "oe" ) ); + addCharacterEncoding( 0376, COSName.getPDFName( "ogonek" ) ); + addCharacterEncoding( 0230, COSName.getPDFName( "ograve" ) ); + addCharacterEncoding( 061, COSName.getPDFName( "one" ) ); + addCharacterEncoding( 0273, COSName.getPDFName( "ordfeminine" ) ); + addCharacterEncoding( 0274, COSName.getPDFName( "ordmasculine" ) ); + addCharacterEncoding( 0277, COSName.getPDFName( "oslash" ) ); + addCharacterEncoding( 0233, COSName.getPDFName( "otilde" ) ); + addCharacterEncoding( 0160, COSName.getPDFName( "p" ) ); + addCharacterEncoding( 0246, COSName.getPDFName( "paragraph" ) ); + addCharacterEncoding( 050, COSName.getPDFName( "parenleft" ) ); + addCharacterEncoding( 051, COSName.getPDFName( "parenright" ) ); + addCharacterEncoding( 045, COSName.getPDFName( "percent" ) ); + addCharacterEncoding( 056, COSName.getPDFName( "period" ) ); + addCharacterEncoding( 0341, COSName.getPDFName( "periodcentered" ) ); + addCharacterEncoding( 0344, COSName.getPDFName( "perthousand" ) ); + addCharacterEncoding( 053, COSName.getPDFName( "plus" ) ); + addCharacterEncoding( 0261, COSName.getPDFName( "plusminus" ) ); + addCharacterEncoding( 0161, COSName.getPDFName( "q" ) ); + addCharacterEncoding( 077, COSName.getPDFName( "question" ) ); + addCharacterEncoding( 0300, COSName.getPDFName( "questiondown" ) ); + addCharacterEncoding( 042, COSName.getPDFName( "quotedbl" ) ); + addCharacterEncoding( 0343, COSName.getPDFName( "quotedblbase" ) ); + addCharacterEncoding( 0322, COSName.getPDFName( "quotedblleft" ) ); + addCharacterEncoding( 0323, COSName.getPDFName( "quotedblright" ) ); + addCharacterEncoding( 0324, COSName.getPDFName( "quoteleft" ) ); + addCharacterEncoding( 0325, COSName.getPDFName( "quoteright" ) ); + addCharacterEncoding( 0342, COSName.getPDFName( "quotesinglbase" ) ); + addCharacterEncoding( 047, COSName.getPDFName( "quotesingle" ) ); + addCharacterEncoding( 0162, COSName.getPDFName( "r" ) ); + addCharacterEncoding( 0250, COSName.getPDFName( "registered" ) ); + addCharacterEncoding( 0373, COSName.getPDFName( "ring" ) ); + addCharacterEncoding( 0163, COSName.getPDFName( "s" ) ); + addCharacterEncoding( 0244, COSName.getPDFName( "section" ) ); + addCharacterEncoding( 073, COSName.getPDFName( "semicolon" ) ); + addCharacterEncoding( 067, COSName.getPDFName( "seven" ) ); + addCharacterEncoding( 066, COSName.getPDFName( "six" ) ); + addCharacterEncoding( 057, COSName.getPDFName( "slash" ) ); + addCharacterEncoding( 040, COSName.getPDFName( "space" ) ); + addCharacterEncoding( 0243, COSName.getPDFName( "sterling" ) ); + addCharacterEncoding( 0164, COSName.getPDFName( "t" ) ); + addCharacterEncoding( 063, COSName.getPDFName( "three" ) ); + addCharacterEncoding( 0367, COSName.getPDFName( "tilde" ) ); + addCharacterEncoding( 0252, COSName.getPDFName( "trademark" ) ); + addCharacterEncoding( 062, COSName.getPDFName( "two" ) ); + addCharacterEncoding( 0165, COSName.getPDFName( "u" ) ); + addCharacterEncoding( 0234, COSName.getPDFName( "uacute" ) ); + addCharacterEncoding( 0236, COSName.getPDFName( "ucircumflex" ) ); + addCharacterEncoding( 0237, COSName.getPDFName( "udieresis" ) ); + addCharacterEncoding( 0235, COSName.getPDFName( "ugrave" ) ); + addCharacterEncoding( 0137, COSName.getPDFName( "underscore" ) ); + addCharacterEncoding( 0166, COSName.getPDFName( "v" ) ); + addCharacterEncoding( 0167, COSName.getPDFName( "w" ) ); + addCharacterEncoding( 0170, COSName.getPDFName( "x" ) ); + addCharacterEncoding( 0171, COSName.getPDFName( "y" ) ); + addCharacterEncoding( 0330, COSName.getPDFName( "ydieresis" ) ); + addCharacterEncoding( 0264, COSName.getPDFName( "yen" ) ); + addCharacterEncoding( 0172, COSName.getPDFName( "z" ) ); + addCharacterEncoding( 060, COSName.getPDFName( "zero" ) ); + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSBase getCOSObject() + { + return COSName.MAC_ROMAN_ENCODING; + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/encoding/PdfDocEncoding.java b/src/main/java/org/pdfbox/encoding/PdfDocEncoding.java new file mode 100644 index 0000000..1153002 --- /dev/null +++ b/src/main/java/org/pdfbox/encoding/PdfDocEncoding.java @@ -0,0 +1,289 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.encoding; + +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSName; + +/** + * This is an interface to a text encoder. + * + * @author Ben Litchfield + * @version $Revision: 1.9 $ + */ +public class PdfDocEncoding extends Encoding +{ + /** + * Constructor. + */ + public PdfDocEncoding() + { + addCharacterEncoding( 0101, COSName.getPDFName( "A" ) ); + addCharacterEncoding( 0306, COSName.getPDFName( "AE" ) ); + addCharacterEncoding( 0301, COSName.getPDFName( "Aacute" ) ); + addCharacterEncoding( 0302, COSName.getPDFName( "Acircumflex" ) ); + addCharacterEncoding( 0304, COSName.getPDFName( "Adieresis" ) ); + addCharacterEncoding( 0300, COSName.getPDFName( "Agrave" ) ); + addCharacterEncoding( 0305, COSName.getPDFName( "Aring" ) ); + addCharacterEncoding( 0303, COSName.getPDFName( "Atilde" ) ); + addCharacterEncoding( 0102, COSName.getPDFName( "B" ) ); + addCharacterEncoding( 0103, COSName.getPDFName( "C" ) ); + addCharacterEncoding( 0307, COSName.getPDFName( "Ccedilla" ) ); + addCharacterEncoding( 0104, COSName.getPDFName( "D" ) ); + addCharacterEncoding( 0105, COSName.getPDFName( "E" ) ); + addCharacterEncoding( 0311, COSName.getPDFName( "Eacute" ) ); + addCharacterEncoding( 0312, COSName.getPDFName( "Ecircumflex" ) ); + addCharacterEncoding( 0313, COSName.getPDFName( "Edieresis" ) ); + addCharacterEncoding( 0310, COSName.getPDFName( "Egrave" ) ); + addCharacterEncoding( 0320, COSName.getPDFName( "Eth" ) ); + addCharacterEncoding( 0240, COSName.getPDFName( "Euro" ) ); + addCharacterEncoding( 0106, COSName.getPDFName( "F" ) ); + addCharacterEncoding( 0107, COSName.getPDFName( "G" ) ); + addCharacterEncoding( 0110, COSName.getPDFName( "H" ) ); + addCharacterEncoding( 0111, COSName.getPDFName( "I" ) ); + addCharacterEncoding( 0315, COSName.getPDFName( "Iacute" ) ); + addCharacterEncoding( 0316, COSName.getPDFName( "Icircumflex" ) ); + addCharacterEncoding( 0317, COSName.getPDFName( "Idieresis" ) ); + addCharacterEncoding( 0314, COSName.getPDFName( "Igrave" ) ); + addCharacterEncoding( 0112, COSName.getPDFName( "J" ) ); + addCharacterEncoding( 0113, COSName.getPDFName( "K" ) ); + addCharacterEncoding( 0114, COSName.getPDFName( "L" ) ); + addCharacterEncoding( 0225, COSName.getPDFName( "Lslash" ) ); + addCharacterEncoding( 0115, COSName.getPDFName( "M" ) ); + addCharacterEncoding( 0116, COSName.getPDFName( "N" ) ); + addCharacterEncoding( 0321, COSName.getPDFName( "Ntilde" ) ); + addCharacterEncoding( 0117, COSName.getPDFName( "O" ) ); + addCharacterEncoding( 0226, COSName.getPDFName( "OE" ) ); + addCharacterEncoding( 0323, COSName.getPDFName( "Oacute" ) ); + addCharacterEncoding( 0324, COSName.getPDFName( "Ocircumflex" ) ); + addCharacterEncoding( 0326, COSName.getPDFName( "Odieresis" ) ); + addCharacterEncoding( 0322, COSName.getPDFName( "Ograve" ) ); + addCharacterEncoding( 0330, COSName.getPDFName( "Oslash" ) ); + addCharacterEncoding( 0325, COSName.getPDFName( "Otilde" ) ); + addCharacterEncoding( 0120, COSName.getPDFName( "P" ) ); + addCharacterEncoding( 0121, COSName.getPDFName( "Q" ) ); + addCharacterEncoding( 0122, COSName.getPDFName( "R" ) ); + addCharacterEncoding( 0123, COSName.getPDFName( "S" ) ); + addCharacterEncoding( 0227, COSName.getPDFName( "Scaron" ) ); + addCharacterEncoding( 0124, COSName.getPDFName( "T" ) ); + addCharacterEncoding( 0336, COSName.getPDFName( "Thorn" ) ); + addCharacterEncoding( 0125, COSName.getPDFName( "U" ) ); + addCharacterEncoding( 0332, COSName.getPDFName( "Uacute" ) ); + addCharacterEncoding( 0333, COSName.getPDFName( "Ucircumflex" ) ); + addCharacterEncoding( 0334, COSName.getPDFName( "Udieresis" ) ); + addCharacterEncoding( 0331, COSName.getPDFName( "Ugrave" ) ); + addCharacterEncoding( 0126, COSName.getPDFName( "V" ) ); + addCharacterEncoding( 0127, COSName.getPDFName( "W" ) ); + addCharacterEncoding( 0130, COSName.getPDFName( "X" ) ); + addCharacterEncoding( 0131, COSName.getPDFName( "Y" ) ); + addCharacterEncoding( 0335, COSName.getPDFName( "Yacute" ) ); + addCharacterEncoding( 0230, COSName.getPDFName( "Ydieresis" ) ); + addCharacterEncoding( 0132, COSName.getPDFName( "Z" ) ); + addCharacterEncoding( 0231, COSName.getPDFName( "Zcaron" ) ); + addCharacterEncoding( 0141, COSName.getPDFName( "a" ) ); + addCharacterEncoding( 0341, COSName.getPDFName( "aacute" ) ); + addCharacterEncoding( 0342, COSName.getPDFName( "acircumflex" ) ); + addCharacterEncoding( 0264, COSName.getPDFName( "acute" ) ); + addCharacterEncoding( 0344, COSName.getPDFName( "adieresis" ) ); + addCharacterEncoding( 0346, COSName.getPDFName( "ae" ) ); + addCharacterEncoding( 0340, COSName.getPDFName( "agrave" ) ); + addCharacterEncoding( 046, COSName.getPDFName( "ampersand" ) ); + addCharacterEncoding( 0345, COSName.getPDFName( "aring" ) ); + addCharacterEncoding( 0136, COSName.getPDFName( "asciicircum" ) ); + addCharacterEncoding( 0176, COSName.getPDFName( "asciitilde" ) ); + addCharacterEncoding( 052, COSName.getPDFName( "asterisk" ) ); + addCharacterEncoding( 0100, COSName.getPDFName( "at" ) ); + addCharacterEncoding( 0343, COSName.getPDFName( "atilde" ) ); + addCharacterEncoding( 0142, COSName.getPDFName( "b" ) ); + addCharacterEncoding( 0134, COSName.getPDFName( "backslash" ) ); + addCharacterEncoding( 0174, COSName.getPDFName( "bar" ) ); + addCharacterEncoding( 0173, COSName.getPDFName( "braceleft" ) ); + addCharacterEncoding( 0175, COSName.getPDFName( "braceright" ) ); + addCharacterEncoding( 0133, COSName.getPDFName( "bracketleft" ) ); + addCharacterEncoding( 0135, COSName.getPDFName( "bracketright" ) ); + addCharacterEncoding( 030, COSName.getPDFName( "breve" ) ); + addCharacterEncoding( 0246, COSName.getPDFName( "brokenbar" ) ); + addCharacterEncoding( 0200, COSName.getPDFName( "bullet" ) ); + addCharacterEncoding( 0143, COSName.getPDFName( "c" ) ); + addCharacterEncoding( 031, COSName.getPDFName( "caron" ) ); + addCharacterEncoding( 0347, COSName.getPDFName( "ccedilla" ) ); + addCharacterEncoding( 0270, COSName.getPDFName( "cedilla" ) ); + addCharacterEncoding( 0242, COSName.getPDFName( "cent" ) ); + addCharacterEncoding( 032, COSName.getPDFName( "circumflex" ) ); + addCharacterEncoding( 072, COSName.getPDFName( "colon" ) ); + addCharacterEncoding( 054, COSName.getPDFName( "comma" ) ); + addCharacterEncoding( 0251, COSName.getPDFName( "copyright" ) ); + addCharacterEncoding( 0244, COSName.getPDFName( "currency1" ) ); + addCharacterEncoding( 0144, COSName.getPDFName( "d" ) ); + addCharacterEncoding( 0201, COSName.getPDFName( "dagger" ) ); + addCharacterEncoding( 0202, COSName.getPDFName( "daggerdbl" ) ); + addCharacterEncoding( 0260, COSName.getPDFName( "degree" ) ); + addCharacterEncoding( 0250, COSName.getPDFName( "dieresis" ) ); + addCharacterEncoding( 0367, COSName.getPDFName( "divide" ) ); + addCharacterEncoding( 044, COSName.getPDFName( "dollar" ) ); + addCharacterEncoding( 033, COSName.getPDFName( "dotaccent" ) ); + addCharacterEncoding( 0232, COSName.getPDFName( "dotlessi" ) ); + addCharacterEncoding( 0145, COSName.getPDFName( "e" ) ); + addCharacterEncoding( 0351, COSName.getPDFName( "eacute" ) ); + addCharacterEncoding( 0352, COSName.getPDFName( "ecircumflex" ) ); + addCharacterEncoding( 0353, COSName.getPDFName( "edieresis" ) ); + addCharacterEncoding( 0350, COSName.getPDFName( "egrave" ) ); + addCharacterEncoding( 070, COSName.getPDFName( "eight" ) ); + addCharacterEncoding( 0203, COSName.getPDFName( "ellipsis" ) ); + addCharacterEncoding( 0204, COSName.getPDFName( "emdash" ) ); + addCharacterEncoding( 0205, COSName.getPDFName( "endash" ) ); + addCharacterEncoding( 075, COSName.getPDFName( "equal" ) ); + addCharacterEncoding( 0360, COSName.getPDFName( "eth" ) ); + addCharacterEncoding( 041, COSName.getPDFName( "exclam" ) ); + addCharacterEncoding( 0241, COSName.getPDFName( "exclamdown" ) ); + addCharacterEncoding( 0146, COSName.getPDFName( "f" ) ); + addCharacterEncoding( 0223, COSName.getPDFName( "fi" ) ); + addCharacterEncoding( 065, COSName.getPDFName( "five" ) ); + addCharacterEncoding( 0224, COSName.getPDFName( "fl" ) ); + addCharacterEncoding( 0206, COSName.getPDFName( "florin" ) ); + addCharacterEncoding( 064, COSName.getPDFName( "four" ) ); + addCharacterEncoding( 0207, COSName.getPDFName( "fraction" ) ); + addCharacterEncoding( 0147, COSName.getPDFName( "g" ) ); + addCharacterEncoding( 0337, COSName.getPDFName( "germandbls" ) ); + addCharacterEncoding( 0140, COSName.getPDFName( "grave" ) ); + addCharacterEncoding( 076, COSName.getPDFName( "greater" ) ); + addCharacterEncoding( 0253, COSName.getPDFName( "guillemotleft" ) ); + addCharacterEncoding( 0273, COSName.getPDFName( "guillemotright" ) ); + addCharacterEncoding( 0210, COSName.getPDFName( "guilsinglleft" ) ); + addCharacterEncoding( 0211, COSName.getPDFName( "guilsinglright" ) ); + addCharacterEncoding( 0150, COSName.getPDFName( "h" ) ); + addCharacterEncoding( 034, COSName.getPDFName( "hungarumlaut" ) ); + addCharacterEncoding( 055, COSName.getPDFName( "hyphen" ) ); + addCharacterEncoding( 0151, COSName.getPDFName( "i" ) ); + addCharacterEncoding( 0355, COSName.getPDFName( "iacute" ) ); + addCharacterEncoding( 0356, COSName.getPDFName( "icircumflex" ) ); + addCharacterEncoding( 0357, COSName.getPDFName( "idieresis" ) ); + addCharacterEncoding( 0354, COSName.getPDFName( "igrave" ) ); + addCharacterEncoding( 0152, COSName.getPDFName( "j" ) ); + addCharacterEncoding( 0153, COSName.getPDFName( "k" ) ); + addCharacterEncoding( 0154, COSName.getPDFName( "l" ) ); + addCharacterEncoding( 074, COSName.getPDFName( "less" ) ); + addCharacterEncoding( 0254, COSName.getPDFName( "logicalnot" ) ); + addCharacterEncoding( 0233, COSName.getPDFName( "lslash" ) ); + addCharacterEncoding( 0155, COSName.getPDFName( "m" ) ); + addCharacterEncoding( 0257, COSName.getPDFName( "macron" ) ); + addCharacterEncoding( 0212, COSName.getPDFName( "minus" ) ); + addCharacterEncoding( 0265, COSName.getPDFName( "mu" ) ); + addCharacterEncoding( 0327, COSName.getPDFName( "multiply" ) ); + addCharacterEncoding( 0156, COSName.getPDFName( "n" ) ); + addCharacterEncoding( 071, COSName.getPDFName( "nine" ) ); + addCharacterEncoding( 0361, COSName.getPDFName( "ntilde" ) ); + addCharacterEncoding( 043, COSName.getPDFName( "numbersign" ) ); + addCharacterEncoding( 0157, COSName.getPDFName( "o" ) ); + addCharacterEncoding( 0363, COSName.getPDFName( "oacute" ) ); + addCharacterEncoding( 0364, COSName.getPDFName( "ocircumflex" ) ); + addCharacterEncoding( 0366, COSName.getPDFName( "odieresis" ) ); + addCharacterEncoding( 0234, COSName.getPDFName( "oe" ) ); + addCharacterEncoding( 035, COSName.getPDFName( "ogonek" ) ); + addCharacterEncoding( 0362, COSName.getPDFName( "ograve" ) ); + addCharacterEncoding( 061, COSName.getPDFName( "one" ) ); + addCharacterEncoding( 0275, COSName.getPDFName( "onehalf" ) ); + addCharacterEncoding( 0274, COSName.getPDFName( "onequarter" ) ); + addCharacterEncoding( 0271, COSName.getPDFName( "onesuperior" ) ); + addCharacterEncoding( 0252, COSName.getPDFName( "ordfeminine" ) ); + addCharacterEncoding( 0272, COSName.getPDFName( "ordmasculine" ) ); + addCharacterEncoding( 0370, COSName.getPDFName( "oslash" ) ); + addCharacterEncoding( 0365, COSName.getPDFName( "otilde" ) ); + addCharacterEncoding( 0160, COSName.getPDFName( "p" ) ); + addCharacterEncoding( 0266, COSName.getPDFName( "paragraph" ) ); + addCharacterEncoding( 050, COSName.getPDFName( "parenleft" ) ); + addCharacterEncoding( 051, COSName.getPDFName( "parenright" ) ); + addCharacterEncoding( 045, COSName.getPDFName( "percent" ) ); + addCharacterEncoding( 056, COSName.getPDFName( "period" ) ); + addCharacterEncoding( 0267, COSName.getPDFName( "periodcentered" ) ); + addCharacterEncoding( 0213, COSName.getPDFName( "perthousand" ) ); + addCharacterEncoding( 053, COSName.getPDFName( "plus" ) ); + addCharacterEncoding( 0261, COSName.getPDFName( "plusminus" ) ); + addCharacterEncoding( 0161, COSName.getPDFName( "q" ) ); + addCharacterEncoding( 077, COSName.getPDFName( "question" ) ); + addCharacterEncoding( 0277, COSName.getPDFName( "questiondown" ) ); + addCharacterEncoding( 042, COSName.getPDFName( "quotedbl" ) ); + addCharacterEncoding( 0214, COSName.getPDFName( "quotedblbase" ) ); + addCharacterEncoding( 0215, COSName.getPDFName( "quotedblleft" ) ); + addCharacterEncoding( 0216, COSName.getPDFName( "quotedblright" ) ); + addCharacterEncoding( 0217, COSName.getPDFName( "quoteleft" ) ); + addCharacterEncoding( 0220, COSName.getPDFName( "quoteright" ) ); + addCharacterEncoding( 0221, COSName.getPDFName( "quotesinglbase" ) ); + addCharacterEncoding( 047, COSName.getPDFName( "quotesingle" ) ); + addCharacterEncoding( 0162, COSName.getPDFName( "r" ) ); + addCharacterEncoding( 0256, COSName.getPDFName( "registered" ) ); + addCharacterEncoding( 036, COSName.getPDFName( "ring" ) ); + addCharacterEncoding( 0163, COSName.getPDFName( "s" ) ); + addCharacterEncoding( 0235, COSName.getPDFName( "scaron" ) ); + addCharacterEncoding( 0247, COSName.getPDFName( "section" ) ); + addCharacterEncoding( 073, COSName.getPDFName( "semicolon" ) ); + addCharacterEncoding( 067, COSName.getPDFName( "seven" ) ); + addCharacterEncoding( 066, COSName.getPDFName( "six" ) ); + addCharacterEncoding( 057, COSName.getPDFName( "slash" ) ); + addCharacterEncoding( 040, COSName.getPDFName( "space" ) ); + addCharacterEncoding( 0243, COSName.getPDFName( "sterling" ) ); + addCharacterEncoding( 0164, COSName.getPDFName( "t" ) ); + addCharacterEncoding( 0376, COSName.getPDFName( "thorn" ) ); + addCharacterEncoding( 063, COSName.getPDFName( "three" ) ); + addCharacterEncoding( 0276, COSName.getPDFName( "threequarters" ) ); + addCharacterEncoding( 0263, COSName.getPDFName( "threesuperior" ) ); + addCharacterEncoding( 037, COSName.getPDFName( "tilde" ) ); + addCharacterEncoding( 0222, COSName.getPDFName( "trademark" ) ); + addCharacterEncoding( 062, COSName.getPDFName( "two" ) ); + addCharacterEncoding( 0262, COSName.getPDFName( "twosuperior" ) ); + addCharacterEncoding( 0165, COSName.getPDFName( "u" ) ); + addCharacterEncoding( 0372, COSName.getPDFName( "uacute" ) ); + addCharacterEncoding( 0373, COSName.getPDFName( "ucircumflex" ) ); + addCharacterEncoding( 0374, COSName.getPDFName( "udieresis" ) ); + addCharacterEncoding( 0371, COSName.getPDFName( "ugrave" ) ); + addCharacterEncoding( 0137, COSName.getPDFName( "underscore" ) ); + addCharacterEncoding( 0166, COSName.getPDFName( "v" ) ); + addCharacterEncoding( 0167, COSName.getPDFName( "w" ) ); + addCharacterEncoding( 0170, COSName.getPDFName( "x" ) ); + addCharacterEncoding( 0171, COSName.getPDFName( "y" ) ); + addCharacterEncoding( 0375, COSName.getPDFName( "yacute" ) ); + addCharacterEncoding( 0377, COSName.getPDFName( "ydieresis" ) ); + addCharacterEncoding( 0245, COSName.getPDFName( "yen" ) ); + addCharacterEncoding( 0172, COSName.getPDFName( "z" ) ); + addCharacterEncoding( 0236, COSName.getPDFName( "zcaron" ) ); + addCharacterEncoding( 060, COSName.getPDFName( "zero" ) ); + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSBase getCOSObject() + { + return COSName.PDF_DOC_ENCODING; + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/encoding/StandardEncoding.java b/src/main/java/org/pdfbox/encoding/StandardEncoding.java new file mode 100644 index 0000000..229adb4 --- /dev/null +++ b/src/main/java/org/pdfbox/encoding/StandardEncoding.java @@ -0,0 +1,209 @@ +/** + * Copyright (c) 2003-2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.encoding; + +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSName; + +/** + * This is an interface to a text encoder. + * + * @author Ben Litchfield + * @version $Revision: 1.9 $ + */ +public class StandardEncoding extends Encoding +{ + /** + * Constructor. + */ + public StandardEncoding() + { + addCharacterEncoding( 0101, COSName.getPDFName( "A" ) ); + addCharacterEncoding( 0341, COSName.getPDFName( "AE" ) ); + addCharacterEncoding( 0102, COSName.getPDFName( "B" ) ); + addCharacterEncoding( 0103, COSName.getPDFName( "C" ) ); + addCharacterEncoding( 0104, COSName.getPDFName( "D" ) ); + addCharacterEncoding( 0105, COSName.getPDFName( "E" ) ); + addCharacterEncoding( 0106, COSName.getPDFName( "F" ) ); + addCharacterEncoding( 0107, COSName.getPDFName( "G" ) ); + addCharacterEncoding( 0110, COSName.getPDFName( "H" ) ); + addCharacterEncoding( 0111, COSName.getPDFName( "I" ) ); + addCharacterEncoding( 0112, COSName.getPDFName( "J" ) ); + addCharacterEncoding( 0113, COSName.getPDFName( "K" ) ); + addCharacterEncoding( 0114, COSName.getPDFName( "L" ) ); + addCharacterEncoding( 0350, COSName.getPDFName( "Lslash" ) ); + addCharacterEncoding( 0115, COSName.getPDFName( "M" ) ); + addCharacterEncoding( 0116, COSName.getPDFName( "N" ) ); + addCharacterEncoding( 0117, COSName.getPDFName( "O" ) ); + addCharacterEncoding( 0352, COSName.getPDFName( "OE" ) ); + addCharacterEncoding( 0351, COSName.getPDFName( "Oslash" ) ); + addCharacterEncoding( 0120, COSName.getPDFName( "P" ) ); + addCharacterEncoding( 0121, COSName.getPDFName( "Q" ) ); + addCharacterEncoding( 0122, COSName.getPDFName( "R" ) ); + addCharacterEncoding( 0123, COSName.getPDFName( "S" ) ); + addCharacterEncoding( 0124, COSName.getPDFName( "T" ) ); + addCharacterEncoding( 0125, COSName.getPDFName( "U" ) ); + addCharacterEncoding( 0126, COSName.getPDFName( "V" ) ); + addCharacterEncoding( 0127, COSName.getPDFName( "W" ) ); + addCharacterEncoding( 0130, COSName.getPDFName( "X" ) ); + addCharacterEncoding( 0131, COSName.getPDFName( "Y" ) ); + addCharacterEncoding( 0132, COSName.getPDFName( "Z" ) ); + addCharacterEncoding( 0141, COSName.getPDFName( "a" ) ); + addCharacterEncoding( 0302, COSName.getPDFName( "acute" ) ); + addCharacterEncoding( 0361, COSName.getPDFName( "ae" ) ); + addCharacterEncoding( 0046, COSName.getPDFName( "ampersand" ) ); + addCharacterEncoding( 0136, COSName.getPDFName( "asciicircum" ) ); + addCharacterEncoding( 0176, COSName.getPDFName( "asciitilde" ) ); + addCharacterEncoding( 0052, COSName.getPDFName( "asterisk" ) ); + addCharacterEncoding( 0100, COSName.getPDFName( "at" ) ); + addCharacterEncoding( 0142, COSName.getPDFName( "b" ) ); + addCharacterEncoding( 0134, COSName.getPDFName( "backslash" ) ); + addCharacterEncoding( 0174, COSName.getPDFName( "bar" ) ); + addCharacterEncoding( 0173, COSName.getPDFName( "braceleft" ) ); + addCharacterEncoding( 0175, COSName.getPDFName( "braceright" ) ); + addCharacterEncoding( 0133, COSName.getPDFName( "bracketleft" ) ); + addCharacterEncoding( 0135, COSName.getPDFName( "bracketright" ) ); + addCharacterEncoding( 0306, COSName.getPDFName( "breve" ) ); + addCharacterEncoding( 0267, COSName.getPDFName( "bullet" ) ); + addCharacterEncoding( 0143, COSName.getPDFName( "c" ) ); + addCharacterEncoding( 0317, COSName.getPDFName( "caron" ) ); + addCharacterEncoding( 0313, COSName.getPDFName( "cedilla" ) ); + addCharacterEncoding( 0242, COSName.getPDFName( "cent" ) ); + addCharacterEncoding( 0303, COSName.getPDFName( "circumflex" ) ); + addCharacterEncoding( 0072, COSName.getPDFName( "colon" ) ); + addCharacterEncoding( 0054, COSName.getPDFName( "comma" ) ); + addCharacterEncoding( 0250, COSName.getPDFName( "currency1" ) ); + addCharacterEncoding( 0144, COSName.getPDFName( "d" ) ); + addCharacterEncoding( 0262, COSName.getPDFName( "dagger" ) ); + addCharacterEncoding( 0263, COSName.getPDFName( "daggerdbl" ) ); + addCharacterEncoding( 0310, COSName.getPDFName( "dieresis" ) ); + addCharacterEncoding( 0044, COSName.getPDFName( "dollar" ) ); + addCharacterEncoding( 0307, COSName.getPDFName( "dotaccent" ) ); + addCharacterEncoding( 0365, COSName.getPDFName( "dotlessi" ) ); + addCharacterEncoding( 0145, COSName.getPDFName( "e" ) ); + addCharacterEncoding( 0070, COSName.getPDFName( "eight" ) ); + addCharacterEncoding( 0274, COSName.getPDFName( "ellipsis" ) ); + addCharacterEncoding( 0320, COSName.getPDFName( "emdash" ) ); + addCharacterEncoding( 0261, COSName.getPDFName( "endash" ) ); + addCharacterEncoding( 0075, COSName.getPDFName( "equal" ) ); + addCharacterEncoding( 0041, COSName.getPDFName( "exclam" ) ); + addCharacterEncoding( 0241, COSName.getPDFName( "exclamdown" ) ); + addCharacterEncoding( 0146, COSName.getPDFName( "f" ) ); + addCharacterEncoding( 0256, COSName.getPDFName( "fi" ) ); + addCharacterEncoding( 0065, COSName.getPDFName( "five" ) ); + addCharacterEncoding( 0257, COSName.getPDFName( "fl" ) ); + addCharacterEncoding( 0246, COSName.getPDFName( "florin" ) ); + addCharacterEncoding( 0064, COSName.getPDFName( "four" ) ); + addCharacterEncoding( 0244, COSName.getPDFName( "fraction" ) ); + addCharacterEncoding( 0147, COSName.getPDFName( "g" ) ); + addCharacterEncoding( 0373, COSName.getPDFName( "germandbls" ) ); + addCharacterEncoding( 0301, COSName.getPDFName( "grave" ) ); + addCharacterEncoding( 0076, COSName.getPDFName( "greater" ) ); + addCharacterEncoding( 0253, COSName.getPDFName( "guillemotleft" ) ); + addCharacterEncoding( 0273, COSName.getPDFName( "guillemotright" ) ); + addCharacterEncoding( 0254, COSName.getPDFName( "guilsinglleft" ) ); + addCharacterEncoding( 0255, COSName.getPDFName( "guilsinglright" ) ); + addCharacterEncoding( 0150, COSName.getPDFName( "h" ) ); + addCharacterEncoding( 0315, COSName.getPDFName( "hungarumlaut" ) ); + addCharacterEncoding( 0055, COSName.getPDFName( "hyphen" ) ); + addCharacterEncoding( 0151, COSName.getPDFName( "i" ) ); + addCharacterEncoding( 0152, COSName.getPDFName( "j" ) ); + addCharacterEncoding( 0153, COSName.getPDFName( "k" ) ); + addCharacterEncoding( 0154, COSName.getPDFName( "l" ) ); + addCharacterEncoding( 0074, COSName.getPDFName( "less" ) ); + addCharacterEncoding( 0370, COSName.getPDFName( "lslash" ) ); + addCharacterEncoding( 0155, COSName.getPDFName( "m" ) ); + addCharacterEncoding( 0305, COSName.getPDFName( "macron" ) ); + addCharacterEncoding( 0156, COSName.getPDFName( "n" ) ); + addCharacterEncoding( 0071, COSName.getPDFName( "nine" ) ); + addCharacterEncoding( 0043, COSName.getPDFName( "numbersign" ) ); + addCharacterEncoding( 0157, COSName.getPDFName( "o" ) ); + addCharacterEncoding( 0372, COSName.getPDFName( "oe" ) ); + addCharacterEncoding( 0316, COSName.getPDFName( "ogonek" ) ); + addCharacterEncoding( 0061, COSName.getPDFName( "one" ) ); + addCharacterEncoding( 0343, COSName.getPDFName( "ordfeminine" ) ); + addCharacterEncoding( 0353, COSName.getPDFName( "ordmasculine" ) ); + addCharacterEncoding( 0371, COSName.getPDFName( "oslash" ) ); + addCharacterEncoding( 0160, COSName.getPDFName( "p" ) ); + addCharacterEncoding( 0266, COSName.getPDFName( "paragraph" ) ); + addCharacterEncoding( 0050, COSName.getPDFName( "parenleft" ) ); + addCharacterEncoding( 0051, COSName.getPDFName( "parenright" ) ); + addCharacterEncoding( 0045, COSName.getPDFName( "percent" ) ); + addCharacterEncoding( 0056, COSName.getPDFName( "period" ) ); + addCharacterEncoding( 0264, COSName.getPDFName( "periodcentered" ) ); + addCharacterEncoding( 0275, COSName.getPDFName( "perthousand" ) ); + addCharacterEncoding( 0053, COSName.getPDFName( "plus" ) ); + addCharacterEncoding( 0161, COSName.getPDFName( "q" ) ); + addCharacterEncoding( 0077, COSName.getPDFName( "question" ) ); + addCharacterEncoding( 0277, COSName.getPDFName( "questiondown" ) ); + addCharacterEncoding( 0042, COSName.getPDFName( "quotedbl" ) ); + addCharacterEncoding( 0271, COSName.getPDFName( "quotedblbase" ) ); + addCharacterEncoding( 0252, COSName.getPDFName( "quotedblleft" ) ); + addCharacterEncoding( 0272, COSName.getPDFName( "quotedblright" ) ); + addCharacterEncoding( 0140, COSName.getPDFName( "quoteleft" ) ); + addCharacterEncoding( 0047, COSName.getPDFName( "quoteright" ) ); + addCharacterEncoding( 0270, COSName.getPDFName( "quotesinglbase" ) ); + addCharacterEncoding( 0251, COSName.getPDFName( "quotesingle" ) ); + addCharacterEncoding( 0162, COSName.getPDFName( "r" ) ); + addCharacterEncoding( 0312, COSName.getPDFName( "ring" ) ); + addCharacterEncoding( 0163, COSName.getPDFName( "s" ) ); + addCharacterEncoding( 0247, COSName.getPDFName( "section" ) ); + addCharacterEncoding( 0073, COSName.getPDFName( "semicolon" ) ); + addCharacterEncoding( 0067, COSName.getPDFName( "seven" ) ); + addCharacterEncoding( 0066, COSName.getPDFName( "six" ) ); + addCharacterEncoding( 0057, COSName.getPDFName( "slash" ) ); + addCharacterEncoding( 0040, COSName.getPDFName( "space" ) ); + addCharacterEncoding( 0243, COSName.getPDFName( "sterling" ) ); + addCharacterEncoding( 0164, COSName.getPDFName( "t" ) ); + addCharacterEncoding( 0063, COSName.getPDFName( "three" ) ); + addCharacterEncoding( 0304, COSName.getPDFName( "tilde" ) ); + addCharacterEncoding( 0062, COSName.getPDFName( "two" ) ); + addCharacterEncoding( 0165, COSName.getPDFName( "u" ) ); + addCharacterEncoding( 0137, COSName.getPDFName( "underscore" ) ); + addCharacterEncoding( 0166, COSName.getPDFName( "v" ) ); + addCharacterEncoding( 0167, COSName.getPDFName( "w" ) ); + addCharacterEncoding( 0170, COSName.getPDFName( "x" ) ); + addCharacterEncoding( 0171, COSName.getPDFName( "y" ) ); + addCharacterEncoding( 0245, COSName.getPDFName( "yen" ) ); + addCharacterEncoding( 0172, COSName.getPDFName( "z" ) ); + addCharacterEncoding( 0060, COSName.getPDFName( "zero" ) ); + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSBase getCOSObject() + { + return COSName.STANDARD_ENCODING; + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/encoding/WinAnsiEncoding.java b/src/main/java/org/pdfbox/encoding/WinAnsiEncoding.java new file mode 100644 index 0000000..dcbe872 --- /dev/null +++ b/src/main/java/org/pdfbox/encoding/WinAnsiEncoding.java @@ -0,0 +1,281 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.encoding; + +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSName; + +/** + * This the win ansi encoding. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.9 $ + */ +public class WinAnsiEncoding extends Encoding +{ + /** + * Constructor. + */ + public WinAnsiEncoding() + { + addCharacterEncoding( 0101, COSName.getPDFName( "A" ) ); + addCharacterEncoding( 0306, COSName.getPDFName( "AE" ) ); + addCharacterEncoding( 0301, COSName.getPDFName( "Aacute" ) ); + addCharacterEncoding( 0302, COSName.getPDFName( "Acircumflex" ) ); + addCharacterEncoding( 0304, COSName.getPDFName( "Adieresis" ) ); + addCharacterEncoding( 0300, COSName.getPDFName( "Agrave" ) ); + addCharacterEncoding( 0305, COSName.getPDFName( "Aring" ) ); + addCharacterEncoding( 0303, COSName.getPDFName( "Atilde" ) ); + addCharacterEncoding( 0102, COSName.getPDFName( "B" ) ); + addCharacterEncoding( 0103, COSName.getPDFName( "C" ) ); + addCharacterEncoding( 0307, COSName.getPDFName( "Ccedilla" ) ); + addCharacterEncoding( 0104, COSName.getPDFName( "D" ) ); + addCharacterEncoding( 0105, COSName.getPDFName( "E" ) ); + addCharacterEncoding( 0311, COSName.getPDFName( "Eacute" ) ); + addCharacterEncoding( 0312, COSName.getPDFName( "Ecircumflex" ) ); + addCharacterEncoding( 0313, COSName.getPDFName( "Edieresis" ) ); + addCharacterEncoding( 0310, COSName.getPDFName( "Egrave" ) ); + addCharacterEncoding( 0320, COSName.getPDFName( "Eth" ) ); + addCharacterEncoding( 0200, COSName.getPDFName( "Euro" ) ); + addCharacterEncoding( 0106, COSName.getPDFName( "F" ) ); + addCharacterEncoding( 0107, COSName.getPDFName( "G" ) ); + addCharacterEncoding( 0110, COSName.getPDFName( "H" ) ); + addCharacterEncoding( 0111, COSName.getPDFName( "I" ) ); + addCharacterEncoding( 0315, COSName.getPDFName( "Iacute" ) ); + addCharacterEncoding( 0316, COSName.getPDFName( "Icircumflex" ) ); + addCharacterEncoding( 0317, COSName.getPDFName( "Idieresis" ) ); + addCharacterEncoding( 0314, COSName.getPDFName( "Igrave" ) ); + addCharacterEncoding( 0112, COSName.getPDFName( "J" ) ); + addCharacterEncoding( 0113, COSName.getPDFName( "K" ) ); + addCharacterEncoding( 0114, COSName.getPDFName( "L" ) ); + addCharacterEncoding( 0115, COSName.getPDFName( "M" ) ); + addCharacterEncoding( 0116, COSName.getPDFName( "N" ) ); + addCharacterEncoding( 0321, COSName.getPDFName( "Ntilde" ) ); + addCharacterEncoding( 0117, COSName.getPDFName( "O" ) ); + addCharacterEncoding( 0214, COSName.getPDFName( "OE" ) ); + addCharacterEncoding( 0323, COSName.getPDFName( "Oacute" ) ); + addCharacterEncoding( 0324, COSName.getPDFName( "Ocircumflex" ) ); + addCharacterEncoding( 0326, COSName.getPDFName( "Odieresis" ) ); + addCharacterEncoding( 0322, COSName.getPDFName( "Ograve" ) ); + addCharacterEncoding( 0330, COSName.getPDFName( "Oslash" ) ); + addCharacterEncoding( 0325, COSName.getPDFName( "Otilde" ) ); + addCharacterEncoding( 0120, COSName.getPDFName( "P" ) ); + addCharacterEncoding( 0121, COSName.getPDFName( "Q" ) ); + addCharacterEncoding( 0122, COSName.getPDFName( "R" ) ); + addCharacterEncoding( 0123, COSName.getPDFName( "S" ) ); + addCharacterEncoding( 0212, COSName.getPDFName( "Scaron" ) ); + addCharacterEncoding( 0124, COSName.getPDFName( "T" ) ); + addCharacterEncoding( 0336, COSName.getPDFName( "Thorn" ) ); + addCharacterEncoding( 0125, COSName.getPDFName( "U" ) ); + addCharacterEncoding( 0332, COSName.getPDFName( "Uacute" ) ); + addCharacterEncoding( 0333, COSName.getPDFName( "Ucircumflex" ) ); + addCharacterEncoding( 0334, COSName.getPDFName( "Udieresis" ) ); + addCharacterEncoding( 0331, COSName.getPDFName( "Ugrave" ) ); + addCharacterEncoding( 0126, COSName.getPDFName( "V" ) ); + addCharacterEncoding( 0127, COSName.getPDFName( "W" ) ); + addCharacterEncoding( 0130, COSName.getPDFName( "X" ) ); + addCharacterEncoding( 0131, COSName.getPDFName( "Y" ) ); + addCharacterEncoding( 0335, COSName.getPDFName( "Yacute" ) ); + addCharacterEncoding( 0237, COSName.getPDFName( "Ydieresis" ) ); + addCharacterEncoding( 0132, COSName.getPDFName( "Z" ) ); + addCharacterEncoding( 0216, COSName.getPDFName( "Zcaron" ) ); + addCharacterEncoding( 0141, COSName.getPDFName( "a" ) ); + addCharacterEncoding( 0341, COSName.getPDFName( "aacute" ) ); + addCharacterEncoding( 0342, COSName.getPDFName( "acircumflex" ) ); + addCharacterEncoding( 0264, COSName.getPDFName( "acute" ) ); + addCharacterEncoding( 0344, COSName.getPDFName( "adieresis" ) ); + addCharacterEncoding( 0346, COSName.getPDFName( "ae" ) ); + addCharacterEncoding( 0340, COSName.getPDFName( "agrave" ) ); + addCharacterEncoding( 046, COSName.getPDFName( "ampersand" ) ); + addCharacterEncoding( 0345, COSName.getPDFName( "aring" ) ); + addCharacterEncoding( 0136, COSName.getPDFName( "asciicircum" ) ); + addCharacterEncoding( 0176, COSName.getPDFName( "asciitilde" ) ); + addCharacterEncoding( 052, COSName.getPDFName( "asterisk" ) ); + addCharacterEncoding( 0100, COSName.getPDFName( "at" ) ); + addCharacterEncoding( 0343, COSName.getPDFName( "atilde" ) ); + addCharacterEncoding( 0142, COSName.getPDFName( "b" ) ); + addCharacterEncoding( 0134, COSName.getPDFName( "backslash" ) ); + addCharacterEncoding( 0174, COSName.getPDFName( "bar" ) ); + addCharacterEncoding( 0173, COSName.getPDFName( "braceleft" ) ); + addCharacterEncoding( 0175, COSName.getPDFName( "braceright" ) ); + addCharacterEncoding( 0133, COSName.getPDFName( "bracketleft" ) ); + addCharacterEncoding( 0135, COSName.getPDFName( "bracketright" ) ); + addCharacterEncoding( 0246, COSName.getPDFName( "brokenbar" ) ); + addCharacterEncoding( 0225, COSName.getPDFName( "bullet" ) ); + addCharacterEncoding( 0143, COSName.getPDFName( "c" ) ); + addCharacterEncoding( 0347, COSName.getPDFName( "ccedilla" ) ); + addCharacterEncoding( 0270, COSName.getPDFName( "cedilla" ) ); + addCharacterEncoding( 0242, COSName.getPDFName( "cent" ) ); + addCharacterEncoding( 0210, COSName.getPDFName( "circumflex" ) ); + addCharacterEncoding( 072, COSName.getPDFName( "colon" ) ); + addCharacterEncoding( 054, COSName.getPDFName( "comma" ) ); + addCharacterEncoding( 0251, COSName.getPDFName( "copyright" ) ); + + /** + * Added because cweb.pdf uses circlecopyrt + */ + addCharacterEncoding( 0251, COSName.getPDFName( "circlecopyrt" ) ); + addCharacterEncoding( 0244, COSName.getPDFName( "currency" ) ); + addCharacterEncoding( 0144, COSName.getPDFName( "d" ) ); + addCharacterEncoding( 0206, COSName.getPDFName( "dagger" ) ); + addCharacterEncoding( 0207, COSName.getPDFName( "daggerdbl" ) ); + addCharacterEncoding( 0260, COSName.getPDFName( "degree" ) ); + addCharacterEncoding( 0250, COSName.getPDFName( "dieresis" ) ); + addCharacterEncoding( 0367, COSName.getPDFName( "divide" ) ); + addCharacterEncoding( 044, COSName.getPDFName( "dollar" ) ); + addCharacterEncoding( 0145, COSName.getPDFName( "e" ) ); + addCharacterEncoding( 0351, COSName.getPDFName( "eacute" ) ); + addCharacterEncoding( 0352, COSName.getPDFName( "ecircumflex" ) ); + addCharacterEncoding( 0353, COSName.getPDFName( "edieresis" ) ); + addCharacterEncoding( 0350, COSName.getPDFName( "egrave" ) ); + addCharacterEncoding( 070, COSName.getPDFName( "eight" ) ); + addCharacterEncoding( 0205, COSName.getPDFName( "ellipsis" ) ); + addCharacterEncoding( 0227, COSName.getPDFName( "emdash" ) ); + addCharacterEncoding( 0226, COSName.getPDFName( "endash" ) ); + addCharacterEncoding( 075, COSName.getPDFName( "equal" ) ); + addCharacterEncoding( 0360, COSName.getPDFName( "eth" ) ); + addCharacterEncoding( 041, COSName.getPDFName( "exclam" ) ); + addCharacterEncoding( 0241, COSName.getPDFName( "exclamdown" ) ); + addCharacterEncoding( 0146, COSName.getPDFName( "f" ) ); + addCharacterEncoding( 065, COSName.getPDFName( "five" ) ); + addCharacterEncoding( 0203, COSName.getPDFName( "florin" ) ); + addCharacterEncoding( 064, COSName.getPDFName( "four" ) ); + addCharacterEncoding( 0147, COSName.getPDFName( "g" ) ); + addCharacterEncoding( 0337, COSName.getPDFName( "germandbls" ) ); + addCharacterEncoding( 0140, COSName.getPDFName( "grave" ) ); + addCharacterEncoding( 076, COSName.getPDFName( "greater" ) ); + addCharacterEncoding( 0253, COSName.getPDFName( "guillemotleft" ) ); + addCharacterEncoding( 0273, COSName.getPDFName( "guillemotright" ) ); + addCharacterEncoding( 0213, COSName.getPDFName( "guilsinglleft" ) ); + addCharacterEncoding( 0233, COSName.getPDFName( "guilsinglright" ) ); + addCharacterEncoding( 0150, COSName.getPDFName( "h" ) ); + addCharacterEncoding( 055, COSName.getPDFName( "hyphen" ) ); + addCharacterEncoding( 0151, COSName.getPDFName( "i" ) ); + addCharacterEncoding( 0355, COSName.getPDFName( "iacute" ) ); + addCharacterEncoding( 0356, COSName.getPDFName( "icircumflex" ) ); + addCharacterEncoding( 0357, COSName.getPDFName( "idieresis" ) ); + addCharacterEncoding( 0354, COSName.getPDFName( "igrave" ) ); + addCharacterEncoding( 0152, COSName.getPDFName( "j" ) ); + addCharacterEncoding( 0153, COSName.getPDFName( "k" ) ); + addCharacterEncoding( 0154, COSName.getPDFName( "l" ) ); + addCharacterEncoding( 074, COSName.getPDFName( "less" ) ); + addCharacterEncoding( 0254, COSName.getPDFName( "logicalnot" ) ); + addCharacterEncoding( 0155, COSName.getPDFName( "m" ) ); + addCharacterEncoding( 0257, COSName.getPDFName( "macron" ) ); + addCharacterEncoding( 0265, COSName.getPDFName( "mu" ) ); + addCharacterEncoding( 0327, COSName.getPDFName( "multiply" ) ); + addCharacterEncoding( 0156, COSName.getPDFName( "n" ) ); + addCharacterEncoding( 071, COSName.getPDFName( "nine" ) ); + addCharacterEncoding( 0361, COSName.getPDFName( "ntilde" ) ); + addCharacterEncoding( 043, COSName.getPDFName( "numbersign" ) ); + addCharacterEncoding( 0157, COSName.getPDFName( "o" ) ); + addCharacterEncoding( 0363, COSName.getPDFName( "oacute" ) ); + addCharacterEncoding( 0364, COSName.getPDFName( "ocircumflex" ) ); + addCharacterEncoding( 0366, COSName.getPDFName( "odieresis" ) ); + addCharacterEncoding( 0234, COSName.getPDFName( "oe" ) ); + addCharacterEncoding( 0362, COSName.getPDFName( "ograve" ) ); + addCharacterEncoding( 061, COSName.getPDFName( "one" ) ); + addCharacterEncoding( 0275, COSName.getPDFName( "onehalf" ) ); + addCharacterEncoding( 0274, COSName.getPDFName( "onequarter" ) ); + addCharacterEncoding( 0271, COSName.getPDFName( "onesuperior" ) ); + addCharacterEncoding( 0252, COSName.getPDFName( "ordfeminine" ) ); + addCharacterEncoding( 0272, COSName.getPDFName( "ordmasculine" ) ); + addCharacterEncoding( 0370, COSName.getPDFName( "oslash" ) ); + addCharacterEncoding( 0365, COSName.getPDFName( "otilde" ) ); + addCharacterEncoding( 0160, COSName.getPDFName( "p" ) ); + addCharacterEncoding( 0266, COSName.getPDFName( "paragraph" ) ); + addCharacterEncoding( 050, COSName.getPDFName( "parenleft" ) ); + addCharacterEncoding( 051, COSName.getPDFName( "parenright" ) ); + addCharacterEncoding( 045, COSName.getPDFName( "percent" ) ); + addCharacterEncoding( 056, COSName.getPDFName( "period" ) ); + addCharacterEncoding( 0267, COSName.getPDFName( "periodcentered" ) ); + addCharacterEncoding( 0211, COSName.getPDFName( "perthousand" ) ); + addCharacterEncoding( 053, COSName.getPDFName( "plus" ) ); + addCharacterEncoding( 0261, COSName.getPDFName( "plusminus" ) ); + addCharacterEncoding( 0161, COSName.getPDFName( "q" ) ); + addCharacterEncoding( 077, COSName.getPDFName( "question" ) ); + addCharacterEncoding( 0277, COSName.getPDFName( "questiondown" ) ); + addCharacterEncoding( 042, COSName.getPDFName( "quotedbl" ) ); + addCharacterEncoding( 0204, COSName.getPDFName( "quotedblbase" ) ); + addCharacterEncoding( 0223, COSName.getPDFName( "quotedblleft" ) ); + addCharacterEncoding( 0224, COSName.getPDFName( "quotedblright" ) ); + addCharacterEncoding( 0221, COSName.getPDFName( "quoteleft" ) ); + addCharacterEncoding( 0222, COSName.getPDFName( "quoteright" ) ); + addCharacterEncoding( 0202, COSName.getPDFName( "quotesinglbase" ) ); + addCharacterEncoding( 047, COSName.getPDFName( "quotesingle" ) ); + addCharacterEncoding( 0162, COSName.getPDFName( "r" ) ); + addCharacterEncoding( 0256, COSName.getPDFName( "registered" ) ); + addCharacterEncoding( 0163, COSName.getPDFName( "s" ) ); + addCharacterEncoding( 0232, COSName.getPDFName( "scaron" ) ); + addCharacterEncoding( 0247, COSName.getPDFName( "section" ) ); + addCharacterEncoding( 073, COSName.getPDFName( "semicolon" ) ); + addCharacterEncoding( 067, COSName.getPDFName( "seven" ) ); + addCharacterEncoding( 066, COSName.getPDFName( "six" ) ); + addCharacterEncoding( 057, COSName.getPDFName( "slash" ) ); + addCharacterEncoding( 040, COSName.getPDFName( "space" ) ); + addCharacterEncoding( 0243, COSName.getPDFName( "sterling" ) ); + addCharacterEncoding( 0164, COSName.getPDFName( "t" ) ); + addCharacterEncoding( 0376, COSName.getPDFName( "thorn" ) ); + addCharacterEncoding( 063, COSName.getPDFName( "three" ) ); + addCharacterEncoding( 0276, COSName.getPDFName( "threequarters" ) ); + addCharacterEncoding( 0263, COSName.getPDFName( "threesuperior" ) ); + addCharacterEncoding( 0230, COSName.getPDFName( "tilde" ) ); + addCharacterEncoding( 0231, COSName.getPDFName( "trademark" ) ); + addCharacterEncoding( 062, COSName.getPDFName( "two" ) ); + addCharacterEncoding( 0262, COSName.getPDFName( "twosuperior" ) ); + addCharacterEncoding( 0165, COSName.getPDFName( "u" ) ); + addCharacterEncoding( 0372, COSName.getPDFName( "uacute" ) ); + addCharacterEncoding( 0373, COSName.getPDFName( "ucircumflex" ) ); + addCharacterEncoding( 0374, COSName.getPDFName( "udieresis" ) ); + addCharacterEncoding( 0371, COSName.getPDFName( "ugrave" ) ); + addCharacterEncoding( 0137, COSName.getPDFName( "underscore" ) ); + addCharacterEncoding( 0166, COSName.getPDFName( "v" ) ); + addCharacterEncoding( 0167, COSName.getPDFName( "w" ) ); + addCharacterEncoding( 0170, COSName.getPDFName( "x" ) ); + addCharacterEncoding( 0171, COSName.getPDFName( "y" ) ); + addCharacterEncoding( 0375, COSName.getPDFName( "yacute" ) ); + addCharacterEncoding( 0377, COSName.getPDFName( "ydieresis" ) ); + addCharacterEncoding( 0245, COSName.getPDFName( "yen" ) ); + addCharacterEncoding( 0172, COSName.getPDFName( "z" ) ); + addCharacterEncoding( 0236, COSName.getPDFName( "zcaron" ) ); + addCharacterEncoding( 060, COSName.getPDFName( "zero" ) ); + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSBase getCOSObject() + { + return COSName.WIN_ANSI_ENCODING; + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/encoding/package.html b/src/main/java/org/pdfbox/encoding/package.html new file mode 100644 index 0000000..2fcc5c7 --- /dev/null +++ b/src/main/java/org/pdfbox/encoding/package.html @@ -0,0 +1,9 @@ + + + + + + +This package contains the implementations for all of the encodings that are used in PDF documents. + + diff --git a/src/main/java/org/pdfbox/encryption/ARCFour.java b/src/main/java/org/pdfbox/encryption/ARCFour.java new file mode 100644 index 0000000..6eeeb95 --- /dev/null +++ b/src/main/java/org/pdfbox/encryption/ARCFour.java @@ -0,0 +1,182 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.encryption; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +/** + * This class is an implementation of the alleged RC4 algorithm. + * + * @author Ben Litchfield + * @version $Revision: 1.7 $ + */ +public class ARCFour +{ + private int[] salt; + private int b; + private int c; + + /** + * Constructor. + * + */ + public ARCFour() + { + salt = new int[256]; + } + + /** + * This will reset the key to be used. + * + * @param key The RC4 key used during encryption. + */ + public void setKey( byte[] key ) + { + b = 0; + c = 0; + + if(key.length < 1 || key.length > 32) + { + throw new IllegalArgumentException("number of bytes must be between 1 and 32"); + } + for(int i = 0; i < salt.length; i++) + { + salt[i] = i; + } + + int keyIndex = 0; + int saltIndex = 0; + for( int i = 0; i < salt.length; i++) + { + saltIndex = (fixByte(key[keyIndex]) + salt[i] + saltIndex) % 256; + swap( salt, i, saltIndex ); + keyIndex = (keyIndex + 1) % key.length; + } + + } + + /** + * Thie will ensure that the value for a byte >=0. + * + * @param aByte The byte to test against. + * + * @return A value >=0 and < 256 + */ + private static final int fixByte( byte aByte ) + { + return aByte < 0 ? 256 + aByte : aByte; + } + + /** + * This will swap two values in an array. + * + * @param data The array to swap from. + * @param firstIndex The index of the first element to swap. + * @param secondIndex The index of the second element to swap. + */ + private static final void swap( int[] data, int firstIndex, int secondIndex ) + { + int tmp = data[ firstIndex ]; + data[ firstIndex ] = data[ secondIndex ]; + data[ secondIndex ] = tmp; + } + + /** + * This will encrypt and write the next byte. + * + * @param aByte The byte to encrypt. + * @param output The stream to write to. + * + * @throws IOException If there is an error writing to the output stream. + */ + public void write( byte aByte, OutputStream output ) throws IOException + { + b = (b + 1) % 256; + c = (salt[b] + c) % 256; + swap( salt, b, c ); + int saltIndex = (salt[b] + salt[c]) % 256; + output.write(aByte ^ (byte)salt[saltIndex]); + } + + /** + * This will encrypt and write the data. + * + * @param data The data to encrypt. + * @param output The stream to write to. + * + * @throws IOException If there is an error writing to the output stream. + */ + public void write( byte[] data, OutputStream output ) throws IOException + { + for( int i = 0; i < data.length; i++ ) + { + write( data[i], output ); + } + } + + /** + * This will encrypt and write the data. + * + * @param data The data to encrypt. + * @param output The stream to write to. + * + * @throws IOException If there is an error writing to the output stream. + */ + public void write( InputStream data, OutputStream output ) throws IOException + { + byte[] buffer = new byte[1024]; + int amountRead = 0; + while( (amountRead = data.read( buffer )) != -1 ) + { + write( buffer, 0, amountRead, output ); + } + } + + /** + * This will encrypt and write the data. + * + * @param data The data to encrypt. + * @param offset The offset into the array to start reading data from. + * @param len The number of bytes to attempt to read. + * @param output The stream to write to. + * + * @throws IOException If there is an error writing to the output stream. + */ + public void write( byte[] data, int offset, int len, OutputStream output) throws IOException + { + for( int i = offset; i < offset + len; i++ ) + { + write( data[i], output ); + } + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/encryption/DocumentEncryption.java b/src/main/java/org/pdfbox/encryption/DocumentEncryption.java new file mode 100644 index 0000000..9ae6936 --- /dev/null +++ b/src/main/java/org/pdfbox/encryption/DocumentEncryption.java @@ -0,0 +1,427 @@ +/** + * Copyright (c) 2003-2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.encryption; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.IOException; + +import java.math.BigInteger; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import org.pdfbox.exceptions.CryptographyException; +import org.pdfbox.exceptions.InvalidPasswordException; + +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSDocument; +import org.pdfbox.cos.COSName; +import org.pdfbox.cos.COSObject; +import org.pdfbox.cos.COSStream; +import org.pdfbox.cos.COSString; + +import org.pdfbox.pdmodel.PDDocument; + +import org.pdfbox.pdmodel.encryption.PDStandardEncryption; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +/** + * This class will deal with encrypting/decrypting a document. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.10 $ + */ +public class DocumentEncryption +{ + private PDDocument pdDocument = null; + private COSDocument document = null; + + private byte[] encryptionKey = null; + private PDFEncryption encryption = new PDFEncryption(); + + private Set objects = new HashSet(); + + /** + * A set that contains potential signature dictionaries. This is used + * because the Contents entry of the signature is not encrypted. + */ + private Set potentialSignatures = new HashSet(); + + /** + * Constructor. + * + * @param doc The document to decrypt. + */ + public DocumentEncryption( PDDocument doc ) + { + pdDocument = doc; + document = doc.getDocument(); + } + + /** + * Constructor. + * + * @param doc The document to decrypt. + */ + public DocumentEncryption( COSDocument doc ) + { + pdDocument = new PDDocument( doc ); + document = doc; + } + + /** + * This will encrypt the given document, given the owner password and user password. + * The encryption method used is the standard filter. + * + * @throws CryptographyException If an error occurs during encryption. + * @throws IOException If there is an error accessing the data. + */ + public void initForEncryption() + throws CryptographyException, IOException + { + String ownerPassword = pdDocument.getOwnerPasswordForEncryption(); + String userPassword = pdDocument.getUserPasswordForEncryption(); + if( ownerPassword == null ) + { + ownerPassword = ""; + } + if( userPassword == null ) + { + userPassword = ""; + } + PDStandardEncryption encParameters = (PDStandardEncryption)pdDocument.getEncryptionDictionary(); + int permissionInt = encParameters.getPermissions(); + int revision = encParameters.getRevision(); + int length = encParameters.getLength()/8; + COSArray idArray = document.getDocumentID(); + + //check if the document has an id yet. If it does not then + //generate one + if( idArray == null || idArray.size() < 2 ) + { + idArray = new COSArray(); + try + { + MessageDigest md = MessageDigest.getInstance( "MD5" ); + BigInteger time = BigInteger.valueOf( System.currentTimeMillis() ); + md.update( time.toByteArray() ); + md.update( ownerPassword.getBytes() ); + md.update( userPassword.getBytes() ); + md.update( document.toString().getBytes() ); + byte[] id = md.digest( this.toString().getBytes() ); + COSString idString = new COSString(); + idString.append( id ); + idArray.add( idString ); + idArray.add( idString ); + document.setDocumentID( idArray ); + } + catch( NoSuchAlgorithmException e ) + { + throw new CryptographyException( e ); + } + + } + COSString id = (COSString)idArray.getObject( 0 ); + encryption = new PDFEncryption(); + + byte[] o = encryption.computeOwnerPassword( + ownerPassword.getBytes("ISO-8859-1"), + userPassword.getBytes("ISO-8859-1"), revision, length); + + byte[] u = encryption.computeUserPassword( + userPassword.getBytes("ISO-8859-1"), + o, permissionInt, id.getBytes(), revision, length); + + encryptionKey = encryption.computeEncryptedKey( + userPassword.getBytes("ISO-8859-1"), o, permissionInt, id.getBytes(), revision, length); + + encParameters.setOwnerKey( o ); + encParameters.setUserKey( u ); + + document.setEncryptionDictionary( encParameters.getCOSDictionary() ); + } + + + + /** + * This will decrypt the document. + * + * @param password The password for the document. + * + * @throws CryptographyException If there is an error decrypting the document. + * @throws IOException If there is an error getting the stream data. + * @throws InvalidPasswordException If the password is not a user or owner password. + */ + public void decryptDocument( String password ) + throws CryptographyException, IOException, InvalidPasswordException + { + if( password == null ) + { + password = ""; + } + + PDStandardEncryption encParameters = (PDStandardEncryption)pdDocument.getEncryptionDictionary(); + + + int permissions = encParameters.getPermissions(); + int revision = encParameters.getRevision(); + int length = encParameters.getLength()/8; + + COSString id = (COSString)document.getDocumentID().getObject( 0 ); + byte[] u = encParameters.getUserKey(); + byte[] o = encParameters.getOwnerKey(); + + boolean isUserPassword = + encryption.isUserPassword( password.getBytes(), u, + o, permissions, id.getBytes(), revision, length ); + boolean isOwnerPassword = + encryption.isOwnerPassword( password.getBytes(), u, + o, permissions, id.getBytes(), revision, length ); + + if( isUserPassword ) + { + encryptionKey = + encryption.computeEncryptedKey( + password.getBytes(), o, + permissions, id.getBytes(), revision, length ); + } + else if( isOwnerPassword ) + { + byte[] computedUserPassword = + encryption.getUserPassword( + password.getBytes(), + o, + revision, + length ); + encryptionKey = + encryption.computeEncryptedKey( + computedUserPassword, o, + permissions, id.getBytes(), revision, length ); + } + else + { + throw new InvalidPasswordException( "Error: The supplied password does not match " + + "either the owner or user password in the document." ); + } + + COSDictionary trailer = document.getTrailer(); + COSArray fields = (COSArray)trailer.getObjectFromPath( "Root/AcroForm/Fields" ); + + //We need to collect all the signature dictionaries, for some + //reason the 'Contents' entry of signatures is not really encrypted + if( fields != null ) + { + for( int i=0; i> 8) & 0xff); + newKey[newKey.length -3] = (byte)((objectNumber >> 16) & 0xff); + newKey[newKey.length -2] = (byte)(genNumber & 0xff); + newKey[newKey.length -1] = (byte)((genNumber >> 8) & 0xff); + + + //step 3 + byte[] digestedKey = null; + try + { + MessageDigest md = MessageDigest.getInstance( "MD5" ); + digestedKey = md.digest( newKey ); + } + catch( NoSuchAlgorithmException e ) + { + throw new CryptographyException( e ); + } + + //step 4 + int length = Math.min( newKey.length, 16 ); + byte[] finalKey = new byte[ length ]; + System.arraycopy( digestedKey, 0, finalKey, 0, length ); + + rc4.setKey( finalKey ); + rc4.write( data, output ); + output.flush(); + } + + /** + * This will get the user password from the owner password and the documents o value. + * + * @param ownerPassword The plaintext owner password. + * @param o The document's o entry. + * @param revision The document revision number. + * @param length The length of the encryption. + * + * @return The plaintext padded user password. + * + * @throws CryptographyException If there is an error getting the user password. + * @throws IOException If there is an error reading data. + */ + public final byte[] getUserPassword( + byte[] ownerPassword, + byte[] o, + int revision, + long length ) + throws CryptographyException, IOException + { + try + { + ByteArrayOutputStream result = new ByteArrayOutputStream(); + + //3.3 STEP 1 + byte[] ownerPadded = truncateOrPad( ownerPassword ); + + //3.3 STEP 2 + MessageDigest md = MessageDigest.getInstance( "MD5" ); + md.update( ownerPadded ); + byte[] digest = md.digest(); + + //3.3 STEP 3 + if( revision == 3 || revision == 4 ) + { + for( int i=0; i<50; i++ ) + { + md.reset(); + md.update( digest ); + digest = md.digest(); + } + } + if( revision == 2 && length != 5 ) + { + throw new CryptographyException( + "Error: Expected length=5 actual=" + length ); + } + + //3.3 STEP 4 + byte[] rc4Key = new byte[ (int)length ]; + System.arraycopy( digest, 0, rc4Key, 0, (int)length ); + + //3.7 step 2 + if( revision == 2 ) + { + rc4.setKey( rc4Key ); + rc4.write( o, result ); + } + else if( revision == 3 || revision == 4) + { + /** + byte[] iterationKey = new byte[ rc4Key.length ]; + byte[] dataToEncrypt = o; + for( int i=19; i>=0; i-- ) + { + System.arraycopy( rc4Key, 0, iterationKey, 0, rc4Key.length ); + for( int j=0; j< iterationKey.length; j++ ) + { + iterationKey[j] = (byte)(iterationKey[j] ^ (byte)i); + } + rc4.setKey( iterationKey ); + rc4.write( dataToEncrypt, result ); + dataToEncrypt = result.toByteArray(); + result.reset(); + } + result.write( dataToEncrypt, 0, dataToEncrypt.length ); + */ + byte[] iterationKey = new byte[ rc4Key.length ]; + + + byte[] otemp = new byte[ o.length ]; //sm + System.arraycopy( o, 0, otemp, 0, o.length ); //sm + rc4.write( o, result);//sm + + for( int i=19; i>=0; i-- ) + { + System.arraycopy( rc4Key, 0, iterationKey, 0, rc4Key.length ); + for( int j=0; j< iterationKey.length; j++ ) + { + iterationKey[j] = (byte)(iterationKey[j] ^ (byte)i); + } + rc4.setKey( iterationKey ); + result.reset(); //sm + rc4.write( otemp, result ); //sm + otemp = result.toByteArray(); //sm + } + } + + + return result.toByteArray(); + + } + catch( NoSuchAlgorithmException e ) + { + throw new CryptographyException( e ); + } + } + + /** + * This will tell if this is the owner password or not. + * + * @param ownerPassword The plaintext owner password. + * @param u The U value from the PDF Document. + * @param o The owner password hash. + * @param permissions The document permissions. + * @param id The document id. + * @param revision The revision of the encryption. + * @param length The length of the encryption key. + * + * @return true if the owner password matches the one from the document. + * + * @throws CryptographyException If there is an error while executing crypt functions. + * @throws IOException If there is an error while checking owner password. + */ + public final boolean isOwnerPassword( + byte[] ownerPassword, + byte[] u, + byte[] o, + int permissions, + byte[] id, + int revision, + int length) + throws CryptographyException, IOException + { + byte[] userPassword = getUserPassword( ownerPassword, o, revision, length ); + return isUserPassword( userPassword, u, o, permissions, id, revision, length ); + } + + /** + * This will tell if this is a valid user password. + * + * Algorithm 3.6 pg 80 + * + * @param password The password to test. + * @param u The U value from the PDF Document. + * @param o The owner password hash. + * @param permissions The document permissions. + * @param id The document id. + * @param revision The revision of the encryption. + * @param length The length of the encryption key. + * + * @return true If this is the correct user password. + * + * @throws CryptographyException If there is an error computing the value. + * @throws IOException If there is an IO error while computing the owners password. + */ + public final boolean isUserPassword( + byte[] password, + byte[] u, + byte[] o, + int permissions, + byte[] id, + int revision, + int length) + throws CryptographyException, IOException + { + boolean matches = false; + //STEP 1 + byte[] computedValue = computeUserPassword( password, o, permissions, id, revision, length ); + if( revision == 2 ) + { + //STEP 2 + matches = arraysEqual( u, computedValue ); + } + else if( revision == 3 || revision == 4 ) + { + //STEP 2 + matches = arraysEqual( u, computedValue, 16 ); + } + return matches; + } + + /** + * This will compare two byte[] for equality for count number of bytes. + * + * @param first The first byte array. + * @param second The second byte array. + * @param count The number of bytes to compare. + * + * @return true If the arrays contain the exact same data. + */ + private final boolean arraysEqual( byte[] first, byte[] second, int count ) + { + boolean equal = first.length >= count && second.length >= count; + for( int i=0; i>> 0); + byte one = (byte)(permissions >>> 8); + byte two = (byte)(permissions >>> 16); + byte three = (byte)(permissions >>> 24); + + md.update( zero ); + md.update( one ); + md.update( two ); + md.update( three ); + + //step 5 + md.update( id ); + byte[] digest = md.digest(); + + //step 6 + if( revision == 3 || revision == 4) + { + for( int i=0; i<50; i++ ) + { + md.reset(); + md.update( digest, 0, length ); + digest = md.digest(); + } + } + + //step 7 + if( revision == 2 && length != 5 ) + { + throw new CryptographyException( + "Error: length should be 5 when revision is two actual=" + length ); + } + System.arraycopy( digest, 0, result, 0, length ); + } + catch( NoSuchAlgorithmException e ) + { + throw new CryptographyException( e ); + } + return result; + } + + /** + * This algorithm is taked from PDF Reference 1.4 Algorithm 3.3 Page 79. + * + * @param ownerPassword The plain owner password. + * @param userPassword The plain user password. + * @param revision The version of the security. + * @param length The length of the document. + * + * @return The computed owner password. + * + * @throws CryptographyException If there is an error computing O. + * @throws IOException If there is an error computing O. + */ + public final byte[] computeOwnerPassword( + byte[] ownerPassword, + byte[] userPassword, + int revision, + int length ) + throws CryptographyException, IOException + { + try + { + //STEP 1 + byte[] ownerPadded = truncateOrPad( ownerPassword ); + + //STEP 2 + MessageDigest md = MessageDigest.getInstance( "MD5" ); + md.update( ownerPadded ); + byte[] digest = md.digest(); + + //STEP 3 + if( revision == 3 || revision == 4) + { + for( int i=0; i<50; i++ ) + { + md.reset(); + md.update( digest, 0, length ); + digest = md.digest(); + } + } + if( revision == 2 && length != 5 ) + { + throw new CryptographyException( + "Error: Expected length=5 actual=" + length ); + } + + //STEP 4 + byte[] rc4Key = new byte[ length ]; + System.arraycopy( digest, 0, rc4Key, 0, length ); + + //STEP 5 + byte[] paddedUser = truncateOrPad( userPassword ); + + + //STEP 6 + rc4.setKey( rc4Key ); + ByteArrayOutputStream crypted = new ByteArrayOutputStream(); + rc4.write( new ByteArrayInputStream( paddedUser ), crypted ); + + + //STEP 7 + if( revision == 3 || revision == 4 ) + { + byte[] iterationKey = new byte[ rc4Key.length ]; + for( int i=1; i<20; i++ ) + { + System.arraycopy( rc4Key, 0, iterationKey, 0, rc4Key.length ); + for( int j=0; j< iterationKey.length; j++ ) + { + iterationKey[j] = (byte)(iterationKey[j] ^ (byte)i); + } + rc4.setKey( iterationKey ); + ByteArrayInputStream input = new ByteArrayInputStream( crypted.toByteArray() ); + crypted.reset(); + rc4.write( input, crypted ); + } + } + + //STEP 8 + return crypted.toByteArray(); + } + catch( NoSuchAlgorithmException e ) + { + throw new CryptographyException( e.getMessage() ); + } + } + + /** + * This will take the password and truncate or pad it as necessary. + * + * @param password The password to pad or truncate. + * + * @return The padded or truncated password. + */ + private final byte[] truncateOrPad( byte[] password ) + { + byte[] padded = new byte[ ENCRYPT_PADDING.length ]; + int bytesBeforePad = Math.min( password.length, padded.length ); + System.arraycopy( password, 0, padded, 0, bytesBeforePad ); + System.arraycopy( ENCRYPT_PADDING, 0, padded, bytesBeforePad, ENCRYPT_PADDING.length-bytesBeforePad ); + return padded; + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/encryption/package.html b/src/main/java/org/pdfbox/encryption/package.html new file mode 100644 index 0000000..62bc982 --- /dev/null +++ b/src/main/java/org/pdfbox/encryption/package.html @@ -0,0 +1,9 @@ + + + + + + +These classes deal with encryption algorithms that are used in the PDF Document. + + diff --git a/src/main/java/org/pdfbox/examples/AbstractExample.java b/src/main/java/org/pdfbox/examples/AbstractExample.java new file mode 100644 index 0000000..1350b73 --- /dev/null +++ b/src/main/java/org/pdfbox/examples/AbstractExample.java @@ -0,0 +1,125 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.examples; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import org.pdfbox.cos.COSDocument; + +import org.pdfbox.pdmodel.PDDocument; + +import org.pdfbox.pdfwriter.COSWriter; + +/** + * A simple class which has some methods used by all examples. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.3 $ + */ +public abstract class AbstractExample +{ + /** + * Close the stream. + * + * @param stream The stream to close. + * + * @throws IOException If there is an error closing the stream. + */ + public void close( InputStream stream ) throws IOException + { + if( stream != null ) + { + stream.close(); + } + } + + /** + * Close the stream. + * + * @param stream The stream to close. + * + * @throws IOException If there is an error closing the stream. + */ + public void close( OutputStream stream ) throws IOException + { + if( stream != null ) + { + stream.close(); + } + } + + /** + * Close the document. + * + * @param doc The doc to close. + * + * @throws IOException If there is an error closing the document. + */ + public void close( COSDocument doc ) throws IOException + { + if( doc != null ) + { + doc.close(); + } + } + + /** + * Close the document. + * + * @param doc The doc to close. + * + * @throws IOException If there is an error closing the document. + */ + public void close( PDDocument doc ) throws IOException + { + if( doc != null ) + { + doc.close(); + } + } + + /** + * Close the writer. + * + * @param writer The writer to close. + * + * @throws IOException If there is an error closing the writer. + */ + public static void close( COSWriter writer ) throws IOException + { + if( writer != null ) + { + writer.close(); + } + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/examples/fdf/PrintFields.java b/src/main/java/org/pdfbox/examples/fdf/PrintFields.java new file mode 100644 index 0000000..189ba72 --- /dev/null +++ b/src/main/java/org/pdfbox/examples/fdf/PrintFields.java @@ -0,0 +1,163 @@ +/** + * Copyright (c) 2003-2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.examples.fdf; + +import java.io.IOException; + +import java.util.Iterator; +import java.util.List; + +import org.pdfbox.pdmodel.interactive.form.PDAcroForm; +import org.pdfbox.pdmodel.interactive.form.PDField; + +import org.pdfbox.exceptions.CryptographyException; +import org.pdfbox.exceptions.InvalidPasswordException; + +import org.pdfbox.pdmodel.PDDocument; +import org.pdfbox.pdmodel.PDDocumentCatalog; + +/** + * This example will take a PDF document and print all the fields from the file. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.15 $ + */ +public class PrintFields +{ + + /** + * This will print all the fields from the document. + * + * @param pdfDocument The PDF to get the fields from. + * + * @throws IOException If there is an error getting the fields. + */ + public void printFields( PDDocument pdfDocument ) throws IOException + { + PDDocumentCatalog docCatalog = pdfDocument.getDocumentCatalog(); + PDAcroForm acroForm = docCatalog.getAcroForm(); + List fields = acroForm.getFields(); + Iterator fieldsIter = fields.iterator(); + + System.out.println(new Integer(fields.size()).toString() + " top-level fields were found on the form"); + + while( fieldsIter.hasNext()) + { + PDField field = (PDField)fieldsIter.next(); + processField(field, "|--", field.getPartialName()); + } + } + + private void processField(PDField field, String sLevel, String sParent) throws IOException + { + List kids = field.getKids(); + if(kids != null) + { + Iterator kidsIter = kids.iterator(); + if(!sParent.equals(field.getPartialName())) + { + sParent = sParent + "." + field.getPartialName(); + } + System.out.println(sLevel + sParent); + //System.out.println(sParent + " is of type " + field.getClass().getName()); + while(kidsIter.hasNext()) + { + Object pdfObj = kidsIter.next(); + if(pdfObj instanceof PDField) + { + PDField kid = (PDField)pdfObj; + processField(kid, "| " + sLevel, sParent); + } + } + } + else + { + String outputString = sLevel + sParent + "." + field.getPartialName() + " = " + field.getValue() + + ", type=" + field.getClass().getName(); + + System.out.println(outputString); + } + } + + /** + * This will read a PDF file and print out the form elements. + *
+ * see usage() for commandline + * + * @param args command line arguments + * + * @throws IOException If there is an error importing the FDF document. + * @throws CryptographyException If there is an error decrypting the document. + */ + public static void main(String[] args) throws IOException, CryptographyException + { + PDDocument pdf = null; + try + { + if( args.length != 1 ) + { + usage(); + } + else + { + pdf = PDDocument.load( args[0] ); + PrintFields exporter = new PrintFields(); + if( pdf.isEncrypted() ) + { + try + { + pdf.decrypt( "" ); + } + catch( InvalidPasswordException e ) + { + System.err.println( "Error: The document is encrypted." ); + usage(); + } + } + exporter.printFields( pdf ); + } + } + finally + { + if( pdf != null ) + { + pdf.close(); + } + } + } + /** + * This will print out a message telling how to use this example. + */ + private static void usage() + { + System.err.println( "usage: org.pdfbox.examples.fdf.PrintFields " ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/examples/fdf/SetField.java b/src/main/java/org/pdfbox/examples/fdf/SetField.java new file mode 100644 index 0000000..904feeb --- /dev/null +++ b/src/main/java/org/pdfbox/examples/fdf/SetField.java @@ -0,0 +1,128 @@ +/** + * Copyright (c) 2003-2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.examples.fdf; + +import java.io.IOException; + +import org.pdfbox.pdmodel.interactive.form.PDAcroForm; +import org.pdfbox.pdmodel.interactive.form.PDField; + +import org.pdfbox.pdmodel.PDDocument; +import org.pdfbox.pdmodel.PDDocumentCatalog; + +import org.pdfbox.exceptions.COSVisitorException; + +import org.pdfbox.examples.AbstractExample; + +/** + * This example will take a PDF document and set a FDF field in it. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.6 $ + */ +public class SetField extends AbstractExample +{ + + /** + * This will set a single field in the document. + * + * @param pdfDocument The PDF to set the field in. + * @param name The name of the field to set. + * @param value The new value of the field. + * + * @throws IOException If there is an error setting the field. + */ + public void setField( PDDocument pdfDocument, String name, String value ) throws IOException + { + PDDocumentCatalog docCatalog = pdfDocument.getDocumentCatalog(); + PDAcroForm acroForm = docCatalog.getAcroForm(); + PDField field = acroForm.getField( name ); + if( field != null ) + { + field.setValue( value ); + } + else + { + System.err.println( "No field found with name:" + name ); + } + + } + + /** + * This will read a PDF file and set a field and then write it the pdf out again. + *
+ * see usage() for commandline + * + * @param args command line arguments + * + * @throws IOException If there is an error importing the FDF document. + * @throws COSVisitorException If there is an error writing the PDF. + */ + public static void main(String[] args) throws IOException, COSVisitorException + { + SetField setter = new SetField(); + setter.setField( args ); + } + + private void setField( String[] args ) throws IOException, COSVisitorException + { + PDDocument pdf = null; + try + { + if( args.length != 3 ) + { + usage(); + } + else + { + SetField example = new SetField(); + + pdf = PDDocument.load( args[0] ); + example.setField( pdf, args[1], args[2] ); + pdf.save( args[0] ); + } + } + finally + { + if( pdf != null ) + { + pdf.close(); + } + } + } + /** + * This will print out a message telling how to use this example. + */ + private static void usage() + { + System.err.println( "usage: org.pdfbox.examples.fdf.SetField " ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/examples/fdf/package.html b/src/main/java/org/pdfbox/examples/fdf/package.html new file mode 100644 index 0000000..5c80aca --- /dev/null +++ b/src/main/java/org/pdfbox/examples/fdf/package.html @@ -0,0 +1,9 @@ + + + + + + +These are examples that use the FDF features of a PDF document. + + diff --git a/src/main/java/org/pdfbox/examples/package.html b/src/main/java/org/pdfbox/examples/package.html new file mode 100644 index 0000000..fe059eb --- /dev/null +++ b/src/main/java/org/pdfbox/examples/package.html @@ -0,0 +1,9 @@ + + + + + + +The packages in this package will show how to use the PDFBox API. + + diff --git a/src/main/java/org/pdfbox/examples/pdmodel/AddJavascript.java b/src/main/java/org/pdfbox/examples/pdmodel/AddJavascript.java new file mode 100644 index 0000000..d04700e --- /dev/null +++ b/src/main/java/org/pdfbox/examples/pdmodel/AddJavascript.java @@ -0,0 +1,96 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.examples.pdmodel; + +import org.pdfbox.pdmodel.PDDocument; +import org.pdfbox.pdmodel.interactive.action.type.PDActionJavaScript; + +import java.io.IOException; + +/** + * This is an example of how to set some javascript in the document. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.2 $ + */ +public class AddJavascript +{ + private AddJavascript() + { + //static class, should not be instantiated. + } + + /** + * This will print the documents data. + * + * @param args The command line arguments. + * + * @throws Exception If there is an error parsing the document. + */ + public static void main( String[] args ) throws Exception + { + if( args.length != 2 ) + { + usage(); + } + else + { + PDDocument document = null; + try + { + document = PDDocument.load( args[0] ); + PDActionJavaScript javascript = new PDActionJavaScript( + "app.alert( {cMsg: 'PDFBox rocks!', nIcon: 3, nType: 0, cTitle: 'PDFBox Javascript example' } );"); + document.getDocumentCatalog().setOpenAction( javascript ); + if( document.isEncrypted() ) + { + throw new IOException( "Encrypted documents are not supported for this example" ); + } + document.save( args[1] ); + } + finally + { + if( document != null ) + { + document.close(); + } + } + } + } + + /** + * This will print the usage for this document. + */ + private static void usage() + { + System.err.println( "Usage: java org.pdfbox.examples.pdmodel.AddJavascript " ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/examples/pdmodel/AddMessageToEachPage.java b/src/main/java/org/pdfbox/examples/pdmodel/AddMessageToEachPage.java new file mode 100644 index 0000000..efb6ec1 --- /dev/null +++ b/src/main/java/org/pdfbox/examples/pdmodel/AddMessageToEachPage.java @@ -0,0 +1,148 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.examples.pdmodel; + +import java.io.IOException; +import java.util.List; + +import org.pdfbox.exceptions.COSVisitorException; + +import org.pdfbox.pdmodel.PDDocument; +import org.pdfbox.pdmodel.PDPage; + +import org.pdfbox.pdmodel.common.PDRectangle; +import org.pdfbox.pdmodel.edit.PDPageContentStream; + +import org.pdfbox.pdmodel.font.PDFont; +import org.pdfbox.pdmodel.font.PDType1Font; + + +/** + * This is an example of how to add a message to every page + * in a pdf document. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.2 $ + */ +public class AddMessageToEachPage +{ + /** + * Constructor. + */ + public AddMessageToEachPage() + { + super(); + } + + /** + * create the second sample document from the PDF file format specification. + * + * @param file The file to write the PDF to. + * @param message The message to write in the file. + * @param outfile The resulting PDF. + * + * @throws IOException If there is an error writing the data. + * @throws COSVisitorException If there is an error writing the PDF. + */ + public void doIt( String file, String message, String outfile ) throws IOException, COSVisitorException + { + // the document + PDDocument doc = null; + try + { + doc = PDDocument.load( file ); + + List allPages = doc.getDocumentCatalog().getAllPages(); + PDFont font = PDType1Font.HELVETICA_BOLD; + float fontSize = 12.0f; + + for( int i=0; i + * see usage() for commandline + * + * @param args Command line arguments. + */ + public static void main(String[] args) + { + AddMessageToEachPage app = new AddMessageToEachPage(); + try + { + if( args.length != 3 ) + { + app.usage(); + } + else + { + app.doIt( args[0], args[1], args[2] ); + } + } + catch (Exception e) + { + e.printStackTrace(); + } + } + + /** + * This will print out a message telling how to use this example. + */ + private void usage() + { + System.err.println( "usage: " + this.getClass().getName() + " " ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/examples/pdmodel/AddMetadataFromDocInfo.java b/src/main/java/org/pdfbox/examples/pdmodel/AddMetadataFromDocInfo.java new file mode 100644 index 0000000..35080cd --- /dev/null +++ b/src/main/java/org/pdfbox/examples/pdmodel/AddMetadataFromDocInfo.java @@ -0,0 +1,180 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.examples.pdmodel; + +import org.pdfbox.pdmodel.PDDocument; +import org.pdfbox.pdmodel.PDDocumentCatalog; +import org.pdfbox.pdmodel.PDDocumentInformation; +import org.pdfbox.pdmodel.common.PDMetadata; +import org.pdfbox.util.DateConverter; + +import java.io.ByteArrayInputStream; +import java.util.Calendar; +import java.util.GregorianCalendar; + +/** + * This is an example on how to add metadata to a document. + * + * Usage: java org.pdfbox.examples.pdmodel.AddMetadataToDocument <input-pdf> <output-pdf> + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.2 $ + */ +public class AddMetadataFromDocInfo +{ + private static final String PADDING = + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " "; + + + + private AddMetadataFromDocInfo() + { + //utility class + } + + /** + * This will print the documents data. + * + * @param args The command line arguments. + * + * @throws Exception If there is an error parsing the document. + */ + public static void main( String[] args ) throws Exception + { + if( args.length != 2 ) + { + usage(); + } + else + { + PDDocument document = null; + + try + { + document = PDDocument.load( args[0] ); + if( document.isEncrypted() ) + { + System.err.println( "Error: Cannot add metadata to encrypted document." ); + System.exit( 1 ); + } + PDDocumentCatalog catalog = document.getDocumentCatalog(); + PDDocumentInformation info = document.getDocumentInformation(); + + //Right now, PDFBox does not have any XMP library, so we will + //just consruct the XML by hand. + StringBuffer xmp= new StringBuffer(); + xmp.append( + "\n" + + "\n" + + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " " + fixNull( info.getTitle() ) +"\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " PDFBox.org\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " " + fixNull( info.getSubject() ) +"\n" + + " \n" + + " \n" + + " \n" + + " \n" + + "\n" ); + + //xmp spec says we should put padding, so that the metadata can be appended to + //in place + xmp.append( PADDING ); + xmp.append( PADDING ); + xmp.append( PADDING ); + xmp.append( "\n" ); + ByteArrayInputStream mdInput = new ByteArrayInputStream( xmp.toString().getBytes() ); + PDMetadata metadataStream = new PDMetadata(document, mdInput, false ); + catalog.setMetadata( metadataStream ); + + + document.save( args[1] ); + } + finally + { + if( document != null ) + { + document.close(); + } + } + } + } + + private static String fixNull( String string ) + { + return string == null ? "" : string; + } + + private static String fixNull( Calendar cal ) + { + return cal == null ? "" : DateConverter.toISO8601( cal ); + } + + /** + * This will print the usage for this document. + */ + private static void usage() + { + System.err.println( "Usage: java org.pdfbox.examples.pdmodel.AddMetadata " ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/examples/pdmodel/CreateBlankPDF.java b/src/main/java/org/pdfbox/examples/pdmodel/CreateBlankPDF.java new file mode 100644 index 0000000..6d942ac --- /dev/null +++ b/src/main/java/org/pdfbox/examples/pdmodel/CreateBlankPDF.java @@ -0,0 +1,123 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.examples.pdmodel; + +import java.io.FileOutputStream; +import java.io.IOException; + +import org.pdfbox.exceptions.COSVisitorException; + +import org.pdfbox.pdfwriter.COSWriter; + +import org.pdfbox.pdmodel.PDDocument; +import org.pdfbox.pdmodel.PDPage; + +/** + * This will create a blank PDF and write the contents to a file. + * + * usage: java org.pdfbox.examples.pdmodel.CreateBlankPDF <outputfile.pdf> + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.7 $ + */ +public class CreateBlankPDF +{ + + /** + * This will create a blank PDF and write the contents to a file. + * + * @param file The name of the file to write to. + * + * @throws IOException If there is an error writing the data. + * @throws COSVisitorException If there is an error while generating the document. + */ + public void create( String file ) throws IOException, COSVisitorException + { + PDDocument document = null; + FileOutputStream output = null; + COSWriter writer = null; + try + { + document = new PDDocument(); + //Every document requires at least one page, so we will add one + //blank page. + PDPage blankPage = new PDPage(); + document.addPage( blankPage ); + output = new FileOutputStream( file ); + writer = new COSWriter( output ); + writer.write( document.getDocument() ); + } + finally + { + if( writer != null ) + { + writer.close(); + } + if( output != null ) + { + output.close(); + } + if( document != null ) + { + document.close(); + } + } + } + + /** + * This will create a blank document. + * + * @param args The command line arguments. + * + * @throws IOException If there is an error writing the document data. + * @throws COSVisitorException If there is an error generating the data. + */ + public static void main( String[] args ) throws IOException, COSVisitorException + { + if( args.length != 1 ) + { + usage(); + } + else + { + CreateBlankPDF creator = new CreateBlankPDF(); + creator.create( args[0] ); + } + } + + /** + * This will print the usage of this class. + */ + private static void usage() + { + System.err.println( "usage: java org.pdfbox.examples.pdmodel.CreateBlankPDF " ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/examples/pdmodel/CreateBookmarks.java b/src/main/java/org/pdfbox/examples/pdmodel/CreateBookmarks.java new file mode 100644 index 0000000..88c09fb --- /dev/null +++ b/src/main/java/org/pdfbox/examples/pdmodel/CreateBookmarks.java @@ -0,0 +1,119 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.examples.pdmodel; + +import org.pdfbox.pdmodel.PDDocument; +import org.pdfbox.pdmodel.PDPage; +import org.pdfbox.pdmodel.interactive.documentnavigation.destination.PDPageFitWidthDestination; +import org.pdfbox.pdmodel.interactive.documentnavigation.outline.PDDocumentOutline; +import org.pdfbox.pdmodel.interactive.documentnavigation.outline.PDOutlineItem; + +import java.util.List; + +/** + * This is an example on how to add bookmarks to a PDF document. It simply + * adds 1 bookmark for every page. + * + * Usage: java org.pdfbox.examples.pdmodel.CreateBookmarks <input-pdf> <output-pdf> + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.1 $ + */ +public class CreateBookmarks +{ + private CreateBookmarks() + { + //utility class + } + + /** + * This will print the documents data. + * + * @param args The command line arguments. + * + * @throws Exception If there is an error parsing the document. + */ + public static void main( String[] args ) throws Exception + { + if( args.length != 2 ) + { + usage(); + } + else + { + PDDocument document = null; + try + { + document = PDDocument.load( args[0] ); + if( document.isEncrypted() ) + { + System.err.println( "Error: Cannot add bookmarks to encrypted document." ); + System.exit( 1 ); + } + PDDocumentOutline outline = new PDDocumentOutline(); + document.getDocumentCatalog().setDocumentOutline( outline ); + PDOutlineItem pagesOutline = new PDOutlineItem(); + pagesOutline.setTitle( "All Pages" ); + outline.appendChild( pagesOutline ); + List pages = document.getDocumentCatalog().getAllPages(); + for( int i=0; i " ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/examples/pdmodel/EmbeddedFiles.java b/src/main/java/org/pdfbox/examples/pdmodel/EmbeddedFiles.java new file mode 100644 index 0000000..86bc447 --- /dev/null +++ b/src/main/java/org/pdfbox/examples/pdmodel/EmbeddedFiles.java @@ -0,0 +1,170 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.examples.pdmodel; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.util.GregorianCalendar; +import java.util.HashMap; +import java.util.Map; + +import org.pdfbox.exceptions.COSVisitorException; + +import org.pdfbox.pdmodel.PDDocument; +import org.pdfbox.pdmodel.PDDocumentNameDictionary; +import org.pdfbox.pdmodel.PDEmbeddedFilesNameTreeNode; +import org.pdfbox.pdmodel.PDPage; + +import org.pdfbox.pdmodel.common.filespecification.PDComplexFileSpecification; +import org.pdfbox.pdmodel.common.filespecification.PDEmbeddedFile; +import org.pdfbox.pdmodel.edit.PDPageContentStream; + +import org.pdfbox.pdmodel.font.PDFont; +import org.pdfbox.pdmodel.font.PDType1Font; + + +/** + * This is an example that creates a simple document and embeds a file into it.. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.1 $ + */ +public class EmbeddedFiles +{ + /** + * Constructor. + */ + public EmbeddedFiles() + { + super(); + } + + /** + * create the second sample document from the PDF file format specification. + * + * @param file The file to write the PDF to. + * + * @throws IOException If there is an error writing the data. + * @throws COSVisitorException If there is an error writing the PDF. + */ + public void doIt( String file) throws IOException, COSVisitorException + { + // the document + PDDocument doc = null; + try + { + doc = new PDDocument(); + + PDPage page = new PDPage(); + doc.addPage( page ); + PDFont font = PDType1Font.HELVETICA_BOLD; + + PDPageContentStream contentStream = new PDPageContentStream(doc, page); + contentStream.beginText(); + contentStream.setFont( font, 12 ); + contentStream.moveTextPositionByAmount( 100, 700 ); + contentStream.drawString( "Go to Document->File Attachments to View Embedded Files" ); + contentStream.endText(); + contentStream.close(); + + //embedded files are stored in a named tree + PDEmbeddedFilesNameTreeNode efTree = new PDEmbeddedFilesNameTreeNode(); + + + //first create the file specification, which holds the embedded file + PDComplexFileSpecification fs = new PDComplexFileSpecification(); + fs.setFile( "Test.txt" ); + //create a dummy file stream, this would probably normally be a FileInputStream + byte[] data = "This is the contents of the embedded file".getBytes(); + ByteArrayInputStream fakeFile = + new ByteArrayInputStream( data ); + PDEmbeddedFile ef = new PDEmbeddedFile(doc, fakeFile ); + //now lets some of the optional parameters + ef.setSubtype( "test/plain" ); + ef.setSize( data.length ); + ef.setCreationDate( new GregorianCalendar() ); + fs.setEmbeddedFile( ef ); + + //now add the entry to the embedded file tree and set in the document. + Map efMap = new HashMap(); + efMap.put( "My first attachment", fs ); + efTree.setNames( efMap ); + PDDocumentNameDictionary names = new PDDocumentNameDictionary( doc.getDocumentCatalog() ); + names.setEmbeddedFiles( efTree ); + doc.getDocumentCatalog().setNames( names ); + + + doc.save( file ); + } + finally + { + if( doc != null ) + { + doc.close(); + } + } + } + + /** + * This will create a hello world PDF document with an embedded file. + *
+ * see usage() for commandline + * + * @param args Command line arguments. + */ + public static void main(String[] args) + { + EmbeddedFiles app = new EmbeddedFiles(); + try + { + if( args.length != 1 ) + { + app.usage(); + } + else + { + app.doIt( args[0] ); + } + } + catch (Exception e) + { + e.printStackTrace(); + } + } + + /** + * This will print out a message telling how to use this example. + */ + private void usage() + { + System.err.println( "usage: " + this.getClass().getName() + " " ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/examples/pdmodel/HelloWorld.java b/src/main/java/org/pdfbox/examples/pdmodel/HelloWorld.java new file mode 100644 index 0000000..9bceca7 --- /dev/null +++ b/src/main/java/org/pdfbox/examples/pdmodel/HelloWorld.java @@ -0,0 +1,137 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.examples.pdmodel; + +import java.io.IOException; + +import org.pdfbox.exceptions.COSVisitorException; + +import org.pdfbox.pdmodel.PDDocument; +import org.pdfbox.pdmodel.PDPage; + +import org.pdfbox.pdmodel.edit.PDPageContentStream; + +import org.pdfbox.pdmodel.font.PDFont; +import org.pdfbox.pdmodel.font.PDType1Font; + + +/** + * This is an example that creates a simple document. + * + * The example is taken from the pdf file format specification. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.5 $ + */ +public class HelloWorld +{ + /** + * Constructor. + */ + public HelloWorld() + { + super(); + } + + /** + * create the second sample document from the PDF file format specification. + * + * @param file The file to write the PDF to. + * @param message The message to write in the file. + * + * @throws IOException If there is an error writing the data. + * @throws COSVisitorException If there is an error writing the PDF. + */ + public void doIt( String file, String message) throws IOException, COSVisitorException + { + // the document + PDDocument doc = null; + try + { + doc = new PDDocument(); + + PDPage page = new PDPage(); + doc.addPage( page ); + PDFont font = PDType1Font.HELVETICA_BOLD; + + PDPageContentStream contentStream = new PDPageContentStream(doc, page); + contentStream.beginText(); + contentStream.setFont( font, 12 ); + contentStream.moveTextPositionByAmount( 100, 700 ); + contentStream.drawString( message ); + contentStream.endText(); + contentStream.close(); + doc.save( file ); + } + finally + { + if( doc != null ) + { + doc.close(); + } + } + } + + /** + * This will create a hello world PDF document. + *
+ * see usage() for commandline + * + * @param args Command line arguments. + */ + public static void main(String[] args) + { + HelloWorld app = new HelloWorld(); + try + { + if( args.length != 2 ) + { + app.usage(); + } + else + { + app.doIt( args[0], args[1] ); + } + } + catch (Exception e) + { + e.printStackTrace(); + } + } + + /** + * This will print out a message telling how to use this example. + */ + private void usage() + { + System.err.println( "usage: " + this.getClass().getName() + " " ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/examples/pdmodel/HelloWorldTTF.java b/src/main/java/org/pdfbox/examples/pdmodel/HelloWorldTTF.java new file mode 100644 index 0000000..16b1423 --- /dev/null +++ b/src/main/java/org/pdfbox/examples/pdmodel/HelloWorldTTF.java @@ -0,0 +1,134 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ + +package org.pdfbox.examples.pdmodel; + +import java.io.IOException; + +import org.pdfbox.exceptions.COSVisitorException; +import org.pdfbox.pdmodel.PDDocument; +import org.pdfbox.pdmodel.PDPage; +import org.pdfbox.pdmodel.edit.PDPageContentStream; +import org.pdfbox.pdmodel.font.PDFont; +import org.pdfbox.pdmodel.font.PDTrueTypeFont; + +/** + * This is an example that creates a simple document + * with a ttf-font. + * + * @author Michael Niedermair + * @version $Revision: 1.2 $ + */ +public class HelloWorldTTF +{ + + /** + * create the second sample document from the PDF file format specification. + * + * @param file The file to write the PDF to. + * @param message The message to write in the file. + * @param fontfile The ttf-font file. + * + * @throws IOException If there is an error writing the data. + * @throws COSVisitorException If there is an error writing the PDF. + */ + public void doIt(final String file, final String message, + final String fontfile) throws IOException, COSVisitorException + { + + // the document + PDDocument doc = null; + try + { + doc = new PDDocument(); + + PDPage page = new PDPage(); + doc.addPage(page); + PDFont font = PDTrueTypeFont.loadTTF(doc, fontfile); + + PDPageContentStream contentStream = new PDPageContentStream(doc, + page); + contentStream.beginText(); + contentStream.setFont(font, 12); + contentStream.moveTextPositionByAmount(100, 700); + contentStream.drawString(message); + contentStream.endText(); + contentStream.close(); + doc.save(file); + System.out.println(file + " created!"); + } + finally + { + if (doc != null) + { + doc.close(); + } + } + } + + /** + * This will create a hello world PDF document + * with a ttf-font. + *
+ * see usage() for commandline + * + * @param args Command line arguments. + */ + public static void main(String[] args) + { + + HelloWorldTTF app = new HelloWorldTTF(); + try + { + if (args.length != 3) + { + app.usage(); + } + else + { + app.doIt(args[0], args[1], args[2]); + } + } + catch (Exception e) + { + e.printStackTrace(); + } + } + + /** + * This will print out a message telling how to use this example. + */ + private void usage() + { + System.err.println("usage: " + this.getClass().getName() + + " "); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/examples/pdmodel/HelloWorldType1AfmPfb.java b/src/main/java/org/pdfbox/examples/pdmodel/HelloWorldType1AfmPfb.java new file mode 100644 index 0000000..2457a2e --- /dev/null +++ b/src/main/java/org/pdfbox/examples/pdmodel/HelloWorldType1AfmPfb.java @@ -0,0 +1,134 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ + +package org.pdfbox.examples.pdmodel; + +import java.io.IOException; + +import org.pdfbox.exceptions.COSVisitorException; +import org.pdfbox.pdmodel.PDDocument; +import org.pdfbox.pdmodel.PDPage; +import org.pdfbox.pdmodel.edit.PDPageContentStream; +import org.pdfbox.pdmodel.font.PDFont; +import org.pdfbox.pdmodel.font.PDType1AfmPfbFont; + +/** + * This is an example that creates a simple document + * with a Type 1 font (afm + pfb). + * + * @author Michael Niedermair + * @version $Revision: 1.2 $ + */ +public class HelloWorldType1AfmPfb +{ + + /** + * create the second sample document from the PDF file format specification. + * + * @param file The file to write the PDF to. + * @param message The message to write in the file. + * @param fontfile The ttf-font file. + * + * @throws IOException If there is an error writing the data. + * @throws COSVisitorException If there is an error writing the PDF. + */ + public void doIt(final String file, final String message, + final String fontfile) throws IOException, COSVisitorException + { + + // the document + PDDocument doc = null; + try + { + doc = new PDDocument(); + + PDPage page = new PDPage(); + doc.addPage(page); + PDFont font = new PDType1AfmPfbFont(doc,fontfile); + + PDPageContentStream contentStream = new PDPageContentStream(doc, + page); + contentStream.beginText(); + contentStream.setFont(font, 12); + contentStream.moveTextPositionByAmount(100, 700); + contentStream.drawString(message); + contentStream.endText(); + contentStream.close(); + doc.save(file); + System.out.println(file + " created!"); + } + finally + { + if (doc != null) + { + doc.close(); + } + } + } + + /** + * This will create a hello world PDF document + * with a ttf-font. + *
+ * see usage() for commandline + * + * @param args Command line arguments. + */ + public static void main(String[] args) + { + + HelloWorldType1AfmPfb app = new HelloWorldType1AfmPfb(); + try + { + if (args.length != 3) + { + app.usage(); + } + else + { + app.doIt(args[0], args[1], args[2]); + } + } + catch (Exception e) + { + e.printStackTrace(); + } + } + + /** + * This will print out a message telling how to use this example. + */ + private void usage() + { + System.err.println("usage: " + this.getClass().getName() + + " "); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/examples/pdmodel/ImageToPDF.java b/src/main/java/org/pdfbox/examples/pdmodel/ImageToPDF.java new file mode 100644 index 0000000..9faf79d --- /dev/null +++ b/src/main/java/org/pdfbox/examples/pdmodel/ImageToPDF.java @@ -0,0 +1,146 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.examples.pdmodel; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.RandomAccessFile; + +import org.pdfbox.exceptions.COSVisitorException; + +import org.pdfbox.pdmodel.PDDocument; +import org.pdfbox.pdmodel.PDPage; + +import org.pdfbox.pdmodel.edit.PDPageContentStream; + +import org.pdfbox.pdmodel.graphics.xobject.PDCcitt; +import org.pdfbox.pdmodel.graphics.xobject.PDJpeg; +import org.pdfbox.pdmodel.graphics.xobject.PDXObjectImage; + + +/** + * This is an example that creates a simple document. + * + * The example is taken from the pdf file format specification. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.5 $ + */ +public class ImageToPDF +{ + + /** + * create the second sample document from the PDF file format specification. + * + * @param file The file to write the PDF to. + * @param image The filename of the image to put in the PDF. + * + * @throws IOException If there is an error writing the data. + * @throws COSVisitorException If there is an error writing the PDF. + */ + public void createPDFFromImage( String file, String image) throws IOException, COSVisitorException + { + // the document + PDDocument doc = null; + try + { + doc = new PDDocument(); + + PDPage page = new PDPage(); + doc.addPage( page ); + + PDXObjectImage ximage = null; + if( image.toLowerCase().endsWith( ".jpg" ) ) + { + ximage = new PDJpeg(doc, new FileInputStream( image ) ); + } + else if (image.toLowerCase().endsWith(".tif") || image.toLowerCase().endsWith(".tiff")) + { + ximage = new PDCcitt(doc, new RandomAccessFile(new File(image),"r")); + } + else + { + //BufferedImage awtImage = ImageIO.read( new File( image ) ); + //ximage = new PDPixelMap(doc, awtImage); + throw new IOException( "Image type not supported:" + image ); + } + PDPageContentStream contentStream = new PDPageContentStream(doc, page); + + contentStream.drawImage( ximage, 20, 20 ); + + contentStream.close(); + doc.save( file ); + } + finally + { + if( doc != null ) + { + doc.close(); + } + } + } + + /** + * This will create a PDF document with a single image on it. + *
+ * see usage() for commandline + * + * @param args Command line arguments. + */ + public static void main(String[] args) + { + ImageToPDF app = new ImageToPDF(); + try + { + if( args.length != 2 ) + { + app.usage(); + } + else + { + app.createPDFFromImage( args[0], args[1] ); + } + } + catch (Exception e) + { + e.printStackTrace(); + } + } + + /** + * This will print out a message telling how to use this example. + */ + private void usage() + { + System.err.println( "usage: " + this.getClass().getName() + " " ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/examples/pdmodel/PrintBookmarks.java b/src/main/java/org/pdfbox/examples/pdmodel/PrintBookmarks.java new file mode 100644 index 0000000..0a1a647 --- /dev/null +++ b/src/main/java/org/pdfbox/examples/pdmodel/PrintBookmarks.java @@ -0,0 +1,142 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.examples.pdmodel; + +import org.pdfbox.exceptions.InvalidPasswordException; + +import org.pdfbox.pdfparser.PDFParser; + +import org.pdfbox.pdmodel.PDDocument; +import org.pdfbox.pdmodel.interactive.documentnavigation.outline.PDDocumentOutline; +import org.pdfbox.pdmodel.interactive.documentnavigation.outline.PDOutlineItem; +import org.pdfbox.pdmodel.interactive.documentnavigation.outline.PDOutlineNode; + +import java.io.FileInputStream; +import java.io.IOException; + +/** + * This is an example on how to access the bookmarks that are part of a pdf document. + * + * Usage: java org.pdfbox.examples.pdmodel.PrintBookmarks <input-pdf> + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.1 $ + */ +public class PrintBookmarks +{ + /** + * This will print the documents data. + * + * @param args The command line arguments. + * + * @throws Exception If there is an error parsing the document. + */ + public static void main( String[] args ) throws Exception + { + if( args.length != 1 ) + { + usage(); + } + else + { + PDDocument document = null; + FileInputStream file = null; + try + { + file = new FileInputStream( args[0] ); + PDFParser parser = new PDFParser( file ); + parser.parse(); + document = parser.getPDDocument(); + if( document.isEncrypted() ) + { + try + { + document.decrypt( "" ); + } + catch( InvalidPasswordException e ) + { + System.err.println( "Error: Document is encrypted with a password." ); + System.exit( 1 ); + } + } + PrintBookmarks meta = new PrintBookmarks(); + PDDocumentOutline outline = document.getDocumentCatalog().getDocumentOutline(); + if( outline != null ) + { + meta.printBookmark( outline, "" ); + } + else + { + System.out.println( "This document does not contain any bookmarks" ); + } + } + finally + { + if( file != null ) + { + file.close(); + } + if( document != null ) + { + document.close(); + } + } + } + } + + /** + * This will print the usage for this document. + */ + private static void usage() + { + System.err.println( "Usage: java org.pdfbox.examples.pdmodel.PrintBookmarks " ); + } + + /** + * This will print the documents bookmarks to System.out. + * + * @param bookmark The bookmark to print out. + * @param indentation A pretty printing parameter + * + * @throws IOException If there is an error getting the page count. + */ + public void printBookmark( PDOutlineNode bookmark, String indentation ) throws IOException + { + PDOutlineItem current = bookmark.getFirstChild(); + while( current != null ) + { + System.out.println( indentation + current.getTitle() ); + printBookmark( current, indentation + " " ); + current = current.getNextSibling(); + } + + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/examples/pdmodel/PrintDocumentMetaData.java b/src/main/java/org/pdfbox/examples/pdmodel/PrintDocumentMetaData.java new file mode 100644 index 0000000..c096113 --- /dev/null +++ b/src/main/java/org/pdfbox/examples/pdmodel/PrintDocumentMetaData.java @@ -0,0 +1,165 @@ +/** + * Copyright (c) 2003-2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.examples.pdmodel; + +import org.pdfbox.exceptions.InvalidPasswordException; + +import org.pdfbox.pdfparser.PDFParser; + +import org.pdfbox.pdmodel.PDDocument; +import org.pdfbox.pdmodel.PDDocumentCatalog; +import org.pdfbox.pdmodel.PDDocumentInformation; +import org.pdfbox.pdmodel.common.PDMetadata; + +import java.io.FileInputStream; +import java.io.IOException; + +import java.text.SimpleDateFormat; + +import java.util.Calendar; + +/** + * This is an example on how to get a documents metadata information. + * + * Usage: java org.pdfbox.examples.pdmodel.PrintDocumentMetaData <input-pdf> + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.10 $ + */ +public class PrintDocumentMetaData +{ + /** + * This will print the documents data. + * + * @param args The command line arguments. + * + * @throws Exception If there is an error parsing the document. + */ + public static void main( String[] args ) throws Exception + { + if( args.length != 1 ) + { + usage(); + } + else + { + PDDocument document = null; + FileInputStream file = null; + try + { + file = new FileInputStream( args[0] ); + PDFParser parser = new PDFParser( file ); + parser.parse(); + document = parser.getPDDocument(); + if( document.isEncrypted() ) + { + try + { + document.decrypt( "" ); + } + catch( InvalidPasswordException e ) + { + System.err.println( "Error: Document is encrypted with a password." ); + System.exit( 1 ); + } + } + PrintDocumentMetaData meta = new PrintDocumentMetaData(); + meta.printMetadata( document ); + } + finally + { + if( file != null ) + { + file.close(); + } + if( document != null ) + { + document.close(); + } + } + } + } + + /** + * This will print the usage for this document. + */ + private static void usage() + { + System.err.println( "Usage: java org.pdfbox.examples.pdmodel.PrintDocumentMetaData " ); + } + + /** + * This will print the documents data to System.out. + * + * @param document The document to get the metadata from. + * + * @throws IOException If there is an error getting the page count. + */ + public void printMetadata( PDDocument document ) throws IOException + { + PDDocumentInformation info = document.getDocumentInformation(); + PDDocumentCatalog cat = document.getDocumentCatalog(); + PDMetadata metadata = cat.getMetadata(); + System.out.println( "Page Count=" + document.getNumberOfPages() ); + System.out.println( "Title=" + info.getTitle() ); + System.out.println( "Author=" + info.getAuthor() ); + System.out.println( "Subject=" + info.getSubject() ); + System.out.println( "Keywords=" + info.getKeywords() ); + System.out.println( "Creator=" + info.getCreator() ); + System.out.println( "Producer=" + info.getProducer() ); + System.out.println( "Creation Date=" + formatDate( info.getCreationDate() ) ); + System.out.println( "Modification Date=" + formatDate( info.getModificationDate() ) ); + System.out.println( "Trapped=" + info.getTrapped() ); + if( metadata != null ) + { + System.out.println( "Metadata=" + metadata.getInputStreamAsString() ); + } + } + + /** + * This will format a date object. + * + * @param date The date to format. + * + * @return A string representation of the date. + */ + private String formatDate( Calendar date ) + { + String retval = null; + if( date != null ) + { + SimpleDateFormat formatter = new SimpleDateFormat(); + retval = formatter.format( date.getTime() ); + } + + return retval; + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/examples/pdmodel/RemoveFirstPage.java b/src/main/java/org/pdfbox/examples/pdmodel/RemoveFirstPage.java new file mode 100644 index 0000000..2b7242b --- /dev/null +++ b/src/main/java/org/pdfbox/examples/pdmodel/RemoveFirstPage.java @@ -0,0 +1,98 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.examples.pdmodel; + +import org.pdfbox.pdmodel.PDDocument; + +import java.io.IOException; + +/** + * This is an example on how to remove pages from a PDF document. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.4 $ + */ +public class RemoveFirstPage +{ + private RemoveFirstPage() + { + //utility class, should not be instantiated. + } + + /** + * This will print the documents data. + * + * @param args The command line arguments. + * + * @throws Exception If there is an error parsing the document. + */ + public static void main( String[] args ) throws Exception + { + if( args.length != 2 ) + { + usage(); + } + else + { + PDDocument document = null; + try + { + document = PDDocument.load( args[0] ); + if( document.isEncrypted() ) + { + throw new IOException( "Encrypted documents are not supported for this example" ); + } + if( document.getNumberOfPages() <= 1 ) + { + throw new IOException( "Error: A PDF document must have at least one page, " + + "cannot remove the last page!"); + } + document.removePage( 0 ); + document.save( args[1] ); + } + finally + { + if( document != null ) + { + document.close(); + } + } + } + } + + /** + * This will print the usage for this document. + */ + private static void usage() + { + System.err.println( "Usage: java org.pdfbox.examples.pdmodel.RemoveFirstPage " ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/examples/pdmodel/ReplaceString.java b/src/main/java/org/pdfbox/examples/pdmodel/ReplaceString.java new file mode 100644 index 0000000..bbf8688 --- /dev/null +++ b/src/main/java/org/pdfbox/examples/pdmodel/ReplaceString.java @@ -0,0 +1,186 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.examples.pdmodel; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.List; + +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSString; +import org.pdfbox.exceptions.COSVisitorException; + +import org.pdfbox.pdfparser.PDFStreamParser; +import org.pdfbox.pdfwriter.ContentStreamWriter; +import org.pdfbox.pdmodel.PDDocument; +import org.pdfbox.pdmodel.PDPage; + +import org.pdfbox.pdmodel.common.PDStream; + +import org.pdfbox.util.PDFOperator; + + +/** + * This is an example that will replace a string in a PDF with a new one. + * + * The example is taken from the pdf file format specification. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.2 $ + */ +public class ReplaceString +{ + /** + * Constructor. + */ + public ReplaceString() + { + super(); + } + + /** + * Locate a string in a PDF and replace it with a new string. + * + * @param inputFile The PDF to open. + * @param outputFile The PDF to write to. + * @param strToFind The string to find in the PDF document. + * @param message The message to write in the file. + * + * @throws IOException If there is an error writing the data. + * @throws COSVisitorException If there is an error writing the PDF. + */ + public void doIt( String inputFile, String outputFile, String strToFind, String message) + throws IOException, COSVisitorException + { + // the document + PDDocument doc = null; + try + { + doc = PDDocument.load( inputFile ); + List pages = doc.getDocumentCatalog().getAllPages(); + for( int i=0; i + * see usage() for commandline + * + * @param args Command line arguments. + */ + public static void main(String[] args) + { + ReplaceString app = new ReplaceString(); + try + { + if( args.length != 4 ) + { + app.usage(); + } + else + { + app.doIt( args[0], args[1], args[2], args[3] ); + } + } + catch (Exception e) + { + e.printStackTrace(); + } + } + + /** + * This will print out a message telling how to use this example. + */ + private void usage() + { + System.err.println( "usage: " + this.getClass().getName() + + " " ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/examples/pdmodel/RubberStamp.java b/src/main/java/org/pdfbox/examples/pdmodel/RubberStamp.java new file mode 100644 index 0000000..158e0f8 --- /dev/null +++ b/src/main/java/org/pdfbox/examples/pdmodel/RubberStamp.java @@ -0,0 +1,113 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.examples.pdmodel; + +import org.pdfbox.pdmodel.PDDocument; +import org.pdfbox.pdmodel.PDPage; +import org.pdfbox.pdmodel.common.PDRectangle; +import org.pdfbox.pdmodel.interactive.annotation.PDAnnotationRubberStamp; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * This is an example on how to add annotations to pages of a PDF document. + * + * @author Paul King + * @version $Revision: 1.1 $ + */ +public class RubberStamp +{ + private RubberStamp() + { + //utility class, should not be instantiated. + } + + /** + * This will print the documents data. + * + * @param args The command line arguments. + * + * @throws Exception If there is an error parsing the document. + */ + public static void main( String[] args ) throws Exception + { + if( args.length != 2 ) + { + usage(); + } + else + { + PDDocument document = null; + try + { + document = PDDocument.load( args[0] ); + if( document.isEncrypted() ) + { + throw new IOException( "Encrypted documents are not supported for this example" ); + } + List allpages = new ArrayList(); + document.getDocumentCatalog().getPages().getAllKids(allpages); + + for (int i=0; i < allpages.size(); i++) + { + PDPage apage = (PDPage) allpages.get(i); + List annotations = apage.getAnnotations(); + + PDAnnotationRubberStamp rs = new PDAnnotationRubberStamp(); + rs.setName(PDAnnotationRubberStamp.NAME_TOP_SECRET); + rs.setRectangle(new PDRectangle(100,100)); + rs.setContents("A top secret note"); + + annotations.add(rs); + } + + document.save( args[1] ); + } + finally + { + if( document != null ) + { + document.close(); + } + } + } + } + + /** + * This will print the usage for this document. + */ + private static void usage() + { + System.err.println( "Usage: java org.pdfbox.examples.pdmodel.RubberStamp " ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/examples/pdmodel/ShowColorBoxes.java b/src/main/java/org/pdfbox/examples/pdmodel/ShowColorBoxes.java new file mode 100644 index 0000000..f936642 --- /dev/null +++ b/src/main/java/org/pdfbox/examples/pdmodel/ShowColorBoxes.java @@ -0,0 +1,135 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.examples.pdmodel; + +import java.awt.Color; +import java.io.IOException; + +import org.pdfbox.exceptions.COSVisitorException; + +import org.pdfbox.pdmodel.PDDocument; +import org.pdfbox.pdmodel.PDPage; + +import org.pdfbox.pdmodel.edit.PDPageContentStream; + +/** + * This is an example that creates a simple document. + * + * The example is taken from the pdf file format specification. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.1 $ + */ +public class ShowColorBoxes +{ + /** + * Constructor. + */ + public ShowColorBoxes() + { + super(); + } + + /** + * create the second sample document from the PDF file format specification. + * + * @param file The file to write the PDF to. + * + * @throws IOException If there is an error writing the data. + * @throws COSVisitorException If there is an error writing the PDF. + */ + public void doIt( String file) throws IOException, COSVisitorException + { + // the document + PDDocument doc = null; + try + { + doc = new PDDocument(); + + PDPage page = new PDPage(); + doc.addPage( page ); + + PDPageContentStream contentStream = new PDPageContentStream(doc, page); + //first fill the entire background with cyan + contentStream.setNonStrokingColor( Color.CYAN ); + contentStream.fillRect( 0,0, page.findMediaBox().getWidth(), page.findMediaBox().getHeight() ); + + //then draw a red box in the lower left hand corner + contentStream.setNonStrokingColor( Color.RED ); + contentStream.fillRect( 10, 10, 100, 100 ); + + contentStream.close(); + doc.save( file ); + } + finally + { + if( doc != null ) + { + doc.close(); + } + } + } + + /** + * This will create a hello world PDF document. + *
+ * see usage() for commandline + * + * @param args Command line arguments. + */ + public static void main(String[] args) + { + ShowColorBoxes app = new ShowColorBoxes(); + try + { + if( args.length != 1 ) + { + app.usage(); + } + else + { + app.doIt( args[0] ); + } + } + catch (Exception e) + { + e.printStackTrace(); + } + } + + /** + * This will print out a message telling how to use this example. + */ + private void usage() + { + System.err.println( "usage: " + this.getClass().getName() + " " ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/examples/pdmodel/package.html b/src/main/java/org/pdfbox/examples/pdmodel/package.html new file mode 100644 index 0000000..b9beefa --- /dev/null +++ b/src/main/java/org/pdfbox/examples/pdmodel/package.html @@ -0,0 +1,9 @@ + + + + + + +These examples show how to use the classes in the PDModel package. + + diff --git a/src/main/java/org/pdfbox/examples/persistence/AppendAndFillDoc.java b/src/main/java/org/pdfbox/examples/persistence/AppendAndFillDoc.java new file mode 100644 index 0000000..01b8cf6 --- /dev/null +++ b/src/main/java/org/pdfbox/examples/persistence/AppendAndFillDoc.java @@ -0,0 +1,282 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.examples.persistence; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.FileInputStream; + +import java.util.Iterator; + +import org.pdfbox.pdfparser.PDFParser; + +import org.pdfbox.pdfwriter.COSWriter; + +import org.pdfbox.cos.COSDocument; +import org.pdfbox.cos.COSString; +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSObject; +import org.pdfbox.cos.COSName; +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSNumber; +import org.pdfbox.cos.COSInteger; + +import org.pdfbox.exceptions.COSVisitorException; + +/** + * This concatenates two documents with fields and fills the fields in the two templates using different + * values. + * + * @author Michael Traut + * @version $Revision: 1.6 $ + */ +public class AppendAndFillDoc +{ + /** + * Constructor. + */ + public AppendAndFillDoc() + { + super(); + } + + /** + * Append all pages from source to destination. + * + * todo: this method will go to the pdfmodel package one day + * + * @param destination the document to receive the pages + * @param source the document originating the new pages + * + */ + public void appendDocument(COSDocument destination, COSDocument source) + { + COSDictionary pages2 = getPages(source); + COSArray kids = (COSArray)pages2.getItem(COSName.getPDFName("Kids")); + for (Iterator i = kids.iterator(); i.hasNext();) + { + COSDictionary page = (COSDictionary)((COSObject)i.next()).getObject(); + appendPage(destination, page); + } + } + /** + * append a page dict to destination. + * + * todo: this method will go to the pdfmodel package one day + * + * @param destination the document to receive the page + * @param page the page to append to the document + * + */ + public void appendPage(COSDocument destination, COSDictionary page) + { + // get the parent object (pages dictionary) + COSDictionary pages = getPages(destination); + // and set in the page object + page.setItem(COSName.PARENT, pages); + // add new page to kids entry in the pages dictionary + COSArray kids = (COSArray) pages.getItem(COSName.getPDFName("Kids")); + kids.add(page); + // and increase count + COSNumber count = (COSNumber) pages.getItem(COSName.COUNT); + pages.setItem(COSName.COUNT, new COSInteger(count.intValue() + 1)); + } + /** + * concat two pdf documents and fill fields in both templates + * this is a bit tricky as one has to rename the fields if we use the same template two times. + * here we don't user a clever algorithm to create dynamic fieldnames - this is left to the user.. + * + * @param in1 The first template file + * @param in2 The second template file + * @param out The created fiel with all pages from document one and document two + * @param name1 The name of the PDF field (FDF field) in the first template + * @param value1 The value to be used for the field in the first template + * @param name2 The name of the PDF field (FDF field) in the second template + * @param value2 The value to be used for the field in the second template + * + * @throws IOException If there is an error writing the data. + * @throws COSVisitorException If there is an error generating the PDF document. + */ + public void doIt( String in1, + String in2, + String out, + String name1, + String value1, + String name2, + String value2) throws IOException, COSVisitorException + { + COSDocument doc1 = null; + COSDocument doc2 = null; + InputStream is1 = null; + InputStream is2 = null; + PDFParser parser1 = null; + PDFParser parser2 = null; + + OutputStream os = null; + COSWriter writer = null; + try + { + is1 = new FileInputStream(in1); + parser1 = new PDFParser(is1); + parser1.parse(); + doc1 = parser1.getDocument(); + + is2 = new FileInputStream(in2); + parser2 = new PDFParser(is2); + parser2.parse(); + doc2 = parser2.getDocument(); + + setField(doc1, "doc1", new COSString(name1), new COSString(value1)); + setField(doc2, "doc2", new COSString(name2), new COSString(value2)); + + appendDocument(doc1, doc2); + + os = new FileOutputStream(out); + writer = new COSWriter(os); + writer.write(doc1); + } + finally + { + is1.close(); + doc1.close(); + + is2.close(); + doc2.close(); + + os.close(); + writer.close(); + } + } + + /** + * Lookup the pages dictionary in a document. + * + * todo: this method will go to the pdfmodel package one day + * + * @param doc the document where the pages dict is searched + * + * @return The Pages dictionary. + */ + public COSDictionary getPages(COSDocument doc) + { + // todo should access via catalog instead! + for (Iterator i = doc.getObjects().iterator(); i.hasNext();) + { + COSObject obj = (COSObject) i.next(); + COSBase base = obj.getObject(); + if (base instanceof COSDictionary) + { + COSDictionary dict = (COSDictionary) base; + COSBase type = dict.getItem(COSName.TYPE); + if (type != null && type.equals(COSName.getPDFName("Pages"))) + { + return dict; + } + } + } + return null; + } + /** + * This will concat two pdf documents and fill fields in both. + *
+ * see usage() for commandline + * + * @param args command line arguments + */ + public static void main(String[] args) + { + AppendAndFillDoc app = new AppendAndFillDoc(); + try + { + if( args.length != 7 ) + { + app.usage(); + } + else + { + app.doIt( args[0], args[1], args[2], args[3], args[4], args[5], args[6]); + } + } + catch (Exception e) + { + e.printStackTrace(); + } + } + /** + * lookup and fill the field. + * + * todo: this method will go to the pdfmodel package one day + * + * @param doc the document where the field resides + * @param prefix a prefix to use to make the field name unique in the new document + * @param name the name of the PDF Annotation field + * @param value The desired value to be used for the field + * + */ + public void setField(COSDocument doc, String prefix, COSString name, COSString value) + { + for (Iterator i = doc.getObjects().iterator(); i.hasNext();) + { + COSObject obj = (COSObject) i.next(); + COSBase base = obj.getObject(); + if (base instanceof COSDictionary) + { + COSDictionary dict = (COSDictionary) base; + COSBase type = dict.getItem(COSName.TYPE); + if (type != null && type.equals(COSName.getPDFName("Annot"))) + { + COSBase subtype = dict.getItem(COSName.getPDFName("Subtype")); + if (subtype != null && subtype.equals(COSName.getPDFName("Widget"))) + { + // we found the field + COSBase fname = dict.getItem(COSName.getPDFName("T")); + if (fname != null && fname.equals(name)) + { + dict.setItem(COSName.getPDFName("V"), value); + dict.setItem(COSName.getPDFName("T"), new COSString(prefix + name.getString())); + } + } + } + } + } + } + /** + * This will print out a message telling how to use this example. + */ + private void usage() + { + System.err.println( "usage: " + this.getClass().getName() + + " " ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/examples/persistence/AppendDoc.java b/src/main/java/org/pdfbox/examples/persistence/AppendDoc.java new file mode 100644 index 0000000..68e254c --- /dev/null +++ b/src/main/java/org/pdfbox/examples/persistence/AppendDoc.java @@ -0,0 +1,357 @@ +/** + * Copyright (c) 2003-2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.examples.persistence; + +import java.io.IOException; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSName; +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSNumber; +import org.pdfbox.cos.COSInteger; +import org.pdfbox.cos.COSObject; +import org.pdfbox.cos.COSStream; + +import org.pdfbox.pdmodel.PDDocument; +import org.pdfbox.pdmodel.PDDocumentInformation; +import org.pdfbox.pdmodel.PDPage; + +import org.pdfbox.pdmodel.common.PDStream; + +import org.pdfbox.exceptions.COSVisitorException; + +/** + * This example concatenates two documents and writes the result. + * + * @author Michael Traut + * @version $Revision: 1.17 $ + */ +public class AppendDoc +{ + /** + * Constructor. + */ + public AppendDoc() + { + super(); + } + /** + * append all pages from source to destination. + * + * todo: this method will go to the pdfmodel package one day + * + * @param destination the document to receive the pages + * @param source the document originating the new pages + * + * @throws IOException If there is an error accessing data from either document. + */ + public void appendDocument(PDDocument destination, PDDocument source) throws IOException + { + if( destination.isEncrypted() ) + { + throw new IOException( "Error: destination PDF is encrypted, can't append encrypted PDF documents." ); + } + if( source.isEncrypted() ) + { + throw new IOException( "Error: destination PDF is encrypted, can't append encrypted PDF documents." ); + } + PDDocumentInformation destInfo = destination.getDocumentInformation(); + PDDocumentInformation srcInfo = source.getDocumentInformation(); + destInfo.getDictionary().mergeInto( srcInfo.getDictionary() ); + + COSDictionary destTrailer = destination.getDocument().getTrailer(); + COSDictionary destRoot = (COSDictionary)destTrailer.getDictionaryObject( COSName.ROOT ); + + COSDictionary srcTrailer = source.getDocument().getTrailer(); + COSDictionary srcRoot = (COSDictionary)srcTrailer.getDictionaryObject( COSName.ROOT ); + + COSName openAction = COSName.getPDFName( "OpenAction" ); + if( destRoot.getDictionaryObject( openAction ) == null ) + { + COSBase open = srcRoot.getDictionaryObject( openAction ); + if( open != null ) + { + destRoot.setItem( openAction, copyStreamsIntoDocument( destination, open ) ); + } + } + + COSName acroForm = COSName.getPDFName( "AcroForm" ); + COSDictionary destAcroForm = (COSDictionary)destRoot.getDictionaryObject( acroForm ); + COSDictionary srcAcroForm = (COSDictionary)srcRoot.getDictionaryObject( acroForm ); + if( srcAcroForm != null ) + { + if( destAcroForm == null ) + { + destRoot.setItem( acroForm, copyStreamsIntoDocument( destination, srcAcroForm ) ); + } + else + { + //****************need to do proper merge*************** + //destAcroForm.addAll( (COSArray)copyStreamsIntoDocument( destination, srcAcroForm ) ); + } + } + + COSName threads = COSName.getPDFName( "Threads" ); + COSArray destThreads = (COSArray)destRoot.getDictionaryObject( threads ); + COSArray srcThreads = (COSArray)srcRoot.getDictionaryObject( threads ); + if( srcThreads != null ) + { + if( destThreads == null ) + { + destRoot.setItem( threads, copyStreamsIntoDocument( destination, srcThreads ) ); + } + else + { + destThreads.addAll( (COSArray)copyStreamsIntoDocument( destination, srcThreads ) ); + } + } + + COSName names = COSName.getPDFName( "Names" ); + COSDictionary destNames = (COSDictionary)destRoot.getDictionaryObject( names ); + COSDictionary srcNames = (COSDictionary)srcRoot.getDictionaryObject( names ); + if( srcNames != null ) + { + if( destNames == null ) + { + destRoot.setItem( names, copyStreamsIntoDocument( destination, srcNames ) ); + } + else + { + //warning, potential for collision here!! + destNames.mergeInto( (COSDictionary)copyStreamsIntoDocument( destination, srcNames ) ); + } + } + + COSName outlines = COSName.getPDFName( "Outlines" ); + COSDictionary destOutlines = (COSDictionary)destRoot.getDictionaryObject( outlines ); + COSDictionary srcOutlines = (COSDictionary)srcRoot.getDictionaryObject( outlines ); + if( srcOutlines != null && destOutlines == null ) + { + destRoot.setItem( outlines, copyStreamsIntoDocument( destination, srcOutlines ) ); + } + + COSName pagemode = COSName.getPDFName( "PageMode" ); + COSBase srcPageMode = srcRoot.getDictionaryObject( pagemode ); + if( srcOutlines != null && destOutlines == null ) + { + destRoot.setItem( pagemode, copyStreamsIntoDocument( destination, srcPageMode ) ); + } + + COSName pageLabels = COSName.getPDFName( "PageLabels" ); + COSDictionary destLabels = (COSDictionary)destRoot.getDictionaryObject( pageLabels ); + COSDictionary srcLabels = (COSDictionary)srcRoot.getDictionaryObject( pageLabels ); + if( srcLabels != null ) + { + int destPageCount = destination.getNumberOfPages(); + COSArray destNums = null; + if( destLabels == null ) + { + destLabels = new COSDictionary(); + destNums = new COSArray(); + destLabels.setItem( COSName.getPDFName( "Nums" ), destNums ); + destRoot.setItem( pageLabels, destLabels ); + } + else + { + destNums = (COSArray)destLabels.getDictionaryObject( COSName.getPDFName( "Nums" ) ); + } + COSArray srcNums = (COSArray)srcLabels.getDictionaryObject( COSName.getPDFName( "Nums" ) ); + for( int i=0; i + * see usage() for commandline + * + * @param args command line arguments + */ + public static void main(String[] args) + { + AppendDoc app = new AppendDoc(); + try + { + if( args.length != 3 ) + { + app.usage(); + } + else + { + app.doIt( args[0], args[1], args[2]); + } + } + catch( Exception e ) + { + e.printStackTrace(); + } + } + /** + * This will print out a message telling how to use this example. + */ + private void usage() + { + System.err.println( "usage: " + this.getClass().getName() + " " ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/examples/persistence/CopyDoc.java b/src/main/java/org/pdfbox/examples/persistence/CopyDoc.java new file mode 100644 index 0000000..a3b7e3f --- /dev/null +++ b/src/main/java/org/pdfbox/examples/persistence/CopyDoc.java @@ -0,0 +1,140 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.examples.persistence; + +import java.io.IOException; + +import org.pdfbox.cos.COSDocument; + + + +import org.pdfbox.pdfparser.PDFParser; + +import org.pdfbox.pdfwriter.COSWriter; +import org.pdfbox.exceptions.COSVisitorException; + +/** + * This is an example used to copy a documents contents from a source doc to destination doc + * via an in-memory document representation. + * + * @author Michael Traut + * @version $Revision: 1.7 $ + */ +public class CopyDoc +{ + /** + * Constructor. + */ + public CopyDoc() + { + super(); + } + + /** + * This will perform the document copy. + * + * @param in The filename used for input. + * @param out The filename used for output. + * + * @throws IOException If there is an error parsing the document. + * @throws COSVisitorException If there is an error while copying the document. + */ + public void doIt(String in, String out) throws IOException, COSVisitorException + { + java.io.InputStream is = null; + java.io.OutputStream os = null; + COSWriter writer = null; + try + { + is = new java.io.FileInputStream(in); + PDFParser parser = new PDFParser(is); + parser.parse(); + + COSDocument doc = parser.getDocument(); + + os = new java.io.FileOutputStream(out); + writer = new COSWriter(os); + + writer.write(doc); + + } + finally + { + if( is != null ) + { + is.close(); + } + if( os != null ) + { + os.close(); + } + if( writer != null ) + { + writer.close(); + } + } + } + + /** + * This will copy a PDF document. + *
+ * see usage() for commandline + * + * @param args command line arguments + */ + public static void main(String[] args) + { + CopyDoc app = new CopyDoc(); + try + { + if( args.length != 2 ) + { + app.usage(); + } + else + { + app.doIt( args[0], args[1]); + } + } + catch (Exception e) + { + e.printStackTrace(); + } + } + + /** + * This will print out a message telling how to use this example. + */ + private void usage() + { + System.err.println( "usage: " + this.getClass().getName() + " " ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/examples/persistence/FieldsDoc.java b/src/main/java/org/pdfbox/examples/persistence/FieldsDoc.java new file mode 100644 index 0000000..e506fe1 --- /dev/null +++ b/src/main/java/org/pdfbox/examples/persistence/FieldsDoc.java @@ -0,0 +1,177 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.examples.persistence; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.FileOutputStream; + +import java.util.Iterator; + +import org.pdfbox.pdfparser.PDFParser; + +import org.pdfbox.pdfwriter.COSWriter; + +import org.pdfbox.cos.COSDocument; +import org.pdfbox.cos.COSString; +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSObject; +import org.pdfbox.cos.COSName; + +import org.pdfbox.exceptions.COSVisitorException; + +/** + * This example fills a field in a pdf document and writes it to new destination. + * + * @author Michael Traut + * @version $Revision: 1.5 $ + */ +public class FieldsDoc +{ + /** + * Constructor. + */ + public FieldsDoc() + { + super(); + } + /** + * fill a field in the pdf. + * + * @param in The template file + * @param out The file to write the PDF to. + * @param name The name of the PDF field (FDF field) + * @param value The value to be used for the field + * + * @throws IOException If there is an error writing the data. + * @throws COSVisitorException If there is an error generating the PDF document. + */ + public void doIt(String in, String out, String name, String value) throws IOException, COSVisitorException + { + java.io.InputStream is = null; + COSDocument doc = null; + OutputStream os = null; + COSWriter writer = null; + try + { + is = new java.io.FileInputStream(in); + PDFParser parser = new PDFParser(is); + parser.parse(); + + doc = parser.getDocument(); + + setField(doc, new COSString(name), new COSString(value)); + + os = new FileOutputStream(out); + writer = new COSWriter(os); + + writer.write(doc); + + } + finally + { + is.close(); + doc.close(); + os.close(); + writer.close(); + } + } + /** + * This will fill a field in a PDF document. + *
+ * see usage() for commandline + * + * @param args command line arguments + */ + public static void main(String[] args) + { + FieldsDoc app = new FieldsDoc(); + try + { + if( args.length != 4 ) + { + app.usage(); + } + else + { + app.doIt( args[0], args[1], args[2], args[3]); + } + } + catch (Exception e) + { + e.printStackTrace(); + } + } + /** + * lookup and fill the field. + * + * todo: this method will go to the pdfmodel package one day + * + * @param doc the document where the field resides + * @param name the name of the PDF Annotation field + * @param value The desired value to be used for the field + * + */ + public void setField(COSDocument doc, COSString name, COSString value) + { + for (Iterator i = doc.getObjects().iterator(); i.hasNext();) + { + COSObject obj = (COSObject) i.next(); + COSBase base = obj.getObject(); + if (base instanceof COSDictionary) + { + COSDictionary dict = (COSDictionary) base; + COSBase type = dict.getItem(COSName.TYPE); + if (type != null && type.equals(COSName.getPDFName("Annot"))) + { + COSBase subtype = dict.getItem(COSName.getPDFName("Subtype")); + if (subtype != null && subtype.equals(COSName.getPDFName("Widget"))) + { + // we found the field + COSBase fname = dict.getItem(COSName.getPDFName("T")); + if (fname != null && fname.equals(name)) + { + dict.setItem(COSName.getPDFName("V"), value); + } + } + } + } + } + } + /** + * This will print out a message telling how to use this example. + */ + private void usage() + { + System.err.println( "usage: " + this.getClass().getName() + " " ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/examples/persistence/WriteDecodedDoc.java b/src/main/java/org/pdfbox/examples/persistence/WriteDecodedDoc.java new file mode 100644 index 0000000..8fcab7f --- /dev/null +++ b/src/main/java/org/pdfbox/examples/persistence/WriteDecodedDoc.java @@ -0,0 +1,151 @@ +/** + * Copyright (c) 2003-2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.examples.persistence; + +import java.io.IOException; + +import java.util.Iterator; + +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSObject; +import org.pdfbox.cos.COSStream; + +import org.pdfbox.pdmodel.PDDocument; + +import org.pdfbox.exceptions.COSVisitorException; + +import org.pdfbox.exceptions.InvalidPasswordException; + +/** + * load document and write with all streams decoded. + * + * @author Michael Traut + * @version $Revision: 1.8 $ + */ +public class WriteDecodedDoc +{ + + /** + * Constructor. + */ + public WriteDecodedDoc() + { + super(); + } + + /** + * This will perform the document reading, decoding and writing. + * + * @param in The filename used for input. + * @param out The filename used for output. + * + * @throws IOException If there is an error parsing the document. + * @throws COSVisitorException If there is an error while copying the document. + */ + public void doIt(String in, String out) throws IOException, COSVisitorException + { + PDDocument doc = null; + try + { + doc = PDDocument.load( in ); + if( doc.isEncrypted() ) + { + try + { + doc.decrypt( "" ); + } + catch( InvalidPasswordException e ) + { + System.err.println( "Error: The document is encrypted." ); + } + catch( org.pdfbox.exceptions.CryptographyException e ) + { + e.printStackTrace(); + } + } + + for (Iterator i = doc.getDocument().getObjects().iterator(); i.hasNext();) + { + COSBase base = ((COSObject) i.next()).getObject(); + if (base instanceof COSStream) + { + // just kill the filters + COSStream cosStream = (COSStream)base; + cosStream.getUnfilteredStream(); + cosStream.setFilters(null); + } + } + doc.save( out ); + } + finally + { + if( doc != null ) + { + doc.close(); + } + } + } + + /** + * This will write a PDF document with completely decoded streams. + *
+ * see usage() for commandline + * + * @param args command line arguments + */ + public static void main(String[] args) + { + WriteDecodedDoc app = new WriteDecodedDoc(); + try + { + if( args.length != 2 ) + { + app.usage(); + } + else + { + app.doIt( args[0], args[1]); + } + } + catch (Exception e) + { + e.printStackTrace(); + } + } + + /** + * This will print out a message telling how to use this example. + */ + private void usage() + { + System.err.println( "usage: " + this.getClass().getName() + " " ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/examples/persistence/package.html b/src/main/java/org/pdfbox/examples/persistence/package.html new file mode 100644 index 0000000..9c0d57f --- /dev/null +++ b/src/main/java/org/pdfbox/examples/persistence/package.html @@ -0,0 +1,9 @@ + + + + + + +These examples will show how to use the persistence features of the PDFBox. + + diff --git a/src/main/java/org/pdfbox/examples/signature/ShowSignature.java b/src/main/java/org/pdfbox/examples/signature/ShowSignature.java new file mode 100644 index 0000000..7398534 --- /dev/null +++ b/src/main/java/org/pdfbox/examples/signature/ShowSignature.java @@ -0,0 +1,168 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.examples.signature; + +import java.io.ByteArrayInputStream; +import java.io.IOException; + +import java.security.cert.CertificateFactory; + +import java.util.Collection; + +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSName; +import org.pdfbox.cos.COSString; + +import org.pdfbox.pdmodel.PDDocument; + +/** + * This will read a document from the filesystem, decrypt it and do something with the signature. + * + * usage: java org.pdfbox.examples.signature.ShowSignature <password> <inputfile> + * + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.8 $ + */ +public class ShowSignature +{ + + /** + * This is the entry point for the application. + * + * @param args The command-line arguments. + * + * @throws Exception If there is an error reading the file. + */ + public static void main( String[] args ) throws Exception + { + ShowSignature show = new ShowSignature(); + show.showSignature( args ); + } + + private void showSignature( String[] args ) throws Exception + { + if( args.length != 2 ) + { + usage(); + } + else + { + String password = args[0]; + String infile = args[1]; + PDDocument document = null; + try + { + document = PDDocument.load( infile ); + + if( document.isEncrypted() ) + { + document.decrypt( password ); + } + else + { + System.err.println( "Warning: Document is not encrypted." ); + } + + COSDictionary trailer = document.getDocument().getTrailer(); + COSDictionary root = (COSDictionary)trailer.getDictionaryObject( COSName.ROOT ); + COSDictionary acroForm = (COSDictionary)root.getDictionaryObject( COSName.getPDFName( "AcroForm" ) ); + COSArray fields = (COSArray)acroForm.getDictionaryObject( COSName.getPDFName( "Fields" ) ); + for( int i=0; i " ); + } + +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/examples/signature/package.html b/src/main/java/org/pdfbox/examples/signature/package.html new file mode 100644 index 0000000..731c0ff --- /dev/null +++ b/src/main/java/org/pdfbox/examples/signature/package.html @@ -0,0 +1,9 @@ + + + + + + +These examples will show how to gain access to the PDF signature. + + diff --git a/src/main/java/org/pdfbox/examples/util/ExtractTextByArea.java b/src/main/java/org/pdfbox/examples/util/ExtractTextByArea.java new file mode 100644 index 0000000..042e3e6 --- /dev/null +++ b/src/main/java/org/pdfbox/examples/util/ExtractTextByArea.java @@ -0,0 +1,119 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.examples.util; + +import org.pdfbox.exceptions.InvalidPasswordException; + +import org.pdfbox.pdmodel.PDDocument; +import org.pdfbox.pdmodel.PDPage; +import org.pdfbox.util.PDFTextStripperByArea; + +import java.awt.Rectangle; + +import java.util.List; + +/** + * This is an example on how to extract text from a specific area on the PDF document. + * + * Usage: java org.pdfbox.examples.util.ExtractTextByArea <input-pdf> + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.1 $ + */ +public class ExtractTextByArea +{ + private ExtractTextByArea() + { + //utility class and should not be constructed. + } + + + /** + * This will print the documents text in a certain area. + * + * @param args The command line arguments. + * + * @throws Exception If there is an error parsing the document. + */ + public static void main( String[] args ) throws Exception + { + if( args.length != 1 ) + { + usage(); + } + else + { + PDDocument document = null; + try + { + document = PDDocument.load( args[0] ); + if( document.isEncrypted() ) + { + try + { + document.decrypt( "" ); + } + catch( InvalidPasswordException e ) + { + System.err.println( "Error: Document is encrypted with a password." ); + System.exit( 1 ); + } + } + PDFTextStripperByArea stripper = new PDFTextStripperByArea(); + stripper.setSortByPosition( true ); + Rectangle rect = new Rectangle( 10, 280, 275, 60 ); + stripper.addRegion( "class1", rect ); + List allPages = document.getDocumentCatalog().getAllPages(); + PDPage firstPage = (PDPage)allPages.get( 0 ); + stripper.extractRegions( firstPage ); + System.out.println( "Text in the area:" + rect ); + System.out.println( stripper.getTextForRegion( "class1" ) ); + + } + finally + { + if( document != null ) + { + document.close(); + } + } + } + } + + /** + * This will print the usage for this document. + */ + private static void usage() + { + System.err.println( "Usage: java org.pdfbox.examples.util.ExtractTextByArea " ); + } + +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/examples/util/PrintTextLocations.java b/src/main/java/org/pdfbox/examples/util/PrintTextLocations.java new file mode 100644 index 0000000..6c83b57 --- /dev/null +++ b/src/main/java/org/pdfbox/examples/util/PrintTextLocations.java @@ -0,0 +1,144 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.examples.util; + +import org.pdfbox.exceptions.InvalidPasswordException; + +import org.pdfbox.pdfparser.PDFParser; + +import org.pdfbox.pdmodel.PDDocument; +import org.pdfbox.pdmodel.PDPage; +import org.pdfbox.util.PDFTextStripper; +import org.pdfbox.util.TextPosition; + +import java.io.FileInputStream; +import java.io.IOException; + +import java.util.List; + +/** + * This is an example on how to get some x/y coordinates of text. + * + * Usage: java org.pdfbox.examples.util.PrintTextLocations <input-pdf> + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.2 $ + */ +public class PrintTextLocations extends PDFTextStripper +{ + /** + * Default constructor. + * + * @throws IOException If there is an error loading text stripper properties. + */ + public PrintTextLocations() throws IOException + { + //default constructor. + } + + /** + * This will print the documents data. + * + * @param args The command line arguments. + * + * @throws Exception If there is an error parsing the document. + */ + public static void main( String[] args ) throws Exception + { + if( args.length != 1 ) + { + usage(); + } + else + { + PDDocument document = null; + FileInputStream file = null; + try + { + file = new FileInputStream( args[0] ); + PDFParser parser = new PDFParser( file ); + parser.parse(); + document = parser.getPDDocument(); + if( document.isEncrypted() ) + { + try + { + document.decrypt( "" ); + } + catch( InvalidPasswordException e ) + { + System.err.println( "Error: Document is encrypted with a password." ); + System.exit( 1 ); + } + } + PrintTextLocations printer = new PrintTextLocations(); + List allPages = document.getDocumentCatalog().getAllPages(); + for( int i=0; i" ); + } + +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/examples/util/package.html b/src/main/java/org/pdfbox/examples/util/package.html new file mode 100644 index 0000000..bc50f59 --- /dev/null +++ b/src/main/java/org/pdfbox/examples/util/package.html @@ -0,0 +1,9 @@ + + + + + + +The packages in this package will show how to use the PDFBox util API. + + diff --git a/src/main/java/org/pdfbox/exceptions/COSVisitorException.java b/src/main/java/org/pdfbox/exceptions/COSVisitorException.java new file mode 100644 index 0000000..8c5cee1 --- /dev/null +++ b/src/main/java/org/pdfbox/exceptions/COSVisitorException.java @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.exceptions; + +/** + * An exception that represents something gone wrong when visiting a PDF object. + * + * @author Michael Traut + * @version $Revision: 1.6 $ + */ +public class COSVisitorException extends WrappedException +{ + + /** + * COSVisitorException constructor comment. + * + * @param e The root exception that caused this exception. + */ + public COSVisitorException( Exception e ) + { + super( e ); + } + + +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/exceptions/CryptographyException.java b/src/main/java/org/pdfbox/exceptions/CryptographyException.java new file mode 100644 index 0000000..c54fb10 --- /dev/null +++ b/src/main/java/org/pdfbox/exceptions/CryptographyException.java @@ -0,0 +1,82 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.exceptions; + +/** + * An exception that indicates that something has gone wrong during a + * cryptography operation. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.3 $ + */ +public class CryptographyException extends Exception +{ + private Exception embedded; + + /** + * Constructor. + * + * @param msg A msg to go with this exception. + */ + public CryptographyException( String msg ) + { + super( msg ); + } + + /** + * Constructor. + * + * @param e The root exception that caused this exception. + */ + public CryptographyException( Exception e ) + { + super( e.getMessage() ); + setEmbedded( e ); + } + /** + * This will get the exception that caused this exception. + * + * @return The embedded exception if one exists. + */ + public Exception getEmbedded() + { + return embedded; + } + /** + * This will set the exception that caused this exception. + * + * @param e The sub exception. + */ + private void setEmbedded( Exception e ) + { + embedded = e; + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/exceptions/InvalidPasswordException.java b/src/main/java/org/pdfbox/exceptions/InvalidPasswordException.java new file mode 100644 index 0000000..22d92ec --- /dev/null +++ b/src/main/java/org/pdfbox/exceptions/InvalidPasswordException.java @@ -0,0 +1,51 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.exceptions; + +/** + * An exception that indicates an invalid password was supplied. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.3 $ + */ +public class InvalidPasswordException extends Exception +{ + + /** + * Constructor. + * + * @param msg A msg to go with this exception. + */ + public InvalidPasswordException( String msg ) + { + super( msg ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/exceptions/OutlineNotLocalException.java b/src/main/java/org/pdfbox/exceptions/OutlineNotLocalException.java new file mode 100644 index 0000000..db7bf76 --- /dev/null +++ b/src/main/java/org/pdfbox/exceptions/OutlineNotLocalException.java @@ -0,0 +1,55 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.exceptions; + +import java.io.IOException; + +/** + * This exception will be thrown when a local destination(page within the same PDF) is required + * but the bookmark(PDOutlineItem) refers to an external destination or an action that does not + * point to a page. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.1 $ + */ +public class OutlineNotLocalException extends IOException +{ + + /** + * Constructor. + * + * @param msg An error message. + */ + public OutlineNotLocalException( String msg ) + { + super( msg ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/exceptions/WrappedException.java b/src/main/java/org/pdfbox/exceptions/WrappedException.java new file mode 100644 index 0000000..558221d --- /dev/null +++ b/src/main/java/org/pdfbox/exceptions/WrappedException.java @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.exceptions; + +import java.io.PrintStream; + +/** + * An exception that that holds a sub exception. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.1 $ + */ +public class WrappedException extends Exception +{ + private Exception wrapped = null; + + /** + * constructor comment. + * + * @param e The root exception that caused this exception. + */ + public WrappedException( Exception e ) + { + wrapped = e; + } + + /** + * Gets the wrapped exception message. + * + * @return A message indicating the exception. + */ + public String getMessage() + { + return wrapped.getMessage(); + } + + /** + * Prints this throwable and its backtrace to the specified print stream. + * + * @param s PrintStream to use for output + */ + public void printStackTrace(PrintStream s) + { + super.printStackTrace( s ); + wrapped.printStackTrace( s ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/exceptions/WrappedIOException.java b/src/main/java/org/pdfbox/exceptions/WrappedIOException.java new file mode 100644 index 0000000..38a004d --- /dev/null +++ b/src/main/java/org/pdfbox/exceptions/WrappedIOException.java @@ -0,0 +1,76 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.exceptions; + +import java.io.IOException; +import java.io.PrintStream; + +/** + * An exception that that holds a sub exception. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.1 $ + */ +public class WrappedIOException extends IOException +{ + private Throwable wrapped = null; + + /** + * constructor comment. + * + * @param e The root exception that caused this exception. + */ + public WrappedIOException( Throwable e ) + { + wrapped = e; + } + + /** + * Gets the wrapped exception message. + * + * @return A message indicating the exception. + */ + public String getMessage() + { + return wrapped.getMessage(); + } + + /** + * Prints this throwable and its backtrace to the specified print stream. + * + * @param s PrintStream to use for output + */ + public void printStackTrace(PrintStream s) + { + super.printStackTrace( s ); + wrapped.printStackTrace( s ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/exceptions/package.html b/src/main/java/org/pdfbox/exceptions/package.html new file mode 100644 index 0000000..d45d03a --- /dev/null +++ b/src/main/java/org/pdfbox/exceptions/package.html @@ -0,0 +1,9 @@ + + + + + + +This package is a place holder for exceptions that are used in the PDFBox project. + + diff --git a/src/main/java/org/pdfbox/filter/ASCII85Filter.java b/src/main/java/org/pdfbox/filter/ASCII85Filter.java new file mode 100644 index 0000000..335208c --- /dev/null +++ b/src/main/java/org/pdfbox/filter/ASCII85Filter.java @@ -0,0 +1,103 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.filter; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import org.pdfbox.io.ASCII85InputStream; +import org.pdfbox.io.ASCII85OutputStream; + +import org.pdfbox.cos.COSDictionary; + +/** + * This is the used for the ASCIIHexDecode filter. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.6 $ + */ +public class ASCII85Filter implements Filter +{ + /** + * This will decode some compressed data. + * + * @param compressedData The compressed byte stream. + * @param result The place to write the uncompressed byte stream. + * @param options The options to use to encode the data. + * + * @throws IOException If there is an error decompressing the stream. + */ + public void decode( InputStream compressedData, OutputStream result, COSDictionary options ) throws IOException + { + ASCII85InputStream is = null; + try + { + is = new ASCII85InputStream(compressedData); + byte[] buffer = new byte[1024]; + int amountRead = 0; + while( (amountRead = is.read( buffer, 0, 1024) ) != -1 ) + { + result.write(buffer, 0, amountRead); + } + result.flush(); + } + finally + { + if( is != null ) + { + is.close(); + } + } + } + + /** + * This will encode some data. + * + * @param rawData The raw data to encode. + * @param result The place to write to encoded results to. + * @param options The options to use to encode the data. + * + * @throws IOException If there is an error compressing the stream. + */ + public void encode( InputStream rawData, OutputStream result, COSDictionary options ) throws IOException + { + ASCII85OutputStream os = new ASCII85OutputStream(result); + byte[] buffer = new byte[1024]; + int amountRead = 0; + while( (amountRead = rawData.read( buffer, 0, 1024 )) != -1 ) + { + os.write( buffer, 0, amountRead ); + } + os.close(); + result.flush(); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/filter/ASCIIHexFilter.java b/src/main/java/org/pdfbox/filter/ASCIIHexFilter.java new file mode 100644 index 0000000..b3cf506 --- /dev/null +++ b/src/main/java/org/pdfbox/filter/ASCIIHexFilter.java @@ -0,0 +1,205 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.filter; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import org.pdfbox.cos.COSDictionary; + +import org.pdfbox.persistence.util.COSHEXTable; + +/** + * This is the used for the ASCIIHexDecode filter. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.7 $ + */ +public class ASCIIHexFilter implements Filter +{ + private static final int ASCII_ZERO = (int)'0'; + + + /** + * This will decode some compressed data. + * + * @param compressedData The compressed byte stream. + * @param result The place to write the uncompressed byte stream. + * @param options The options to use to encode the data. + * + * @throws IOException If there is an error decompressing the stream. + */ + public void decode( InputStream compressedData, OutputStream result, COSDictionary options ) throws IOException + { + int value =0; + int firstByte = 0; + int secondByte = 0; + while( (firstByte = compressedData.read()) != -1 ) + { + value = REVERSE_HEX[firstByte] * 16; + secondByte = compressedData.read(); + if( secondByte >= 0 ) + { + value += REVERSE_HEX[ secondByte ]; + } + result.write( value ); + } + result.flush(); + } + + private static final int[] REVERSE_HEX = + { + -1, //0 + -1, //1 + -1, //2 + -1, //3 + -1, //4 + -1, //5 + -1, //6 + -1, //7 + -1, //8 + -1, //9 + -1, //10 + -1, //11 + -1, //12 + -1, //13 + -1, //14 + -1, //15 + -1, //16 + -1, //17 + -1, //18 + -1, //19 + -1, //20 + -1, //21 + -1, //22 + -1, //23 + -1, //24 + -1, //25 + -1, //26 + -1, //27 + -1, //28 + -1, //29 + -1, //30 + -1, //31 + -1, //32 + -1, //33 + -1, //34 + -1, //35 + -1, //36 + -1, //37 + -1, //38 + -1, //39 + -1, //40 + -1, //41 + -1, //42 + -1, //43 + -1, //44 + -1, //45 + -1, //46 + -1, //47 + 0, //48 + 1, //49 + 2, //50 + 3, //51 + 4, //52 + 5, //53 + 6, //54 + 7, //55 + 8, //56 + 9, //57 + -1, //58 + -1, //59 + -1, //60 + -1, //61 + -1, //62 + -1, //63 + -1, //64 + 10, //65 + 11, //66 + 12, //67 + 13, //68 + 14, //69 + 15, //70 + -1, //71 + -1, //72 + -1, //73 + -1, //74 + -1, //75 + -1, //76 + -1, //77 + -1, //78 + -1, //79 + -1, //80 + -1, //81 + -1, //82 + -1, //83 + -1, //84 + -1, //85 + -1, //86 + -1, //87 + -1, //88 + -1, //89 + -1, //90 + -1, //91 + -1, //92 + -1, //93 + -1, //94 + -1, //95 + -1, //96 + 10, //97 + 11, //98 + 12, //99 + 13, //100 + 14, //101 + 15, //102 + }; + + /** + * This will encode some data. + * + * @param rawData The raw data to encode. + * @param result The place to write to encoded results to. + * @param options The options to use to encode the data. + * + * @throws IOException If there is an error compressing the stream. + */ + public void encode( InputStream rawData, OutputStream result, COSDictionary options ) throws IOException + { + int byteRead = 0; + while( (byteRead = rawData.read()) != -1 ) + { + int value = (byteRead+256)%256; + result.write( COSHEXTable.TABLE[value] ); + } + result.flush(); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/filter/CCITTFaxDecodeFilter.java b/src/main/java/org/pdfbox/filter/CCITTFaxDecodeFilter.java new file mode 100644 index 0000000..15f4c58 --- /dev/null +++ b/src/main/java/org/pdfbox/filter/CCITTFaxDecodeFilter.java @@ -0,0 +1,735 @@ +/** + * Copyright (c) 2003-2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.filter; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.text.SimpleDateFormat; +import java.util.Date; + +import org.apache.log4j.Logger; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSName; + +/** + * This is a filter for the CCITTFax Decoder. + * + * @author Ben Litchfield, Marcel Kammer, Paul King + * @version $Revision: 1.10 $ + */ +public class CCITTFaxDecodeFilter implements Filter +{ + private static Logger log = Logger.getLogger(CCITTFaxDecodeFilter.class); + + // Filter will write 15 TAG's + // If you add or remove TAG's you will have to modify this value + private static final int TAG_COUNT = 15; + + // HEADERLENGTH(fix 8 Bytes) plus ImageLength(variable) + private int offset = 8; + + // Bytecounter for Bytes that will be written after the TAG-DICTIONARY + private int tailingBytesCount = 0; + + // Bytes to write after TAG-DICTIONARY + private final ByteArrayOutputStream tailer = new ByteArrayOutputStream(); + + /** + * Constructor. + */ + public CCITTFaxDecodeFilter() + { + } + + /** + * This will decode some compressed data. + * + * @param compressedData + * The compressed byte stream. + * @param result + * The place to write the uncompressed byte stream. + * @param options + * The options to use to encode the data. + * + * @throws IOException + * If there is an error decompressing the stream. + */ + public void decode(InputStream compressedData, OutputStream result, COSDictionary options) throws IOException + { + // log.warn( "Warning: CCITTFaxDecode.decode is not implemented yet, + // skipping this stream." ); + + + // Get ImageParams from PDF + COSDictionary dict = (COSDictionary) options.getDictionaryObject("DecodeParms"); + int width = options.getInt("Width"); + int height = options.getInt("Height"); + int length = options.getInt(COSName.LENGTH); + int compressionType = dict.getInt("K"); + boolean blackIs1 = dict.getBoolean("BlackIs1", false); + + + // HEADER-INFO and starting point of TAG-DICTIONARY + writeTagHeader(result, length); + + // IMAGE-DATA + int i = 0; + //int sum = 0; + byte[] buffer = new byte[32768]; + int lentoread = length; + + while ((lentoread > 0) && ((i = compressedData.read(buffer, 0, Math.min(lentoread, 32768))) != -1)) + { + //sum += i; + result.write(buffer, 0, i); + lentoread = lentoread - i; + } + + // If lentoread is > 0 then we need to write out some padding to equal the header + // We'll use what we have in the buffer it's just padding after all + while (lentoread > 0) + { + result.write(buffer, 0, Math.min(lentoread, 32768)); + lentoread = lentoread - Math.min(lentoread, 32738); + } + //System.out.println("Gelesen: " + sum); + + // TAG-COUNT + writeTagCount(result); + + // WIDTH 0x0100 + writeTagWidth(result, width); + + // HEIGHT 0x0101 + writeTagHeight(result, height); + + // BITSPERSAMPLE 0x0102 + // Always 1 for CCITTFax + writeTagBitsPerSample(result, 1); + + // COMPRESSION 0x0103 + writeTagCompression(result, compressionType); + + // PHOTOMETRIC 0x0106 + writeTagPhotometric(result, blackIs1); + + // STRIPOFFSET 0x0111 + // HERE ALWAYS 8, because ImageData comes before TAG-DICTIONARY + writeTagStripOffset(result, 8); + + // ORIENTATION 0x0112 + writeTagOrientation(result, 1); + + // SamplesPerPixel 0x0115 + writeTagSamplesPerPixel(result, 1); + + // RowsPerStrip 0x0116 + writeTagRowsPerStrip(result, height); + + // Stripcount 0x0117 + writeTagStripByteCount(result, length); + + // XRESOLUTION 0x011A + // HERE: 200 DPI + writeTagXRes(result, 200, 1); + + // YRESOLITION 0x011B + // HERE: 200 DPI + writeTagYRes(result, 200, 1); + + // ResolutionUnit 0x0128 + // HERE: DPI + writeTagResolutionUnit(result, 2); + + // SOFTWARE 0x0131 + // minimum 4 chars + writeTagSoftware(result, "pdfbox".getBytes()); + + // DATE AND TIME 0x0132 + writeTagDateTime(result, new Date()); + + // END OF TAG-DICT + writeTagTailer(result); + } + + private void writeTagHeader(OutputStream result, int length) throws IOException + { + byte[] header = { 'M', 'M', 0, '*' };// Big-endian + result.write(header); + + + // Add imagelength to offset + offset += length; + + // OFFSET TAG-DICTIONARY + int i1 = offset/16777216;//=value/(256*256*256) + int i2 = (offset-i1*16777216)/65536; + int i3 = (offset-i1*16777216-i2*65536)/256; + int i4 = offset % 256; + result.write(i1); + result.write(i2); + result.write(i3); + result.write(i4); + } + + private void writeTagCount(OutputStream result) throws IOException + { + result.write(TAG_COUNT / 256); + result.write(TAG_COUNT % 256);// tagCount + } + + private void writeTagWidth(OutputStream result, int width) throws IOException + { + // @todo width berechnen + + // TAG-ID 100 + result.write(1); + result.write(0); + + + // TAG-TYPE SHORT=3 + result.write(0); + result.write(3); + + + // TAG-LENGTH = 1 + result.write(0); + result.write(0); + result.write(0); + result.write(1); + + + // TAG-VALUE = width + result.write(width/256); + result.write(width%256); + result.write(0);// SHORT=0 + result.write(0);// SHORT=0 + + } + + private void writeTagHeight(OutputStream result, int height) throws IOException + { + //@todo height berechnen + // TAG-ID 101 + result.write(1); + result.write(1); + + + // TAG-TYPE SHORT=3 + result.write(0); + result.write(3); + + + // TAG-LENGTH = 1 + result.write(0); + result.write(0); + result.write(0); + result.write(1); + + + // TAG-VALUE + result.write(height/256); + result.write(height%256); + result.write(0);// SHORT=0 + result.write(0);// SHORT=0 + + } + + private void writeTagBitsPerSample(OutputStream result, int value) throws IOException + { + // TAG-ID 102 + result.write(1); + result.write(2); + + + // TAG-TYPE SHORT=3 + result.write(0); + result.write(3); + + // TAG-LENGTH = 1 + result.write(0); + result.write(0); + result.write(0); + result.write(1); + + + // TAG-VALUE + result.write(value/256); + result.write(value%256); + result.write(0);//SHORT=0 + result.write(0);//SHORT=0 + + } + + /** + * Write the tag compression. + * + * @param result The stream to write to. + * @param type The type to write. + * @throws IOException If there is an error writing to the stream. + */ + public void writeTagCompression(OutputStream result, int type) throws IOException + { + // TAG-ID 103 + result.write(1); + result.write(3); + + // TAG-TYPE SHORT=3 + result.write(0); + result.write(3); + + + // TAG-LEGNTH = 1 + result.write(0); + result.write(0); + result.write(0); + result.write(1); + + // TAG-VALUE + //@todo typ eintragen; hier immer 4 + result.write(0); + if (type < 0) + { + result.write(4);// G4 + } + else if (type == 0) + { + result.write(3);// G3-1D + } + else + { + result.write(2);// G3-2D + } + result.write(0); + result.write(0); + + } + + private void writeTagPhotometric(OutputStream result, boolean blackIs1) throws IOException + { + // TAG-ID 106 + result.write(1); + result.write(6); + + + // TAG-TYPE SHORT + result.write(0); + result.write(3); + + + // TAG-LENGTH = 1 + result.write(0); + result.write(0); + result.write(0); + result.write(1); + + + // TAG-VALUE + result.write(0); + if (blackIs1) + { + result.write(1); + } + else + { + result.write(0); + } + result.write(0);// SHORT=0 + result.write(0);// SHORT=0 + + } + + private void writeTagStripOffset(OutputStream result, int value) throws IOException + { + // TAG-ID 111 + result.write(1); + result.write(17); + + // TAG-TYPE LONG=4 + result.write(0); + result.write(4); + + + // TAG-LENGTH=1 + result.write(0); + result.write(0); + result.write(0); + result.write(1); + + + // TAG-VALUE = 8 //VOR TAG-DICTIONARY + int i1 = value/16777216;//=value/(256*256*256) + int i2 = (value-i1*16777216)/65536; + int i3 = (value-i1*16777216-i2*65536)/256; + int i4 = value % 256; + result.write(i1); + result.write(i2); + result.write(i3); + result.write(i4); + + } + + private void writeTagSamplesPerPixel(OutputStream result, int value) throws IOException + { + // TAG-ID 115 + result.write(1); + result.write(21); + + + // TAG-TYPE SHORT=3 + result.write(0); + result.write(3); + + + // TAG-LENGTH=1 + result.write(0); + result.write(0); + result.write(0); + result.write(1); + + + // TAG-VALUE + result.write(value / 256); + result.write(value % 256); + result.write(0);// SHORT=0 + result.write(0);// SHORT=0 + + } + + private void writeTagRowsPerStrip(OutputStream result, int value) throws IOException + { + // TAG-ID 116 + result.write(1); + result.write(22); + + + // TAG-TYPE SHORT=3 + result.write(0); + result.write(3); + + + // TAG-LENGTH=1 + result.write(0); + result.write(0); + result.write(0); + result.write(1); + + + // TAG-VALUE + result.write(value / 256); + result.write(value % 256); + result.write(0);// SHORT=0 + result.write(0);// SHORT=0 + + } + + private void writeTagStripByteCount(OutputStream result, int value) throws IOException + { + //@todo value auswerten + // TAG-ID 117 + result.write(1); + result.write(23); + + // TAG-TYPE LONG=4 + result.write(0); + result.write(4); + + + // TAG-LENGTH = 1 + result.write(0); + result.write(0); + result.write(0); + result.write(1); + + // TAG-VALUE + int i1 = value/16777216;//=value/(256*256*256) + int i2 = (value-i1*16777216)/65536; + int i3 = (value-i1*16777216-i2*65536)/256; + int i4 = value % 256; + result.write(i1); + result.write(i2); + result.write(i3); + result.write(i4); + + } + + private void writeTagXRes(OutputStream result, int value1, int value2) throws IOException + { + // TAG-ID 11A + result.write(1); + result.write(26); + + // TAG-TYPE RATIONAL=5 + result.write(0); + result.write(5); + + // TAG-LENGTH=1 + result.write(0); + result.write(0); + result.write(0); + result.write(1); + + + // TAG-VALUE=OFFSET TO RATIONAL + int valueOffset = offset + 6 + 12 * TAG_COUNT + tailer.size(); + int i1 = valueOffset/16777216;//=value/(256*256*256) + int i2 = (valueOffset-i1*16777216)/65536; + int i3 = (valueOffset-i1*16777216-i2*65536)/256; + int i4 = valueOffset % 256; + result.write(i1); + result.write(i2); + result.write(i3); + result.write(i4); + + i1 = value1 /16777216; + i2 = (value1-i1*16777216)/65536; + i3 = (value1-i1*16777216 - i2*65536)/256; + i4 = value1 % 256; + tailer.write(i1); + tailer.write(i2); + tailer.write(i3); + tailer.write(i4); + + i1 = value2 /16777216; + i2 = (value2-i1*16777216)/65536; + i3 = (value2-i1*16777216 - i2*65536)/256; + i4 = value2 % 256; + tailer.write(i1); + tailer.write(i2); + tailer.write(i3); + tailer.write(i4); + + tailingBytesCount += 8; + } + + private void writeTagYRes(OutputStream result, int value1, int value2) throws IOException + { + // TAG-ID 11B + result.write(1); + result.write(27); + + + // TAG-TYPE RATIONAL=5 + result.write(0); + result.write(5); + + // TAG-LENGTH=1 + result.write(0); + result.write(0); + result.write(0); + result.write(1); + + + // TAG-VALUE=OFFSET TO RATIONAL + int valueOffset = offset + 6 + 12 * TAG_COUNT + tailer.size(); + int i1 = valueOffset/16777216;//=value/(256*256*256) + int i2 = (valueOffset-i1*16777216)/65536; + int i3 = (valueOffset-i1*16777216-i2*65536)/256; + int i4 = valueOffset % 256; + result.write(i1); + result.write(i2); + result.write(i3); + result.write(i4); + + i1 = value1 /16777216; + i2 = (value1-i1*16777216)/65536; + i3 = (value1-i1*16777216 - i2*65536)/256; + i4 = value1 % 256; + tailer.write(i1); + tailer.write(i2); + tailer.write(i3); + tailer.write(i4); + + i1 = value2 /16777216; + i2 = (value2-i1*16777216)/65536; + i3 = (value2-i1*16777216 - i2*65536)/256; + i4 = value2 % 256; + tailer.write(i1); + tailer.write(i2); + tailer.write(i3); + tailer.write(i4); + + tailingBytesCount += 8; + } + + private void writeTagResolutionUnit(OutputStream result, int value) throws IOException + { + // TAG-ID 128 + result.write(1); + result.write(40); + + // TAG-TYPE SHORT=3 + result.write(0); + result.write(3); + + // TAG-LENGTH = 1 + result.write(0); + result.write(0); + result.write(0); + result.write(1); + + // TAG-VALUE + result.write(value/256); + result.write(value%256); + result.write(0);// SHORT=0 + result.write(0);// SHORT=0 + + } + + private void writeTagOrientation(OutputStream result, int value) throws IOException + { + // TAG-ID 112 + result.write(1); + result.write(18); + + // TAG-TYPE SHORT = 3 + result.write(0); + result.write(3); + + + // TAG-LENGTH=1 + result.write(0); + result.write(0); + result.write(0); + result.write(1); + + // TAG-VALUE + result.write(value / 256); + result.write(value % 256); + result.write(0);// SHORT=0 + result.write(0);// SHORT=0 + + } + + private void writeTagTailer(OutputStream result) throws IOException + { + // END OF TAG-DICTIONARY + result.write(0); + result.write(0); + result.write(0); + result.write(0); + + // TAILER WITH VALUES OF RATIONALFIELD's + result.write(tailer.toByteArray()); + } + + private void writeTagSoftware(OutputStream result, byte[] text) throws IOException + { + // TAG-ID 131 + result.write(1); + result.write(49); + + // TAG-TYPE ASCII=2 + result.write(0); + result.write(2); + + + // TAG-LENGTH=id.length+1 + result.write(0); + result.write(0); + result.write((text.length + 1) / 256); + result.write((text.length + 1) % 256); + + // TAG-VALUE + int valueOffset = offset + 6 + 12 * TAG_COUNT + tailer.size(); + int i1 = valueOffset/16777216;//=value/(256*256*256) + int i2 = (valueOffset-i1*16777216)/65536; + int i3 = (valueOffset-i1*16777216-i2*65536)/256; + int i4 = valueOffset % 256; + result.write(i1); + result.write(i2); + result.write(i3); + result.write(i4); + + + tailer.write(text); + tailer.write(0); + tailingBytesCount += text.length + 1; + } + + private void writeTagDateTime(OutputStream result, Date date) throws IOException + { + // TAG-ID 132 + result.write(1); + result.write(50); + + + // TAG-TYPE ASCII=2 + result.write(0); + result.write(2); + + + // TAG-LENGTH=20 + result.write(0); + result.write(0); + result.write(0); + result.write(20); + + + // TAG-VALUE + int valueOffset = offset + 6 + 12 * TAG_COUNT + tailer.size(); + int i1 = valueOffset/16777216;//=value/(256*256*256) + int i2 = (valueOffset-i1*16777216)/65536; + int i3 = (valueOffset-i1*16777216-i2*65536)/256; + int i4 = valueOffset % 256; + result.write(i1); + result.write(i2); + result.write(i3); + result.write(i4); + + SimpleDateFormat sdf = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss"); + String datetime = sdf.format(date); + tailer.write(datetime.getBytes()); + tailer.write(0); + + tailingBytesCount += 20; + } + + /** + * This will encode some data. + * + * @param rawData + * The raw data to encode. + * @param result + * The place to write to encoded results to. + * @param options + * The options to use to encode the data. + * + * @throws IOException + * If there is an error compressing the stream. + */ + public void encode(InputStream rawData, OutputStream result, COSDictionary options) throws IOException + { + log.warn("Warning: CCITTFaxDecode.encode is not implemented yet, skipping this stream."); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/filter/DCTFilter.java b/src/main/java/org/pdfbox/filter/DCTFilter.java new file mode 100644 index 0000000..8f371ea --- /dev/null +++ b/src/main/java/org/pdfbox/filter/DCTFilter.java @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.filter; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import org.apache.log4j.Logger; +import org.pdfbox.cos.COSDictionary; + +/** + * This is the used for the DCTDecode filter. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.7 $ + */ +public class DCTFilter implements Filter +{ + private static Logger log = Logger.getLogger( DCTFilter.class ); + + /** + * This will decode some compressed data. + * + * @param compressedData The compressed byte stream. + * @param result The place to write the uncompressed byte stream. + * @param options The options to use to encode the data. + * + * @throws IOException If there is an error decompressing the stream. + */ + public void decode( InputStream compressedData, OutputStream result, COSDictionary options ) throws IOException + { + log.warn( "Warning: DCTFilter.decode is not implemented yet, skipping this stream." ); + } + + /** + * This will encode some data. + * + * @param rawData The raw data to encode. + * @param result The place to write to encoded results to. + * @param options The options to use to encode the data. + * + * @throws IOException If there is an error compressing the stream. + */ + public void encode( InputStream rawData, OutputStream result, COSDictionary options ) throws IOException + { + log.warn( "Warning: DCTFilter.encode is not implemented yet, skipping this stream." ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/filter/Filter.java b/src/main/java/org/pdfbox/filter/Filter.java new file mode 100644 index 0000000..8de3f81 --- /dev/null +++ b/src/main/java/org/pdfbox/filter/Filter.java @@ -0,0 +1,68 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.filter; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import org.pdfbox.cos.COSDictionary; + +/** + * This is the interface that will be used to apply filters to a byte stream. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.5 $ + */ +public interface Filter +{ + /** + * This will decode some compressed data. + * + * @param compressedData The compressed byte stream. + * @param result The place to write the uncompressed byte stream. + * @param options The options to use to encode the data. + * + * @throws IOException If there is an error decompressing the stream. + */ + public void decode( InputStream compressedData, OutputStream result, COSDictionary options ) throws IOException; + + /** + * This will encode some data. + * + * @param rawData The raw data to encode. + * @param result The place to write to encoded results to. + * @param options The options to use to encode the data. + * + * @throws IOException If there is an error compressing the stream. + */ + public void encode( InputStream rawData, OutputStream result, COSDictionary options ) throws IOException; +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/filter/FilterManager.java b/src/main/java/org/pdfbox/filter/FilterManager.java new file mode 100644 index 0000000..87b1ad4 --- /dev/null +++ b/src/main/java/org/pdfbox/filter/FilterManager.java @@ -0,0 +1,135 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.filter; + +import java.io.IOException; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import org.pdfbox.cos.COSName; + +/** + * This will contain manage all the different types of filters that are available. + * + * @author Ben Litchfield + * @version $Revision: 1.12 $ + */ +public class FilterManager +{ + private Map filters = new HashMap(); + + /** + * Constructor. + */ + public FilterManager() + { + Filter flateFilter = new FlateFilter(); + Filter dctFilter = new DCTFilter(); + Filter ccittFaxFilter = new CCITTFaxDecodeFilter(); + Filter lzwFilter = new LZWFilter(); + Filter asciiHexFilter = new ASCIIHexFilter(); + Filter ascii85Filter = new ASCII85Filter(); + Filter runLengthFilter = new RunLengthDecodeFilter(); + + addFilter( COSName.FLATE_DECODE, flateFilter ); + addFilter( COSName.FLATE_DECODE_ABBREVIATION, flateFilter ); + addFilter( COSName.DCT_DECODE, dctFilter ); + addFilter( COSName.DCT_DECODE_ABBREVIATION, dctFilter ); + addFilter( COSName.CCITTFAX_DECODE, ccittFaxFilter ); + addFilter( COSName.CCITTFAX_DECODE_ABBREVIATION, ccittFaxFilter ); + addFilter( COSName.LZW_DECODE, lzwFilter ); + addFilter( COSName.LZW_DECODE_ABBREVIATION, lzwFilter ); + addFilter( COSName.ASCII_HEX_DECODE, asciiHexFilter ); + addFilter( COSName.ASCII_HEX_DECODE_ABBREVIATION, asciiHexFilter ); + addFilter( COSName.ASCII85_DECODE, ascii85Filter ); + addFilter( COSName.ASCII85_DECODE_ABBREVIATION, ascii85Filter ); + addFilter( COSName.RUN_LENGTH_DECODE, runLengthFilter ); + addFilter( COSName.RUN_LENGTH_DECODE_ABBREVIATION, runLengthFilter ); + + } + + /** + * This will get all of the filters that are available in the system. + * + * @return All available filters in the system. + */ + public Collection getFilters() + { + return filters.values(); + } + + /** + * This will add an available filter. + * + * @param filterName The name of the filter. + * @param filter The filter to use. + */ + public void addFilter( COSName filterName, Filter filter ) + { + filters.put( filterName, filter ); + } + + /** + * This will get a filter by name. + * + * @param filterName The name of the filter to retrieve. + * + * @return The filter that matches the name. + * + * @throws IOException If the filter could not be found. + */ + public Filter getFilter( COSName filterName ) throws IOException + { + Filter filter = (Filter)filters.get( filterName ); + if( filter == null ) + { + throw new IOException( "Unknown stream filter:" + filterName ); + } + + return filter; + } + + /** + * This will get a filter by name. + * + * @param filterName The name of the filter to retrieve. + * + * @return The filter that matches the name. + * + * @throws IOException If the filter could not be found. + */ + public Filter getFilter( String filterName ) throws IOException + { + return getFilter( COSName.getPDFName( filterName ) ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/filter/FlateFilter.java b/src/main/java/org/pdfbox/filter/FlateFilter.java new file mode 100644 index 0000000..c239686 --- /dev/null +++ b/src/main/java/org/pdfbox/filter/FlateFilter.java @@ -0,0 +1,303 @@ +/** + * Copyright (c) 2003-2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.filter; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.zip.DeflaterOutputStream; +import java.util.zip.InflaterInputStream; + +import org.pdfbox.cos.COSDictionary; + +/** + * This is the used for the FlateDecode filter. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @author Marcel Kammer + * @version $Revision: 1.9 $ + */ +public class FlateFilter implements Filter +{ + private static final int BUFFER_SIZE = 2048; + + /** + * This will decode some compressed data. + * + * @param compressedData + * The compressed byte stream. + * @param result + * The place to write the uncompressed byte stream. + * @param options + * The options to use to encode the data. + * + * @throws IOException + * If there is an error decompressing the stream. + */ + + public void decode(InputStream compressedData, OutputStream result, COSDictionary options) throws IOException + { + COSDictionary dict = (COSDictionary) options.getDictionaryObject("DecodeParms"); + int predictor = -1; + int colors = -1; + int bitsPerPixel = -1; + int columns = -1; + InflaterInputStream decompressor = null; + ByteArrayInputStream bais = null; + ByteArrayOutputStream baos = null; + if (dict!=null) + { + predictor = dict.getInt("Predictor"); + colors = dict.getInt("Colors"); + bitsPerPixel = options.getInt("BitsPerComponent"); + columns = dict.getInt("Columns"); + } + + try + { + // Decompress data to temporary ByteArrayOutputStream + decompressor = new InflaterInputStream(compressedData); + byte[] buffer = new byte[BUFFER_SIZE]; + int amountRead; + + // Decode data using given predictor + if (predictor==-1 || predictor == 1 && predictor == 10) + { + // decoding not needed + while ((amountRead = decompressor.read(buffer, 0, BUFFER_SIZE)) != -1) + { + result.write(buffer, 0, amountRead); + } + } + else + { + if (colors==-1 || bitsPerPixel==-1 || columns==-1) + { + throw new IOException("Could not read all parameters to decode image"); + } + + baos = new ByteArrayOutputStream(); + while ((amountRead = decompressor.read(buffer, 0, BUFFER_SIZE)) != -1) + { + baos.write(buffer, 0, amountRead); + } + baos.flush(); + + // Copy data to ByteArrayInputStream for reading + bais = new ByteArrayInputStream(baos.toByteArray()); + baos.close(); + baos = null; + + byte[] decodedData = decodePredictor(predictor, colors, bitsPerPixel, columns, bais); + bais.close(); + bais = new ByteArrayInputStream(decodedData); + + // write decoded data to result + while ((amountRead = bais.read(buffer)) != -1) + { + result.write(buffer, 0, amountRead); + } + bais.close(); + bais = null; + } + + + result.flush(); + } + finally + { + if (decompressor != null) + { + decompressor.close(); + } + if (bais != null) + { + bais.close(); + } + if (baos != null) + { + baos.close(); + } + } + } + + private byte[] decodePredictor(int predictor, int colors, int bitsPerComponent, int columns, InputStream data) + throws IOException + { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte[] buffer = new byte[2048]; + + if (predictor == 1 || predictor == 10) + { + // No prediction or PNG NONE + int i = 0; + while ((i = data.read(buffer)) != -1) + { + baos.write(buffer, 0, i); + } + } + else + { + // calculate sizes + int bpp = (colors * bitsPerComponent + 7) / 8; + int rowlength = (columns * colors * bitsPerComponent + 7) / 8 + bpp; + byte[] actline = new byte[rowlength]; + byte[] lastline = new byte[rowlength];// Initialize lastline with + // Zeros according to + // PNG-specification + boolean done = false; + int linepredictor = predictor; + + while (!done) + { + if (predictor == 15) + { + linepredictor = data.read();// read per line predictor + if (linepredictor == -1) + { + done = true;// reached EOF + break; + } + else + { + linepredictor += 10; // add 10 to tread value 1 as 11 + } + // (instead of PRED NONE) and 2 + // as 12 (instead of PRED TIFF) + } + + // read line + int i = 0; + int offset = bpp; + while (offset < rowlength && ((i = data.read(actline, offset, rowlength - offset)) != -1)) + { + offset += i; + } + + // Do prediction as specified in PNG-Specification 1.2 + switch (linepredictor) + { + case 2:// PRED TIFF SUB + /** + * @todo decode tiff + */ + throw new IOException("TIFF-Predictor not supported"); + case 11:// PRED SUB + for (int p = bpp; p < rowlength; p++) + { + int sub = actline[p] & 0xff; + int left = actline[p - bpp] & 0xff; + actline[p] = (byte) (sub + left); + } + break; + case 12:// PRED UP + for (int p = bpp; p < rowlength; p++) + { + int up = actline[p] & 0xff; + int prior = lastline[p] & 0xff; + actline[p] = (byte) (up + prior); + } + break; + case 13:// PRED AVG + for (int p = bpp; p < rowlength; p++) + { + int avg = actline[p] & 0xff; + int left = actline[p - bpp] & 0xff; + int up = lastline[p] & 0xff; + actline[p] = (byte) (avg + ((left + up) / 2)); + } + break; + case 14:// PRED PAETH + for (int p = bpp; p < rowlength; p++) + { + int paeth = actline[p] & 0xff; + int a = actline[p - bpp] & 0xff;// left + int b = lastline[p] & 0xff;// upper + int c = lastline[p - bpp] & 0xff;// upperleft + int value = a + b - c; + int absa = Math.abs(value - a); + int absb = Math.abs(value - b); + int absc = Math.abs(value - c); + + if (absa <= absb && absa <= absc) + { + actline[p] = (byte) (paeth + absa); + } + else if (absb <= absc) + { + actline[p] += (byte) (paeth + absb); + } + else + { + actline[p] += (byte) (paeth + absc); + } + } + break; + default: + break; + } + + lastline = actline; + baos.write(actline, bpp, actline.length - bpp); + } + } + + return baos.toByteArray(); + } + + /** + * This will encode some data. + * + * @param rawData + * The raw data to encode. + * @param result + * The place to write to encoded results to. + * @param options + * The options to use to encode the data. + * + * @throws IOException + * If there is an error compressing the stream. + */ + public void encode(InputStream rawData, OutputStream result, COSDictionary options) throws IOException + { + DeflaterOutputStream out = new DeflaterOutputStream(result); + byte[] buffer = new byte[BUFFER_SIZE]; + int amountRead = 0; + while ((amountRead = rawData.read(buffer, 0, BUFFER_SIZE)) != -1) + { + out.write(buffer, 0, amountRead); + } + out.close(); + result.flush(); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/filter/LZWDictionary.java b/src/main/java/org/pdfbox/filter/LZWDictionary.java new file mode 100644 index 0000000..075dab8 --- /dev/null +++ b/src/main/java/org/pdfbox/filter/LZWDictionary.java @@ -0,0 +1,215 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.filter; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import java.util.HashMap; +import java.util.Map; + +/** + * This is the used for the LZWDecode filter. This represents the dictionary mappings + * between codes and their values. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.3 $ + */ +class LZWDictionary +{ + private Map codeToData = new HashMap(); + private LZWNode root = new LZWNode(); + + private ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + private long nextCode = 258; + private int codeSize = 9; + + /** + * constructor. + */ + public LZWDictionary() + { + for( long i=0; i<256; i++ ) + { + LZWNode node = new LZWNode(); + node.setCode( i ); + root.setNode( (byte)i, node ); + codeToData.put( new Long( i ), new byte[]{ (byte)i } ); + } + } + + /** + * This will get the value for the code. It will return null if the code is not + * defined. + * + * @param code The key to the data. + * + * @return The data that is mapped to the code. + */ + public byte[] getData( long code ) + { + return (byte[])codeToData.get( new Long( code ) ); + } + + /** + * This will take a visit from a byte[]. This will create new code entries as + * necessary. + * + * @param data The byte to get a visit from. + * + * @throws IOException If there is an error visiting this data. + */ + public void visit( byte[] data ) throws IOException + { + for( int i=0; i= 2048 ) + { + codeSize = 12; + } + else if( nextCode >= 1024 ) + { + codeSize = 11; + } + else if( nextCode >= 512 ) + { + codeSize = 10; + } + else + { + codeSize = 9; + } + } + + /** + * This will crear the internal buffer that the dictionary uses. + */ + public void clear() + { + buffer.reset(); + } + + /** + * This will folow the path to the data node. + * + * @param data The path to the node. + * + * @return The node that resides at that path. + */ + public LZWNode getNode( byte[] data ) + { + return root.getNode( data ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/filter/LZWFilter.java b/src/main/java/org/pdfbox/filter/LZWFilter.java new file mode 100644 index 0000000..e8ba003 --- /dev/null +++ b/src/main/java/org/pdfbox/filter/LZWFilter.java @@ -0,0 +1,235 @@ +/** + * Copyright (c) 2003-2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.filter; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PushbackInputStream; +import java.io.StreamCorruptedException; + +import org.pdfbox.cos.COSDictionary; + +import org.pdfbox.io.NBitInputStream; +import org.pdfbox.io.NBitOutputStream; + +/** + * This is the used for the LZWDecode filter. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.13 $ + */ +public class LZWFilter implements Filter +{ + + /** + * The LZW clear table code. + */ + public static final long CLEAR_TABLE = 256; + /** + * The LZW end of data code. + */ + public static final long EOD = 257; + + /** + * This will decode some compressed data. + * + * @param compressedData The compressed byte stream. + * @param result The place to write the uncompressed byte stream. + * @param options The options to use to encode the data. + * + * @throws IOException If there is an error decompressing the stream. + */ + public void decode( InputStream compressedData, OutputStream result, COSDictionary options ) throws IOException + { + //log.debug("decode( )"); + NBitInputStream in = null; + in = new NBitInputStream( compressedData ); + in.setBitsInChunk( 9 ); + LZWDictionary dic = new LZWDictionary(); + byte firstByte = 0; + long nextCommand = 0; + while( (nextCommand = in.read() ) != EOD ) + { + // log.debug( "decode - nextCommand=" + nextCommand + ", bitsInChunk: " + in.getBitsInChunk()); + + if( nextCommand == CLEAR_TABLE ) + { + in.setBitsInChunk( 9 ); + dic = new LZWDictionary(); + } + else + { + byte[] data = dic.getData( nextCommand ); + if( data == null ) + { + dic.visit( firstByte ); + data = dic.getData( nextCommand ); + dic.clear(); + } + if( data == null ) + { + throw new StreamCorruptedException( "Error: data is null" ); + } + dic.visit(data); + + //log.debug( "decode - dic.getNextCode(): " + dic.getNextCode()); + + if( dic.getNextCode() >= 2047 ) + { + in.setBitsInChunk( 12 ); + } + else if( dic.getNextCode() >= 1023 ) + { + in.setBitsInChunk( 11 ); + } + else if( dic.getNextCode() >= 511 ) + { + in.setBitsInChunk( 10 ); + } + else + { + in.setBitsInChunk( 9 ); + } + /** + if( in.getBitsInChunk() != dic.getCodeSize() ) + { + in.unread( nextCommand ); + in.setBitsInChunk( dic.getCodeSize() ); + System.out.print( "Switching " + nextCommand + " to " ); + nextCommand = in.read(); + System.out.println( "" + nextCommand ); + data = dic.getData( nextCommand ); + }**/ + firstByte = data[0]; + result.write( data ); + } + } + result.flush(); + } + + + /** + * This will encode some data. + * + * @param rawData The raw data to encode. + * @param result The place to write to encoded results to. + * @param options The options to use to encode the data. + * + * @throws IOException If there is an error compressing the stream. + */ + public void encode( InputStream rawData, OutputStream result, COSDictionary options ) throws IOException + { + //log.debug("encode( )"); + PushbackInputStream input = new PushbackInputStream( rawData, 4096 ); + LZWDictionary dic = new LZWDictionary(); + NBitOutputStream out = new NBitOutputStream( result ); + out.setBitsInChunk( 9 ); //initially nine + out.write( CLEAR_TABLE ); + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + int byteRead = 0; + for( int i=0; (byteRead = input.read()) != -1; i++ ) + { + //log.debug( "byteRead = '" + (char)byteRead + "' (0x" + Integer.toHexString(byteRead) + "), i=" + i); + buffer.write( byteRead ); + dic.visit( (byte)byteRead ); + out.setBitsInChunk( dic.getCodeSize() ); + + //log.debug( "Getting node '" + new String( buffer.toByteArray() ) + "', buffer.size = " + buffer.size() ); + LZWNode node = dic.getNode( buffer.toByteArray() ); + int nextByte = input.read(); + if( nextByte != -1 ) + { + //log.debug( "nextByte = '" + (char)nextByte + "' (0x" + Integer.toHexString(nextByte) + ")"); + LZWNode next = node.getNode( (byte)nextByte ); + if( next == null ) + { + //log.debug("encode - No next node, writing node and resetting buffer (" + + // " node.getCode: " + node.getCode() + ")" + + // " bitsInChunk: " + out.getBitsInChunk() + + // ")"); + out.write( node.getCode() ); + buffer.reset(); + } + + input.unread( nextByte ); + } + else + { + //log.debug("encode - EOF on lookahead: writing node, resetting buffer, and terminating read loop (" + + // " node.getCode: " + node.getCode() + ")" + + // " bitsInChunk: " + out.getBitsInChunk() + + // ")"); + out.write( node.getCode() ); + buffer.reset(); + break; + } + + if( dic.getNextCode() == 4096 ) + { + //log.debug("encode - Clearing dictionary and unreading pending buffer data (" + + // " bitsInChunk: " + out.getBitsInChunk() + + // ")"); + out.write( CLEAR_TABLE ); + dic = new LZWDictionary(); + input.unread( buffer.toByteArray() ); + buffer.reset(); + } + } + + // Fix the code size based on the fact that we are writing the EOD + // + if( dic.getNextCode() >= 2047 ) + { + out.setBitsInChunk( 12 ); + } + else if( dic.getNextCode() >= 1023 ) + { + out.setBitsInChunk( 11 ); + } + else if( dic.getNextCode() >= 511 ) + { + out.setBitsInChunk( 10 ); + } + else + { + out.setBitsInChunk( 9 ); + } + + //log.debug("encode - Writing EOD (" + + // " bitsInChunk: " + out.getBitsInChunk() + + // ")"); + out.write( EOD ); + out.close(); + result.flush(); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/filter/LZWNode.java b/src/main/java/org/pdfbox/filter/LZWNode.java new file mode 100644 index 0000000..563ea5d --- /dev/null +++ b/src/main/java/org/pdfbox/filter/LZWNode.java @@ -0,0 +1,115 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.filter; + +import java.util.HashMap; +import java.util.Map; + +/** + * This is the used for the LZWDecode filter. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.3 $ + */ +class LZWNode +{ + private long code; + private Map subNodes = new HashMap(); + + /** + * This will get the number of children. + * + * @return The number of children. + */ + public int childCount() + { + return subNodes.size(); + } + + /** + * This will set the node for a particular byte. + * + * @param b The byte for that node. + * @param node The node to add. + */ + public void setNode( byte b, LZWNode node ) + { + subNodes.put( new Byte( b ), node ); + } + + /** + * This will get the node that is a direct sub node of this node. + * + * @param data The byte code to the node. + * + * @return The node at that value if it exists. + */ + public LZWNode getNode( byte data ) + { + return (LZWNode)subNodes.get( new Byte( data ) ); + } + + + /** + * This will traverse the tree until it gets to the sub node. + * This will return null if the node does not exist. + * + * @param data The path to the node. + * + * @return The node that resides at the data path. + */ + public LZWNode getNode( byte[] data ) + { + LZWNode current = this; + for( int i=0; i + * The RunLengthDecode filter decodes data that has been encoded in a simple + * byte-oriented format based on run length. The encoded data is a sequence of + * runs, where each run consists of a length byte followed by 1 to 128 bytes of data. If + * the length byte is in the range 0 to 127, the following length + 1 (1 to 128) bytes + * are copied literally during decompression. If length is in the range 129 to 255, the + * following single byte is to be copied 257 ? length (2 to 128) times during decompression. + * A length value of 128 denotes EOD. + * + * The compression achieved by run-length encoding depends on the input data. In + * the best case (all zeros), a compression of approximately 64:1 is achieved for long + * files. The worst case (the hexadecimal sequence 00 alternating with FF) results in + * an expansion of 127:128. + * + * + * @author Ben Litchfield + * @version $Revision: 1.3 $ + */ +public class RunLengthDecodeFilter implements Filter +{ + private static Logger log = Logger.getLogger( RunLengthDecodeFilter.class ); + + private static final int RUN_LENGTH_EOD = 128; + + /** + * Constructor. + */ + public RunLengthDecodeFilter() + { + //default constructor + } + + /** + * This will decode some compressed data. + * + * @param compressedData The compressed byte stream. + * @param result The place to write the uncompressed byte stream. + * @param options The options to use to encode the data. + * + * @throws IOException If there is an error decompressing the stream. + */ + public void decode( InputStream compressedData, OutputStream result, COSDictionary options ) throws IOException + { + int dupAmount = -1; + byte[] buffer = new byte[128]; + while( (dupAmount = compressedData.read()) != -1 && dupAmount != RUN_LENGTH_EOD ) + { + if( dupAmount <= 127 ) + { + int amountToCopy = dupAmount+1; + int compressedRead = 0; + while( amountToCopy > 0 ) + { + compressedRead = compressedData.read( buffer, 0, amountToCopy ); + result.write( buffer, 0, compressedRead ); + amountToCopy -= compressedRead; + } + } + else + { + int dupByte = compressedData.read(); + for( int i=0; i<257-dupAmount; i++ ) + { + result.write( dupByte ); + } + } + } + } + + /** + * This will encode some data. + * + * @param rawData The raw data to encode. + * @param result The place to write to encoded results to. + * @param options The options to use to encode the data. + * + * @throws IOException If there is an error compressing the stream. + */ + public void encode( InputStream rawData, OutputStream result, COSDictionary options ) throws IOException + { + log.warn( "Warning: RunLengthDecodeFilter.encode is not implemented yet, skipping this stream." ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/filter/package.html b/src/main/java/org/pdfbox/filter/package.html new file mode 100644 index 0000000..36dbb7d --- /dev/null +++ b/src/main/java/org/pdfbox/filter/package.html @@ -0,0 +1,9 @@ + + + + + + +This package will hold the PDFBox implementations of the filters that are used in PDF documents. + + diff --git a/src/main/java/org/pdfbox/io/ASCII85InputStream.java b/src/main/java/org/pdfbox/io/ASCII85InputStream.java new file mode 100644 index 0000000..863d64d --- /dev/null +++ b/src/main/java/org/pdfbox/io/ASCII85InputStream.java @@ -0,0 +1,269 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.io; + +import java.io.FilterInputStream; +import java.io.InputStream; +import java.io.IOException; + +/** + * This class represents an ASCII85 stream. + * + * @author Ben Litchfield + * @version $Revision: 1.5 $ + */ +public class ASCII85InputStream extends FilterInputStream +{ + private int index; + private int n; + private boolean eof; + + private byte[] ascii; + private byte[] b; + + /** + * Constructor. + * + * @param is The input stream to actually read from. + */ + public ASCII85InputStream( InputStream is ) + { + super(is); + index = 0; + n = 0; + eof = false; + ascii = new byte[5]; + b = new byte[4]; + } + + /** + * This will read the next byte from the stream. + * + * @return The next byte read from the stream. + * + * @throws IOException If there is an error reading from the wrapped stream. + */ + public final int read() throws IOException + { + if( index >= n ) + { + if(eof) + { + return -1; + } + index = 0; + int k; + byte z; + do + { + int zz=(byte)in.read(); + if(zz==-1) + { + eof=true; + return -1; + } + z = (byte)zz; + } while( z=='\n' || z=='\r' || z==' '); + + if (z == '~' || z=='x') + { + eof=true; + ascii=b=null; + n = 0; + return -1; + } + else if (z == 'z') + { + b[0]=b[1]=b[2]=b[3]=0; + n = 4; + } + else + { + ascii[0]=z; // may be EOF here.... + for (k=1;k<5;++k) + { + do + { + int zz=(byte)in.read(); + if(zz==-1) + { + eof=true; + return -1; + } + z=(byte)zz; + } while ( z=='\n' || z=='\r' || z==' ' ); + ascii[k]=z; + if (z == '~' || z=='x') + { + break; + } + } + n = k - 1; + if ( n==0 ) + { + eof = true; + ascii = null; + b = null; + return -1; + } + if ( k < 5 ) + { + for (++k; k < 5; ++k ) + { + ascii[k] = 0x21; + } + eof=true; + } + // decode stream + long t=0; + for ( k=0; k<5; ++k) + { + z=(byte)(ascii[k] - 0x21); + if (z < 0 || z > 93) + { + n = 0; + eof = true; + ascii = null; + b = null; + throw new IOException("Invalid data in Ascii85 stream"); + } + t = (t * 85L) + z; + } + for ( k = 3; k>=0; --k) + { + b[k] = (byte)(t & 0xFFL); + t>>>=8; + } + } + } + return b[index++] & 0xFF; + } + + /** + * This will read a chunk of data. + * + * @param data The buffer to write data to. + * @param offset The offset into the data stream. + * @param len The number of byte to attempt to read. + * + * @return The number of bytes actually read. + * + * @throws IOException If there is an error reading data from the underlying stream. + */ + public final int read(byte[] data, int offset, int len) throws IOException + { + if(eof && index>=n) + { + return -1; + } + for(int i=0;i126 || term=='z') + { + throw new IllegalArgumentException("Terminator must be 118-126 excluding z"); + } + terminator=term; + } + + /** + * This will get the terminating character. + * + * @return The terminating character. + */ + public char getTerminator() + { + return terminator; + } + + /** + * This will set the line length that will be used. + * + * @param l The length of the line to use. + */ + public void setLineLength(int l) + { + if( lineBreak > l ) + { + lineBreak = l; + } + maxline=l; + } + + /** + * This will get the length of the line. + * + * @return The line length attribute. + */ + public int getLineLength() + { + return maxline; + } + + /** + * This will transform the next four ascii bytes. + */ + private final void transformASCII85() + { + long word; + word=( (((indata[0] << 8) | (indata[1] &0xFF)) << 16) | + ( (indata[2] & 0xFF) << 8) | (indata[3] & 0xFF) + ) & 0xFFFFFFFFL; + // System.out.println("word=0x"+Long.toString(word,16)+" "+word); + + if (word == 0 ) + { + outdata[0]=(byte)'z'; + outdata[1]=0; + return; + } + long x; + x=word/(85L*85L*85L*85L); + // System.out.println("x0="+x); + outdata[0]=(byte)(x+'!'); + word-=x*85L*85L*85L*85L; + + x=word/(85L*85L*85L); + // System.out.println("x1="+x); + outdata[1]=(byte)(x+'!'); + word-=x*85L*85L*85L; + + x=word/(85L*85L); + // System.out.println("x2="+x); + outdata[2]=(byte)(x+'!'); + word-=x*85L*85L; + + x=word/85L; + // System.out.println("x3="+x); + outdata[3]=(byte)(x+'!'); + + // word-=x*85L; + + // System.out.println("x4="+(word % 85L)); + outdata[4]=(byte)((word%85L)+'!'); + } + + /** + * This will write a single byte. + * + * @param b The byte to write. + * + * @throws IOException If there is an error writing to the stream. + */ + public final void write(int b) throws IOException + { + flushed=false; + indata[count++]=(byte)b; + if(count < 4 ) + { + return; + } + transformASCII85(); + for(int i=0;i<5;i++) + { + if(outdata[i]==0) + { + break; + } + out.write(outdata[i]); + if(--lineBreak==0) + { + out.write('\n'); + lineBreak=maxline; + } + } + count = 0; + } + + /** + * This will write a chunk of data to the stream. + * + * @param b The byte buffer to read from. + * @param off The offset into the buffer. + * @param sz The number of bytes to read from the buffer. + * + * @throws IOException If there is an error writing to the underlying stream. + */ + public final void write(byte[] b,int off, int sz) throws IOException + { + for(int i=0;i 0 ) + { + for( int i=count; i<4; i++ ) + { + indata[i]=0; + } + transformASCII85(); + if(outdata[0]=='z') + { + for(int i=0;i<5;i++) // expand 'z', + { + outdata[i]=(byte)'!'; + } + } + for(int i=0;i= datalen; + } + + /** + * Save the state of this stream. + * @param readlimit Has no effect. + * @see InputStream#mark(int) + */ + public void mark(int readlimit) + { + if (false) + { + ++readlimit; // avoid unused param warning + } + save = datapos; + } + + /** + * Check if mark is supported. + * @return Always true. + * @see InputStream#markSupported() + */ + public boolean markSupported() + { + return true; + } + + /** + * Restore the state of this stream to the last saveState call. + * @see InputStream#reset() + */ + public void reset() + { + datapos = save; + } + + /** Available bytes. + * @see InputStream#available() + * @return Available bytes. + */ + public int available() + { + int av = datalen - datapos; + return av > 0 ? av : 0; + } + + /** Totally available bytes in the underlying array. + * @return Available bytes. + */ + public int size() + { + return datalen; + } + + /** + * Pushes back a byte. + * After this method returns, the next byte to be read will have the value (byte)by. + * @param by the int value whose low-order byte is to be pushed back. + * @throws IOException - If there is not enough room in the buffer for the byte. + * @see java.io.PushbackInputStream#unread(int) + */ + public void unread(int by) throws IOException + { + if (datapos == 0) + { + throw new IOException("ByteArrayParserInputStream.unread(int): " + + "cannot unread 1 byte at buffer position " + datapos); + } + --datapos; + data[datapos] = (byte)by; + } + + /** + * Pushes back a portion of an array of bytes by copying it to the + * front of the pushback buffer. After this method returns, the next byte + * to be read will have the value b[off], the byte after that will have + * the value b[off+1], and so forth. + * @param buffer the byte array to push back. + * @param off the start offset of the data. + * @param len the number of bytes to push back. + * @throws IOException If there is not enough room in the pushback buffer + * for the specified number of bytes. + * @see java.io.PushbackInputStream#unread(byte[], int, int) + */ + public void unread(byte[] buffer, int off, int len) throws IOException + { + if (len <= 0 || off >= buffer.length) + { + return; + } + if (off < 0) + { + off = 0; + } + if (len > buffer.length) + { + len = buffer.length; + } + localUnread(buffer, off, len); + } + + /** + * Pushes back a portion of an array of bytes by copying it to the + * front of the pushback buffer. After this method returns, the next byte + * to be read will have the value buffer[0], the byte after that will have + * the value buffer[1], and so forth. + * @param buffer the byte array to push back. + * @throws IOException If there is not enough room in the pushback buffer + * for the specified number of bytes. + * @see java.io.PushbackInputStream#unread(byte[]) + */ + public void unread(byte[] buffer) throws IOException + { + localUnread(buffer, 0, buffer.length); + } + + /** + * Pushes back a portion of an array of bytes by copying it to the + * front of the pushback buffer. After this method returns, the next byte + * to be read will have the value buffer[off], the byte after that will have + * the value buffer[off+1], and so forth. + * Internal method that assumes off and len to be valid. + * @param buffer the byte array to push back. + * @param off the start offset of the data. + * @param len the number of bytes to push back. + * @throws IOException If there is not enough room in the pushback buffer + * for the specified number of bytes. + * @see java.io.PushbackInputStream#unread(byte[], int, int) + */ + private void localUnread(byte[] buffer, int off, int len) throws IOException + { + if (datapos < len) + { + throw new IOException("ByteArrayParserInputStream.unread(int): " + + "cannot unread " + len + + " bytes at buffer position " + datapos); + } + datapos -= len; + System.arraycopy(buffer, off, data, datapos, len); + } + + /** + * Read a byte. + * @see InputStream#read() + * @return Byte read or -1 if no more bytes are available. + */ + public int read() + { + try + { + // convert negative values to 128..255 + return (data[datapos++] + 0x100) & 0xff; + } + catch (ArrayIndexOutOfBoundsException ex) + { + // could check this before, but this is a rare case + // and this method is called sufficiently often to justify this + // optimization + datapos = datalen; + return -1; + } + } + + /** + * Read a number of bytes. + * @see InputStream#read(byte[]) + * @param buffer the buffer into which the data is read. + * @return the total number of bytes read into the buffer, or -1 if there + * is no more data because the end of the stream has been reached. + */ + public int read(byte[] buffer) + { + return localRead(buffer, 0, buffer.length); + } + + /** + * Read a number of bytes. + * @see InputStream#read(byte[], int, int) + * @param buffer the buffer into which the data is read. + * @param off the start offset in array buffer at which the data is written. + * @param len the maximum number of bytes to read. + * @return the total number of bytes read into the buffer, or -1 if there + * is no more data because the end of the stream has been reached. + */ + public int read(byte[] buffer, int off, int len) + { + if (len <= 0 || off >= buffer.length) + { + return 0; + } + if (off < 0) + { + off = 0; + } + if (len > buffer.length) + { + len = buffer.length; + } + return localRead(buffer, off, len); + } + + + /** + * Read a number of bytes. Internal method that assumes off and len to be + * valid. + * @see InputStream#read(byte[], int, int) + * @param buffer the buffer into which the data is read. + * @param off the start offset in array buffer at which the data is written. + * @param len the maximum number of bytes to read. + * @return the total number of bytes read into the buffer, or -1 if there + * is no more data because the end of the stream has been reached. + */ + public int localRead(byte[] buffer, int off, int len) + { + if (len == 0) + { + return 0; // must return 0 even if at end! + } + else if (datapos >= datalen) + { + return -1; + } + else + { + int newpos = datapos + len; + if (newpos > datalen) + { + newpos = datalen; + len = newpos - datapos; + } + System.arraycopy(data, datapos, buffer, off, len); + datapos = newpos; + return len; + } + } + + /** + * Skips over and discards n bytes of data from this input stream. + * The skip method may, for a variety of reasons, end up skipping over some + * smaller number of bytes, possibly 0. This may result from any of a number + * of conditions; reaching end of file before n bytes have been skipped is + * only one possibility. The actual number of bytes skipped is returned. + * If n is negative, no bytes are skipped. + * @param num the number of bytes to be skipped. + * @return the actual number of bytes skipped. + * @see InputStream#skip(long) + */ + public long skip(long num) + { + if (num <= 0) + { + return 0; + } + else + { + long newpos = datapos + num; + if (newpos >= datalen) + { + num = datalen - datapos; + datapos = datalen; + } + else + { + datapos = (int)newpos; + } + return num; + } + } + + /** Position the stream at a given index. Positioning the stream + * at position size() will cause the next call to read() to return -1. + * + * @param newpos Position in the underlying array. A negative value will be + * interpreted as 0, a value greater than size() as size(). + * @return old position. + */ + public int seek(int newpos) + { + if (newpos < 0) + { + newpos = 0; + } + else if (newpos > datalen) + { + newpos = datalen; + } + int oldpos = pos; + pos = newpos; + return oldpos; + } + +} diff --git a/src/main/java/org/pdfbox/io/FastByteArrayOutputStream.java b/src/main/java/org/pdfbox/io/FastByteArrayOutputStream.java new file mode 100644 index 0000000..1e5fdc6 --- /dev/null +++ b/src/main/java/org/pdfbox/io/FastByteArrayOutputStream.java @@ -0,0 +1,62 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.io; + +import java.io.ByteArrayOutputStream; + +/** + * An byte array output stream that allows direct access to the byte array. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.3 $ + */ +public class FastByteArrayOutputStream extends ByteArrayOutputStream +{ + /** + * Constructor. + * + * @param size An initial size of the stream. + */ + public FastByteArrayOutputStream( int size ) + { + super( size ); + } + + /** + * This will get the underlying byte array. + * + * @return The underlying byte array at this moment in time. + */ + public byte[] getByteArray() + { + return buf; + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/io/NBitInputStream.java b/src/main/java/org/pdfbox/io/NBitInputStream.java new file mode 100644 index 0000000..d8254b2 --- /dev/null +++ b/src/main/java/org/pdfbox/io/NBitInputStream.java @@ -0,0 +1,124 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.io; + +import java.io.InputStream; +import java.io.IOException; + +/** + * This is an n-bit input stream. This means that you can read chunks of data + * as any number of bits, not just 8 bits like the regular input stream. Just set the + * number of bits that you would like to read on each call. The default is 8. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.3 $ + */ +public class NBitInputStream +{ + private int bitsInChunk; + private InputStream in; + + private int currentByte; + private int bitsLeftInCurrentByte; + + /** + * Constructor. + * + * @param is The input stream to read from. + */ + public NBitInputStream( InputStream is ) + { + in = is; + bitsLeftInCurrentByte = 0; + bitsInChunk = 8; + } + + /** + * This will unread some data. + * + * @param data The data to put back into the stream. + */ + public void unread( long data ) + { + data <<= bitsLeftInCurrentByte; + currentByte |= data; + bitsLeftInCurrentByte += bitsInChunk; + } + + /** + * This will read the next n bits from the stream and return the unsigned + * value of those bits. + * + * @return The next n bits from the stream. + * + * @throws IOException If there is an error reading from the underlying stream. + */ + public long read() throws IOException + { + long retval = 0; + for( int i=0; i> (bitsLeftInCurrentByte-1))&0x1); + bitsLeftInCurrentByte--; + } + } + return retval; + } + + /** Getter for property bitsToRead. + * @return Value of property bitsToRead. + */ + public int getBitsInChunk() + { + return bitsInChunk; + } + + /** Setter for property bitsToRead. + * @param bitsInChunkValue New value of property bitsToRead. + */ + public void setBitsInChunk(int bitsInChunkValue) + { + bitsInChunk = bitsInChunkValue; + } + +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/io/NBitOutputStream.java b/src/main/java/org/pdfbox/io/NBitOutputStream.java new file mode 100644 index 0000000..f944b8a --- /dev/null +++ b/src/main/java/org/pdfbox/io/NBitOutputStream.java @@ -0,0 +1,116 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.io; + +import java.io.OutputStream; +import java.io.IOException; + +/** + * This is an n-bit output stream. This means that you write data in n-bit chunks. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.3 $ + */ +public class NBitOutputStream +{ + private int bitsInChunk; + private OutputStream out; + + private int currentByte; + private int positionInCurrentByte; + + /** + * Constructor. + * + * @param os The output stream to write to. + */ + public NBitOutputStream( OutputStream os ) + { + out = os; + currentByte = 0; + positionInCurrentByte = 7; + } + + /** + * This will write the next n-bits to the stream. + * + * @param chunk The next chunk of data to write. + * + * @throws IOException If there is an error writing the chunk. + */ + public void write( long chunk ) throws IOException + { + long bitToWrite; + for( int i=(bitsInChunk-1); i>=0; i-- ) + { + bitToWrite = (chunk >> i) & 0x1; + bitToWrite <<= positionInCurrentByte; + currentByte |= bitToWrite; + positionInCurrentByte--; + if( positionInCurrentByte < 0 ) + { + out.write( currentByte ); + currentByte = 0; + positionInCurrentByte = 7; + } + } + } + + /** + * This will close the stream. + * + * @throws IOException if there is an error closing the stream. + */ + public void close() throws IOException + { + if( positionInCurrentByte < 7 ) + { + out.write( currentByte ); + } + } + + /** Getter for property bitsToRead. + * @return Value of property bitsToRead. + */ + public int getBitsInChunk() + { + return bitsInChunk; + } + + /** Setter for property bitsToRead. + * @param bitsInChunkValue New value of property bitsToRead. + */ + public void setBitsInChunk(int bitsInChunkValue) + { + bitsInChunk = bitsInChunkValue; + } + +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/io/PushBackInputStream.java b/src/main/java/org/pdfbox/io/PushBackInputStream.java new file mode 100644 index 0000000..d519900 --- /dev/null +++ b/src/main/java/org/pdfbox/io/PushBackInputStream.java @@ -0,0 +1,92 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.io; + +import java.io.InputStream; +import java.io.IOException; + +/** + * A simple subclass that adds a few convience methods. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.4 $ + */ +public class PushBackInputStream extends java.io.PushbackInputStream +{ + + /** + * Constructor. + * + * @param input The input stream. + * @param size The size of the push back buffer. + * + * @throws IOException If there is an error with the stream. + */ + public PushBackInputStream( InputStream input, int size ) throws IOException + { + super( input, size ); + if( input == null ) + { + throw new IOException( "Error: input was null" ); + } + } + + /** + * This will peek at the next byte. + * + * @return The next byte on the stream, leaving it as available to read. + * + * @throws IOException If there is an error reading the next byte. + */ + public int peek() throws IOException + { + int result = read(); + if( result != -1 ) + { + unread( result ); + } + return result; + } + + /** + * A simple test to see if we are at the end of the stream. + * + * @return true if we are at the end of the stream. + * + * @throws IOException If there is an error reading the next byte. + */ + public boolean isEOF() throws IOException + { + int peek = peek(); + return peek == -1; + } + +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/io/RandomAccessFileInputStream.java b/src/main/java/org/pdfbox/io/RandomAccessFileInputStream.java new file mode 100644 index 0000000..6589bcb --- /dev/null +++ b/src/main/java/org/pdfbox/io/RandomAccessFileInputStream.java @@ -0,0 +1,132 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.io; + +import java.io.InputStream; +import java.io.IOException; +import java.io.RandomAccessFile; + +/** + * This class allows a section of a RandomAccessFile to be accessed as an + * input stream. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.3 $ + */ +public class RandomAccessFileInputStream extends InputStream +{ + private RandomAccessFile file; + private long currentPosition; + private long endPosition; + + /** + * Constructor. + * + * @param raFile The file to read the data from. + * @param startPosition The position in the file that this stream starts. + * @param length The length of the input stream. + */ + public RandomAccessFileInputStream( RandomAccessFile raFile, long startPosition, long length ) + { + file = raFile; + currentPosition = startPosition; + endPosition = currentPosition+length; + } + /** + * @see InputStream#available() + */ + public int available() + { + return (int)(endPosition - currentPosition); + } + /** + * @see InputStream#close() + */ + public void close() + { + //do nothing because we want to leave the random access file open. + } + /** + * @see InputStream#read() + */ + public int read() throws IOException + { + synchronized(file) + { + int retval = -1; + if( currentPosition < endPosition ) + { + file.seek( currentPosition ); + currentPosition++; + retval = file.read(); + } + return retval; + } + } + /** + * @see InputStream#read( byte[], int, int ) + */ + public int read( byte[] b, int offset, int length ) throws IOException + { + //only allow a read of the amount available. + if( length > available() ) + { + length = available(); + } + int amountRead = -1; + //only read if there are bytes actually available, otherwise + //return -1 if the EOF has been reached. + if( available() > 0 ) + { + synchronized(file) + { + file.seek( currentPosition ); + amountRead = file.read( b, offset, length ); + } + } + //update the current cursor position. + if( amountRead > 0 ) + { + currentPosition += amountRead; + } + return amountRead; + } + + /** + * @see InputStream#skip( long ) + */ + public long skip( long amountToSkip ) + { + long amountSkipped = Math.min( amountToSkip, available() ); + currentPosition+= amountSkipped; + return amountSkipped; + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/io/RandomAccessFileOutputStream.java b/src/main/java/org/pdfbox/io/RandomAccessFileOutputStream.java new file mode 100644 index 0000000..b2e7511 --- /dev/null +++ b/src/main/java/org/pdfbox/io/RandomAccessFileOutputStream.java @@ -0,0 +1,145 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.io; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.RandomAccessFile; + +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSObject; +import org.pdfbox.cos.COSNumber; + +/** + * This will write to a RandomAccessFile in the filesystem and keep track + * of the position it is writing to and the length of the stream. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.3 $ + */ +public class RandomAccessFileOutputStream extends OutputStream +{ + private RandomAccessFile file; + private long position; + private long lengthWritten = 0; + private COSBase expectedLength = null; + + /** + * Constructor to create an output stream that will write to the end of a + * random access file. + * + * @param raf The file to write to. + * + * @throws IOException If there is a problem accessing the raf. + */ + public RandomAccessFileOutputStream( RandomAccessFile raf ) throws IOException + { + file = raf; + //first get the position that we will be writing to + position = raf.length(); + } + + /** + * This will get the position in the RAF that the stream was written + * to. + * + * @return The position in the raf where the file can be obtained. + */ + public long getPosition() + { + return position; + } + + /** + * The number of bytes written to the stream. + * + * @return The number of bytes read to the stream. + */ + public long getLength() + { + long length = -1; + if( expectedLength instanceof COSNumber ) + { + length = ((COSNumber)expectedLength).intValue(); + } + else if( expectedLength instanceof COSObject && + ((COSObject)expectedLength).getObject() instanceof COSNumber ) + { + length = ((COSNumber)((COSObject)expectedLength).getObject()).intValue(); + } + if( length == -1 ) + { + length = lengthWritten; + } + return length; + } + + /** + * @see OutputStream#write( byte[], int, int ) + */ + public void write( byte[] b, int offset, int length ) throws IOException + { + file.seek( position+lengthWritten ); + lengthWritten += length; + file.write( b, offset, length ); + + } + /** + * @see OutputStream#write( int ) + */ + public void write( int b ) throws IOException + { + file.seek( position+lengthWritten ); + lengthWritten++; + file.write( b ); + } + + /** + * This will get the length that the PDF document specified this stream + * should be. This may not match the number of bytes read. + * + * @return The expected length. + */ + public COSBase getExpectedLength() + { + return expectedLength; + } + + /** + * This will set the expected length of this stream. + * + * @param value The expected value. + */ + public void setExpectedLength(COSBase value) + { + expectedLength = value; + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/io/package.html b/src/main/java/org/pdfbox/io/package.html new file mode 100644 index 0000000..12261f4 --- /dev/null +++ b/src/main/java/org/pdfbox/io/package.html @@ -0,0 +1,9 @@ + + + + + + +This package contains IO streams. + + diff --git a/src/main/java/org/pdfbox/package.html b/src/main/java/org/pdfbox/package.html new file mode 100644 index 0000000..f040f68 --- /dev/null +++ b/src/main/java/org/pdfbox/package.html @@ -0,0 +1,9 @@ + + + + + + +This package holds executable classes that interact with the PDFBox application. + + diff --git a/src/main/java/org/pdfbox/pdfparser/BaseParser.java b/src/main/java/org/pdfbox/pdfparser/BaseParser.java new file mode 100644 index 0000000..3937025 --- /dev/null +++ b/src/main/java/org/pdfbox/pdfparser/BaseParser.java @@ -0,0 +1,1369 @@ +/** + * Copyright (c) 2003-2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdfparser; + +import java.io.BufferedInputStream; +import java.io.InputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.RandomAccessFile; + +import java.util.ArrayList; +import java.util.List; + +import org.pdfbox.io.ByteArrayPushBackInputStream; +import org.pdfbox.io.PushBackInputStream; + +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSBoolean; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSDocument; +import org.pdfbox.cos.COSInteger; +import org.pdfbox.cos.COSName; +import org.pdfbox.cos.COSNull; +import org.pdfbox.cos.COSNumber; +import org.pdfbox.cos.COSObject; +import org.pdfbox.cos.COSStream; +import org.pdfbox.cos.COSString; + +import org.pdfbox.persistence.util.COSObjectKey; +import org.apache.log4j.Logger; + +/** + * This class is used to contain parsing logic that will be used by both the + * PDFParser and the COSStreamParser. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.57 $ + */ +public abstract class BaseParser +{ + private static Logger log = Logger.getLogger(BaseParser.class); + + /** + * This is a byte array that will be used for comparisons. + */ + public static final byte[] ENDSTREAM = + new byte[] {101,110,100,115,116,114,101,97,109};//"endstream".getBytes( "ISO-8859-1" ); + + /** + * This is a byte array that will be used for comparisons. + */ + public static final String DEF = "def"; + + /** + * This is the stream that will be read from. + */ + //protected PushBackByteArrayStream pdfSource; + protected PushBackInputStream pdfSource; + + /** + * moved xref here, is a persistence construct + * maybe not needed anyway when not read from behind with delayed + * access to objects. + */ + private List xrefs = new ArrayList(); + + private COSDocument document; + + /** + * Constructor. + * + * @param input The input stream to read the data from. + * + * @throws IOException If there is an error reading the input stream. + */ + public BaseParser( InputStream input) throws IOException + { + //pdfSource = new PushBackByteArrayStream( input ); + pdfSource = new PushBackInputStream( new BufferedInputStream( input, 16384 ), 4096 ); + } + + /** + * Constructor. + * + * @param input The array to read the data from. + * + * @throws IOException If there is an error reading the byte data. + */ + protected BaseParser(byte[] input) throws IOException + { + pdfSource = new ByteArrayPushBackInputStream(input); + } + + /** + * Set the document for this stream. + * + * @param doc The current document. + */ + public void setDocument( COSDocument doc ) + { + document = doc; + } + + private static boolean isHexDigit(char ch) + { + return (ch >= '0' && ch <= '9') || + (ch >= 'a' && ch <= 'f') || + (ch >= 'A' && ch <= 'F'); + // the line below can lead to problems with certain versions of the IBM JIT compiler + // (and is slower anyway) + //return (HEXDIGITS.indexOf(ch) != -1); + } + + /** + * This will parse a PDF dictionary value. + * + * @return The parsed Dictionary object. + * + * @throws IOException If there is an error parsing the dictionary object. + */ + private COSBase parseCOSDictionaryValue() throws IOException + { + + if( log.isDebugEnabled() ) + { + log.debug("parseCOSDictionaryValue() " + pdfSource ); + } + COSBase retval = null; + COSBase number = parseDirObject(); + skipSpaces(); + char next = (char)pdfSource.peek(); + if( next >= '0' && next <= '9' ) + { + COSBase generationNumber = parseDirObject(); + skipSpaces(); + char r = (char)pdfSource.read(); + if( r != 'R' ) + { + throw new IOException( "expected='R' actual='" + r + "' " + pdfSource ); + } + COSObjectKey key = new COSObjectKey(((COSInteger) number).intValue(), + ((COSInteger) generationNumber).intValue()); + retval = document.getObjectFromPool(key); + } + else + { + retval = number; + } + return retval; + } + + /** + * This will parse a PDF dictionary. + * + * @return The parsed dictionary. + * + * @throws IOException IF there is an error reading the stream. + */ + protected COSDictionary parseCOSDictionary() throws IOException + { + if( log.isDebugEnabled() ) + { + log.debug("parseCOSDictionary() " + pdfSource ); + } + char c = (char)pdfSource.read(); + if( c != '<') + { + throw new IOException( "expected='<' actual='" + c + "'" ); + } + c = (char)pdfSource.read(); + if( c != '<') + { + throw new IOException( "expected='<' actual='" + c + "' " + pdfSource ); + } + skipSpaces(); + COSDictionary obj = new COSDictionary(); + boolean done = false; + while( !done ) + { + skipSpaces(); + c = (char)pdfSource.peek(); + if( c == '>') + { + done = true; + } + else + { + COSName key = parseCOSName(); + COSBase value = parseCOSDictionaryValue(); + skipSpaces(); + if( ((char)pdfSource.peek()) == 'd' ) + { + //if the next string is 'def' then we are parsing a cmap stream + //and want to ignore it, otherwise throw an exception. + String potentialDEF = readString(); + if( !potentialDEF.equals( DEF ) ) + { + pdfSource.unread( potentialDEF.getBytes() ); + } + else + { + skipSpaces(); + } + } + + if( value == null ) + { + throw new IOException("Bad Dictionary Declaration " + pdfSource ); + } + obj.setItem( key, value ); + } + } + char ch = (char)pdfSource.read(); + if( ch != '>' ) + { + throw new IOException( "expected='>' actual='" + ch + "'" ); + } + ch = (char)pdfSource.read(); + if( ch != '>' ) + { + throw new IOException( "expected='>' actual='" + ch + "'" ); + } + if( log.isDebugEnabled() ) + { + log.debug("parseCOSDictionary() done peek='" + pdfSource.peek() + "'" ); + } + return obj; + } + + /** + * This will read a COSStream from the input stream. + * + * @param file The file to write the stream to when reading. + * @param dic The dictionary that goes with this stream. + * + * @return The parsed pdf stream. + * + * @throws IOException If there is an error reading the stream. + */ + protected COSStream parseCOSStream( COSDictionary dic, RandomAccessFile file ) throws IOException + { + if( log.isDebugEnabled() ) + { + log.debug("parseCOSStream() " + pdfSource ); + } + COSStream stream = new COSStream( dic, file ); + OutputStream out = null; + try + { + String streamString = readString(); + //long streamLength; + + if (!streamString.equals("stream")) + { + throw new IOException("expected='stream' actual='" + streamString + "'"); + } + + //PDF Ref 3.2.7 A stream must be followed by either + //a CRLF or LF but nothing else. + + int whitespace = pdfSource.read(); + + //see brother_scan_cover.pdf, it adds whitespaces + //after the stream but before the start of the + //data, so just read those first + while (whitespace == 0x20) + { + whitespace = pdfSource.read(); + } + + if( whitespace == 0x0D ) + { + whitespace = pdfSource.read(); + if( whitespace != 0x0A ) + { + pdfSource.unread( whitespace ); + //The spec says this is invalid but it happens in the real + //world so we must support it. + //throw new IOException("expected='0x0A' actual='0x" + + // Integer.toHexString(whitespace) + "' " + pdfSource); + } + } + else if (whitespace == 0x0A) + { + //that is fine + } + else + { + //we are in an error. + //but again we will do a lenient parsing and just assume that everything + //is fine + pdfSource.unread( whitespace ); + //throw new IOException("expected='0x0D or 0x0A' actual='0x" + + //Integer.toHexString(whitespace) + "' " + pdfSource); + + } + + + COSBase streamLength = dic.getDictionaryObject(COSName.LENGTH); + long length = -1; + if( streamLength instanceof COSNumber ) + { + length = ((COSNumber)streamLength).intValue(); + } + else if( streamLength instanceof COSObject && + ((COSObject)streamLength).getObject() instanceof COSNumber ) + { + length = ((COSNumber)((COSObject)streamLength).getObject()).intValue(); + } + + //length = -1; + //streamLength = null; + + //Need to keep track of the + out = stream.createFilteredStream( streamLength ); + String endStream = null; + //the length is wrong in some pdf documents which means + //that PDFBox must basically ignore it in order to be able to read + //the most number of PDF documents. This of course is a penalty hit, + //maybe I could implement a faster parser. + /**if( length != -1 ) + { + byte[] buffer = new byte[1024]; + int amountRead = 0; + int totalAmountRead = 0; + while( amountRead != -1 && totalAmountRead < length ) + { + int maxAmountToRead = Math.min(buffer.length, (int)(length-totalAmountRead)); + amountRead = pdfSource.read(buffer,0,maxAmountToRead); + totalAmountRead += amountRead; + if( amountRead != -1 ) + { + out.write( buffer, 0, amountRead ); + } + } + } + else + {**/ + readUntilEndStream( out ); + /**}*/ + skipSpaces(); + endStream = readString(); + + if (!endStream.equals("endstream")) + { + readUntilEndStream( out ); + endStream = readString(); + if( !endStream.equals( "endstream" ) ) + { + throw new IOException("expected='endstream' actual='" + endStream + "' " + pdfSource); + } + } + } + finally + { + if( out != null ) + { + out.close(); + } + } + if( log.isDebugEnabled() ) + { + log.debug("parseCOSStream() done" ); + } + return stream; + } + + private void readUntilEndStream( OutputStream out ) throws IOException + { + int currentIndex = 0; + int byteRead = 0; + //this is the additional bytes buffered but not written + int additionalBytes=0; + byte[] buffer = new byte[ENDSTREAM.length+additionalBytes]; + int writeIndex = 0; + while(!cmpCircularBuffer( buffer, currentIndex, ENDSTREAM ) && byteRead != -1 ) + { + writeIndex = currentIndex - buffer.length; + if( writeIndex >= 0 ) + { + out.write( buffer[writeIndex%buffer.length] ); + } + byteRead = pdfSource.read(); + buffer[currentIndex%buffer.length] = (byte)byteRead; + currentIndex++; + } + + //we want to ignore the end of the line data when reading a stream + //so will make an attempt to ignore it. + /*writeIndex = currentIndex - buffer.length; + if( buffer[writeIndex%buffer.length] == 13 && + buffer[(writeIndex+1)%buffer.length] == 10 ) + { + //then ignore the newline before the endstream + } + else if( buffer[(writeIndex+1)%buffer.length] == 10 ) + { + //Then first byte is data, second byte is newline + out.write( buffer[writeIndex%buffer.length] ); + } + else + { + out.write( buffer[writeIndex%buffer.length] ); + out.write( buffer[(writeIndex+1)%buffer.length] ); + }*/ + + /** + * Old way of handling newlines before endstream + for( int i=0; i=0 && + //buffer[writeIndex%buffer.length] != 10 && + buffer[writeIndex%buffer.length] != 13 ) + { + out.write( buffer[writeIndex%buffer.length] ); + } + currentIndex++; + } + */ + pdfSource.unread( ENDSTREAM ); + + } + + /** + * This basically checks to see if the next compareTo.length bytes of the + * buffer match the compareTo byte array. + */ + private boolean cmpCircularBuffer( byte[] buffer, int currentIndex, byte[] compareTo ) + { + int cmpLen = compareTo.length; + int buflen = buffer.length; + boolean match = true; + int off = currentIndex-cmpLen; + if( off < 0 ) + { + match = false; + } + for( int i=0; match && i 0 && c != -1) + { + char ch = (char)c; + int nextc = -2; // not yet read + //if( log.isDebugEnabled() ) + //{ + // log.debug( "Parsing COSString character '" + c + "' code=" + (int)c ); + //} + + if(ch == closeBrace) + { + braces--; + byte[] nextThreeBytes = new byte[3]; + int amountRead = pdfSource.read(nextThreeBytes); + + //lets handle the special case seen in Bull River Rules and Regulations.pdf + //The dictionary looks like this + // 2 0 obj + // << + // /Type /Info + // /Creator (PaperPort http://www.scansoft.com) + // /Producer (sspdflib 1.0 http://www.scansoft.com) + // /Title ( (5) + // /Author () + // /Subject () + // + // Notice the /Title, the braces are not even but they should + // be. So lets assume that if we encounter an this scenario + // then that + // means that there is an error in the pdf and assume that + // was the end of the document. + if( amountRead == 3 ) + { + if( nextThreeBytes[0] == 0x0d && + nextThreeBytes[1] == 0x0a && + nextThreeBytes[2] == 0x2f ) + { + braces = 0; + } + } + pdfSource.unread( nextThreeBytes, 0, amountRead ); + if( braces != 0 ) + { + retval.append( ch ); + } + } + else if( ch == openBrace ) + { + braces++; + retval.append( ch ); + } + else if( ch == '\\' ) + { + //patched by ram + char next = (char)pdfSource.read(); + switch(next) + { + case 'n': + retval.append( '\n' ); + break; + case 'r': + retval.append( '\r' ); + break; + case 't': + retval.append( '\t' ); + break; + case 'b': + retval.append( '\b' ); + break; + case 'f': + retval.append( '\f' ); + break; + case '(': + case ')': + case '\\': + retval.append( next ); + break; + case 10: + case 13: + //this is a break in the line so ignore it and the newline and continue + c = pdfSource.read(); + while( isEOL(c) && c != -1) + { + c = pdfSource.read(); + } + nextc = c; + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + { + StringBuffer octal = new StringBuffer(); + octal.append( next ); + c = pdfSource.read(); + char digit = (char)c; + if( digit >= '0' && digit <= '7' ) + { + octal.append( digit ); + c = pdfSource.read(); + digit = (char)c; + if( digit >= '0' && digit <= '7' ) + { + octal.append( digit ); + } + else + { + nextc = c; + } + } + else + { + nextc = c; + } + + int character = 0; + try + { + character = Integer.parseInt( octal.toString(), 8 ); + } + catch( NumberFormatException e ) + { + throw new IOException( "Error: Expected octal character, actual='" + octal + "'" ); + } + retval.append( character ); + break; + } + default: + { + retval.append( '\\' ); + retval.append( next ); + //another ficken problem with PDF's, sometimes the \ doesn't really + //mean escape like the PDF spec says it does, sometimes is should be literal + //which is what we will assume here. + //throw new IOException( "Unexpected break sequence '" + next + "' " + pdfSource ); + } + } + } + else + { + if( openBrace == '<' ) + { + if( isHexDigit(ch) ) + { + retval.append( ch ); + } + } + else + { + retval.append( ch ); + } + } + if (nextc != -2) + { + c = nextc; + } + else + { + c = pdfSource.read(); + } + } + if (c != -1) + { + pdfSource.unread(c); + } + if( openBrace == '<' ) + { + retval = COSString.createFromHexString( retval.getString() ); + } + if( log.isDebugEnabled() ) + { + log.debug("parseCOSString() done parsed=" + retval ); + } + return retval; + } + + /** + * This will parse a PDF array object. + * + * @return The parsed PDF array. + * + * @throws IOException If there is an error parsing the stream. + */ + protected COSArray parseCOSArray() throws IOException + { + if( log.isDebugEnabled() ) + { + log.debug("parseCOSArray() " + pdfSource ); + } + char ch = (char)pdfSource.read(); + if( ch != '[') + { + throw new IOException( "expected='[' actual='" + ch + "'" ); + } + COSArray po = new COSArray(); + COSBase pbo = null; + skipSpaces(); + int i = 0; + while( ((i = pdfSource.peek()) > 0) && ((char)i != ']') ) + { + pbo = parseDirObject(); + if( pbo instanceof COSObject ) + { + COSInteger genNumber = (COSInteger)po.remove( po.size() -1 ); + COSInteger number = (COSInteger)po.remove( po.size() -1 ); + COSObjectKey key = new COSObjectKey(number.intValue(), genNumber.intValue()); + pbo = document.getObjectFromPool(key); + } + if( pbo != null ) + { + po.add( pbo ); + } + else + { + //it could be a bad object in the array which is just skipped + } + skipSpaces(); + } + pdfSource.read(); //read ']' + skipSpaces(); + if( log.isDebugEnabled() ) + { + log.debug("parseCOSArray() done peek='" + (char)pdfSource.peek() + "'" ); + } + return po; + } + + /** + * Determine if a character terminates a PDF name. + * + * @param ch The character + * @return true if the character terminates a PDF name, otherwise false. + */ + protected boolean isEndOfName(char ch) + { + return (ch == ' ' || ch == 13 || ch == 10 || ch == 9 || ch == '>' || ch == '<' + || ch == '[' || ch =='/' || ch ==']' || ch ==')' || ch =='(' || + ch == -1 //EOF + ); + } + + /** + * This will parse a PDF name from the stream. + * + * @return The parsed PDF name. + * + * @throws IOException If there is an error reading from the stream. + */ + protected COSName parseCOSName() throws IOException + { + if( log.isDebugEnabled() ) + { + log.debug("parseCOSName() " + pdfSource ); + } + COSName retval = null; + int c = pdfSource.read(); + if( (char)c != '/') + { + throw new IOException("expected='/' actual='" + (char)c + "'-" + c + " " + pdfSource ); + } + // costruisce il nome + StringBuffer buffer = new StringBuffer(); + c = pdfSource.read(); + while( c != -1 ) + { + char ch = (char)c; + if(ch == '#') + { + char ch1 = (char)pdfSource.read(); + char ch2 = (char)pdfSource.read(); + + // Prior to PDF v1.2, the # was not a special character. Also, + // it has been observed that various PDF tools do not follow the + // spec with respect to the # escape, even though they report + // PDF versions of 1.2 or later. The solution here is that we + // interpret the # as an escape only when it is followed by two + // valid hex digits. + // + if (isHexDigit(ch1) && isHexDigit(ch2)) + { + String hex = "" + ch1 + ch2; + try + { + buffer.append( (char) Integer.parseInt(hex, 16)); + } + catch (NumberFormatException e) + { + if( log.isDebugEnabled() ) + { + log.debug("isHexDigit(ch1)=" + isHexDigit(ch1) + ", isHexDigit(ch2)=" + isHexDigit(ch2)); + } + throw new IOException("Error: expected hex number, actual='" + hex + "'"); + } + c = pdfSource.read(); + } + else + { + pdfSource.unread(ch2); + c = ch1; + buffer.append( ch ); + } + } + else if (isEndOfName(ch)) + { + break; + } + else + { + buffer.append( ch ); + c = pdfSource.read(); + } + } + if (c != -1) + { + pdfSource.unread(c); + } + retval = COSName.getPDFName( buffer.toString() ); + return retval; + } + + /** + * This will parse a boolean object from the stream. + * + * @return The parsed boolean object. + * + * @throws IOException If an IO error occurs during parsing. + */ + protected COSBoolean parseBoolean() throws IOException + { + COSBoolean retval = null; + char c = (char)pdfSource.peek(); + if( c == 't' ) + { + byte[] trueArray = new byte[ 4 ]; + int amountRead = pdfSource.read( trueArray, 0, 4 ); + String trueString = new String( trueArray, 0, amountRead ); + if( !trueString.equals( "true" ) ) + { + throw new IOException( "Error parsing boolean: expected='true' actual='" + trueString + "'" ); + } + else + { + retval = COSBoolean.TRUE; + } + } + else if( c == 'f' ) + { + byte[] falseArray = new byte[ 5 ]; + int amountRead = pdfSource.read( falseArray, 0, 5 ); + String falseString = new String( falseArray, 0, amountRead ); + if( !falseString.equals( "false" ) ) + { + throw new IOException( "Error parsing boolean: expected='true' actual='" + falseString + "'" ); + } + else + { + retval = COSBoolean.FALSE; + } + } + else + { + throw new IOException( "Error parsing boolean expected='t or f' actual='" + c + "'" ); + } + return retval; + } + + /** + * This will parse a directory object from the stream. + * + * @return The parsed object. + * + * @throws IOException If there is an error during parsing. + */ + protected COSBase parseDirObject() throws IOException + { + if( log.isDebugEnabled() ) + { + log.debug("parseDirObject() " + pdfSource ); + } + COSBase retval = null; + + skipSpaces(); + int nextByte = pdfSource.peek(); + char c = (char)nextByte; + switch(c) + { + case '<': + { + int leftBracket = pdfSource.read();//pull off first left bracket + c = (char)pdfSource.peek(); //check for second left bracket + pdfSource.unread( leftBracket ); + if(c == '<') + { + + retval = parseCOSDictionary(); + skipSpaces(); + } + else + { + retval = parseCOSString(); + } + break; + } + case '[': // array + { + retval = parseCOSArray(); + break; + } + case '(': + retval = parseCOSString(); + break; + case '/': // name + retval = parseCOSName(); + break; + case 'n': // null + { + String nullString = readString(); + if( !nullString.equals( "null") ) + { + throw new IOException("Expected='null' actual='" + nullString + "'"); + } + retval = COSNull.NULL; + break; + } + case 't': + { + byte[] trueBytes = new byte[4]; + int amountRead = pdfSource.read( trueBytes, 0, 4 ); + String trueString = new String( trueBytes, 0, amountRead ); + if( trueString.equals( "true" ) ) + { + retval = COSBoolean.TRUE; + } + else + { + throw new IOException( "expected true actual='" + trueString + "' " + pdfSource ); + } + break; + } + case 'f': + { + byte[] falseBytes = new byte[5]; + int amountRead = pdfSource.read( falseBytes, 0, 5 ); + String falseString = new String( falseBytes, 0, amountRead ); + if( falseString.equals( "false" ) ) + { + retval = COSBoolean.FALSE; + } + else + { + throw new IOException( "expected false actual='" + falseString + "' " + pdfSource ); + } + break; + } + case 'R': + pdfSource.read(); + retval = new COSObject(null); + break; + case (char)-1: + return null; + default: + { + if( Character.isDigit(c) || c == '-' || c == '+' || c == '.') + { + StringBuffer buf = new StringBuffer(); + int ic = pdfSource.read(); + c = (char)ic; + while( Character.isDigit( c )|| + c == '-' || + c == '+' || + c == '.' || + c == 'E' || + c == 'e' ) + { + buf.append( c ); + ic = pdfSource.read(); + c = (char)ic; + } + if( ic != -1 ) + { + pdfSource.unread( ic ); + } + retval = COSNumber.get( buf.toString() ); + } + else + { + //This is not suppose to happen, but we will allow for it + //so we are more compatible with POS writers that don't + //follow the spec + String badString = readString(); + //throw new IOException( "Unknown dir object c='" + c + + //"' peek='" + (char)pdfSource.peek() + "' " + pdfSource ); + if( log.isDebugEnabled() ) + { + log.debug("parseDirObject() bad DIR object found. ignoring: '" + badString + "'"); + } + if( badString == null || badString.length() == 0 ) + { + int peek = pdfSource.peek(); + // we can end up in an infinite loop otherwise + throw new IOException( "Unknown dir object c='" + c + + "' cInt=" + (int)c + " peek='" + (char)peek + "' peekInt=" + peek + " " + pdfSource ); + } + + } + } + } + if( log.isDebugEnabled() ) + { + log.debug("parseDirObject() done retval=" +retval ); + } + return retval; + } + + /** + * This will read the next string from the stream. + * + * @return The string that was read from the stream. + * + * @throws IOException If there is an error reading from the stream. + */ + protected String readString() throws IOException + { + skipSpaces(); + StringBuffer buffer = new StringBuffer(); + int c = pdfSource.read(); + while( !isEndOfName((char)c) && !isClosing(c) && c != -1 ) + { + buffer.append( (char)c ); + c = pdfSource.read(); + } + if (c != -1) + { + pdfSource.unread(c); + } + return buffer.toString(); + } + + /** + * This will read bytes until the end of line marker occurs. + * + * @param theString The next expected string in the stream. + * + * @return The characters between the current position and the end of the line. + * + * @throws IOException If there is an error reading from the stream or theString does not match what was read. + */ + protected String readExpectedString( String theString ) throws IOException + { + int c = pdfSource.read(); + while( isWhitespace(c) && c != -1) + { + c = pdfSource.read(); + } + StringBuffer buffer = new StringBuffer( theString.length() ); + int charsRead = 0; + while( !isEOL(c) && c != -1 && charsRead < theString.length() ) + { + char next = (char)c; + buffer.append( next ); + if( theString.charAt( charsRead ) == next ) + { + charsRead++; + } + else + { + throw new IOException( "Error: Expected to read '" + theString + + "' instead started reading '" +buffer.toString() + "'" ); + } + c = pdfSource.read(); + } + while( isEOL(c) && c != -1 ) + { + c = pdfSource.read(); + } + if (c != -1) + { + pdfSource.unread(c); + } + return buffer.toString(); + } + + /** + * This will read the next string from the stream up to a certain length. + * + * @param length The length to stop reading at. + * + * @return The string that was read from the stream of length 0 to length. + * + * @throws IOException If there is an error reading from the stream. + */ + protected String readString( int length ) throws IOException + { + skipSpaces(); + + int c = pdfSource.read(); + + //average string size is around 2 and the normal string buffer size is + //about 16 so lets save some space. + StringBuffer buffer = new StringBuffer(length); + while( !isWhitespace(c) && !isClosing(c) && c != -1 && buffer.length() < length && + c != '[' && + c != '<' && + c != '(' && + c != '/' ) + { + buffer.append( (char)c ); + c = pdfSource.read(); + } + if (c != -1) + { + pdfSource.unread(c); + } + return buffer.toString(); + } + + /** + * This will tell if the next character is a closing brace( close of PDF array ). + * + * @return true if the next byte is ']', false otherwise. + * + * @throws IOException If an IO error occurs. + */ + protected boolean isClosing() throws IOException + { + return isClosing(pdfSource.peek()); + } + + /** + * This will tell if the next character is a closing brace( close of PDF array ). + * + * @param c The character to check against end of line + * @return true if the next byte is ']', false otherwise. + */ + protected boolean isClosing(int c) + { + return c == ']'; + } + + /** + * This will read bytes until the end of line marker occurs. + * + * @return The characters between the current position and the end of the line. + * + * @throws IOException If there is an error reading from the stream. + */ + protected String readLine() throws IOException + { + int c = pdfSource.read(); + while(isWhitespace(c) && c != -1) + { + c = pdfSource.read(); + } + StringBuffer buffer = new StringBuffer( 11 ); + + while( !isEOL(c) && c != -1 ) + { + buffer.append( (char)c ); + c = pdfSource.read(); + } + while( isEOL(c) && c != -1 ) + { + c = pdfSource.read(); + } + if (c != -1) + { + pdfSource.unread(c); + } + return buffer.toString(); + } + + /** + * This will tell if the next byte to be read is an end of line byte. + * + * @return true if the next byte is 0x0A or 0x0D. + * + * @throws IOException If there is an error reading from the stream. + */ + protected boolean isEOL() throws IOException + { + return isEOL(pdfSource.peek()); + } + + /** + * This will tell if the next byte to be read is an end of line byte. + * + * @param c The character to check against end of line + * @return true if the next byte is 0x0A or 0x0D. + */ + protected boolean isEOL(int c) + { + return c == 10 || c == 13; + } + + /** + * This will tell if the next byte is whitespace or not. + * + * @return true if the next byte in the stream is a whitespace character. + * + * @throws IOException If there is an error reading from the stream. + */ + protected boolean isWhitespace() throws IOException + { + return isWhitespace( pdfSource.peek() ); + } + + /** + * This will tell if the next byte is whitespace or not. + * + * @param c The character to check against whitespace + * + * @return true if the next byte in the stream is a whitespace character. + */ + protected boolean isWhitespace( int c ) + { + return c == 0 || c == 9 || c == 12 || c == 10 + || c == 13 || c == 32; + } + + /** + * This will skip all spaces and comments that are present. + * + * @throws IOException If there is an error reading from the stream. + */ + protected void skipSpaces() throws IOException + { + //log( "skipSpaces() " + pdfSource ); + int c = pdfSource.read(); + // identical to, but faster as: isWhiteSpace(c) || c == 37 + while(c == 0 || c == 9 || c == 12 || c == 10 + || c == 13 || c == 32 || c == 37)//37 is the % character, a comment + { + if ( c == 37 ) + { + // skip past the comment section + c = pdfSource.read(); + while(!isEOL(c) && c != -1) + { + c = pdfSource.read(); + } + } + else + { + c = pdfSource.read(); + } + } + if (c != -1) + { + pdfSource.unread(c); + } + //log( "skipSpaces() done peek='" + (char)pdfSource.peek() + "'" ); + } + + /** + * this will compare two byte arrays. + * + * @param first The first byte array to compare. + * @param second The second byte array to compare. + * + * @return true if both arrays are the same AND forall i : first[i] = second[i] + */ + private boolean cmpArray( byte[] first, byte[] second ) + { + return cmpArray( first, 0, second ); + } + + /** + * This will compare two arrays for equality. + * + * @param first The first array to compare. + * @param firstOffset The first byte to start comparing. + * @param second The second array to compare. + */ + private boolean cmpArray( byte[] first, int firstOffset, byte[] second ) + { + boolean retval = true; + if( first.length-firstOffset >= second.length ) + { + int arrayLength = second.length; + for( int i =0; i 0 ) + { + //trim off any leading characters + header = header.substring( headerStart, header.length() ); + } + + try + { + float pdfVersion = Float.parseFloat( + header.substring( PDF_HEADER.length(), Math.min( header.length(), PDF_HEADER.length()+3) ) ); + document.setVersion( pdfVersion ); + } + catch( NumberFormatException e ) + { + throw new IOException( "Error getting pdf version:" + e ); + } + + skipHeaderFillBytes(); + + + Object nextObject; + boolean wasLastParsedObjectAnXref = false; + try + { + while( (nextObject = parseObject()) != null ) + { + if( nextObject instanceof PDFXref ) + { + PDFXref xref = (PDFXref)nextObject; + addXref(xref); + wasLastParsedObjectAnXref = true; + } + else + { + wasLastParsedObjectAnXref = false; + } + skipSpaces(); + } + if( document.getTrailer() == null ) + { + COSDictionary trailer = new COSDictionary(); + Iterator xrefIter = document.getObjectsByType( "XRef" ).iterator(); + while( xrefIter.hasNext() ) + { + COSStream next = (COSStream)((COSObject)xrefIter.next()).getObject(); + trailer.addAll( next ); + } + document.setTrailer( trailer ); + } + if( !document.isEncrypted() ) + { + document.dereferenceObjectStreams(); + } + } + catch( IOException e ) + { + if( wasLastParsedObjectAnXref ) + { + log.debug( "Skipping some garbage", e ); + //Then we assume that there is just random garbage after + //the xref, not sure why the PDF spec allows this but it does. + } + else + { + //some other error so just pass it along + throw e; + } + } + } + catch( Throwable t ) + { + //so if the PDF is corrupt then close the document and clear + //all resources to it + if( document != null ) + { + document.close(); + } + if( t instanceof IOException ) + { + throw (IOException)t; + } + else + { + throw new WrappedIOException( t ); + } + } + finally + { + pdfSource.close(); + } + } + + /** + * This will skip a header's binary fill bytes. This is in accordance to + * PDF Specification 1.5 pg 68 section 3.4.1 "Syntax.File Structure.File Header" + * + * @throws IOException If there is an error reading from the stream. + */ + protected void skipHeaderFillBytes() throws IOException + { + skipSpaces(); + int c = pdfSource.peek(); + + if( !Character.isDigit( (char)c ) ) + { + // Fill bytes conform with PDF reference (but without comment sign) + // => skip until EOL + readLine(); + } + // else: no fill bytes + } + + /** + * This will get the document that was parsed. parse() must be called before this is called. + * When you are done with this document you must call close() on it to release + * resources. + * + * @return The document that was parsed. + * + * @throws IOException If there is an error getting the document. + */ + public COSDocument getDocument() throws IOException + { + if( document == null ) + { + throw new IOException( "You must call parse() before calling getDocument()" ); + } + return document; + } + + /** + * This will get the PD document that was parsed. When you are done with + * this document you must call close() on it to release resources. + * + * @return The document at the PD layer. + * + * @throws IOException If there is an error getting the document. + */ + public PDDocument getPDDocument() throws IOException + { + return new PDDocument( getDocument() ); + } + + /** + * This will get the FDF document that was parsed. When you are done with + * this document you must call close() on it to release resources. + * + * @return The document at the PD layer. + * + * @throws IOException If there is an error getting the document. + */ + public FDFDocument getFDFDocument() throws IOException + { + return new FDFDocument( getDocument() ); + } + + /** + * This will parse a document object from the stream. + * + * @return The parsed object. + * + * @throws IOException If an IO error occurs. + */ + private Object parseObject() throws IOException + { + Object object = null; + char peekedChar = (char)pdfSource.peek(); + if( log.isDebugEnabled() ) + { + log.debug( "PDFParser.parseObject() peek='" + peekedChar + "'" ); + } + if( pdfSource.isEOF() ) + { + if( log.isDebugEnabled() ) + { + log.debug( "Skipping because of EOF" ); + //end of file we will return a null object and call it a day. + } + } + else if( peekedChar == 'x' || + peekedChar == 't' || + peekedChar == 's') + { + //System.out.println( "parseObject() parsing xref" ); + + //FDF documents do not always have the xref + if( peekedChar == 'x' || peekedChar == 't' ) + { + object = parseXrefSection(); + } + + //if peeked char is xref or startxref + if( peekedChar == 'x' || peekedChar == 's') + { + skipSpaces(); + while( pdfSource.peek() == 'x' ) + { + parseXrefSection(); + } + String startxref = readString(); + if( !startxref.equals( "startxref" ) ) + { + throw new IOException( "expected='startxref' actual='" + startxref + "' " + pdfSource ); + } + skipSpaces(); + //read some integer that is in the stream but PDFBox doesn't use + readInt(); + } + + //This MUST be readLine because readString strips out comments + //and it will think that %% is a comment in from of the EOF + String eof = readExpectedString( "%%EOF" ); + if( eof.indexOf( "%%EOF" )== -1 && !pdfSource.isEOF() ) + { + throw new IOException( "expected='%%EOF' actual='" + eof + "' next=" + readString() + + " next=" +readString() ); + } + else if( !pdfSource.isEOF() ) + { + //we might really be at the end of the file, there might just be some crap at the + //end of the file. + if( pdfSource.available() < 1000 ) + { + //We need to determine if we are at the end of the file. + byte[] data = new byte[ 1000 ]; + + int amountRead = pdfSource.read( data ); + if( amountRead != -1 ) + { + pdfSource.unread( data, 0, amountRead ); + } + boolean atEndOfFile = true;//we assume yes unless we find another. + for( int i=0; iEI. + while( !(isWhitespace( twoBytesAgo ) && + lastByte == 'E' && + currentByte == 'I' && + isWhitespace() //&& + //amyuni2_05d__pdf1_3_acro4x.pdf has image data that + //is compressed, so expectedBytes is useless here. + //count >= expectedBytes + ) && + !pdfSource.isEOF() ) + { + imageData.write( lastByte ); + twoBytesAgo = lastByte; + lastByte = currentByte; + currentByte = pdfSource.read(); + count++; + } + pdfSource.unread( 'I' ); //unread the EI operator + pdfSource.unread( 'E' ); + retval = PDFOperator.getOperator( "ID" ); + ((PDFOperator)retval).setImageData( imageData.toByteArray() ); + break; + } + case ']': + { + // some ']' around without its previous '[' + // this means a PDF is somewhat corrupt but we will continue to parse. + pdfSource.read(); + retval = COSNull.NULL; // must be a better solution than null... + break; + } + default: + { + //we must be an operator + String operator = readOperator(); + if( operator.trim().length() == 0 ) + { + //we have a corrupt stream, stop reading here + retval = null; + } + else + { + retval = PDFOperator.getOperator( operator ); + } + } + + } + if( log.isDebugEnabled() ) + { + log.debug( "parseNextToken() retval=" + retval + " peek=" + (char)pdfSource.peek() + " end" ); + } + + return retval; + } + + /** + * This will read an operator from the stream. + * + * @return The operator that was read from the stream. + * + * @throws IOException If there is an error reading from the stream. + */ + protected String readOperator() throws IOException + { + skipSpaces(); + + //average string size is around 2 and the normal string buffer size is + //about 16 so lets save some space. + StringBuffer buffer = new StringBuffer(4); + while( + !isWhitespace() && + !isClosing() && + !pdfSource.isEOF() && + pdfSource.peek() != (int)'[' && + pdfSource.peek() != (int)'<' && + pdfSource.peek() != (int)'(' && + pdfSource.peek() != (int)'/' && + (pdfSource.peek() < (int)'0' || + pdfSource.peek() > (int)'9' ) ) + { + buffer.append( (char)pdfSource.read() ); + } + return buffer.toString(); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdfparser/PDFXref.java b/src/main/java/org/pdfbox/pdfparser/PDFXref.java new file mode 100644 index 0000000..abe0f35 --- /dev/null +++ b/src/main/java/org/pdfbox/pdfparser/PDFXref.java @@ -0,0 +1,96 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdfparser; + +/** + * This class represents a PDF xref. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.3 $ + */ +public class PDFXref +{ + + private long count; + private long start; + + /** + * constructor. + * + * @param startValue The start attribute. + * @param countValue The count attribute. + */ + public PDFXref( long startValue, long countValue ) + { + setStart( startValue ); + setCount( countValue ); + } + + /** + * This will get the count attribute. + * + * @return The count. + */ + public long getCount() + { + return count; + } + + /** + * This will get the start attribute. + * + * @return The start. + */ + public long getStart() + { + return start; + } + + /** + * This will set the count attribute. + * + * @param newCount The new count. + */ + private void setCount(long newCount) + { + count = newCount; + } + + /** + * This will set the start attribute. + * + * @param newStart The new start attribute. + */ + private void setStart(long newStart) + { + start = newStart; + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdfparser/package.html b/src/main/java/org/pdfbox/pdfparser/package.html new file mode 100644 index 0000000..fe012c1 --- /dev/null +++ b/src/main/java/org/pdfbox/pdfparser/package.html @@ -0,0 +1,9 @@ + + + + + + +The pdfparser package contains classes to parse PDF documents and objects within the document. + + diff --git a/src/main/java/org/pdfbox/pdfviewer/ArrayEntry.java b/src/main/java/org/pdfbox/pdfviewer/ArrayEntry.java new file mode 100644 index 0000000..e229587 --- /dev/null +++ b/src/main/java/org/pdfbox/pdfviewer/ArrayEntry.java @@ -0,0 +1,83 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdfviewer; + +/** + * This is a simple class that will contain an index and a value. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.2 $ + */ +public class ArrayEntry +{ + private int index; + private Object value; + + /** + * This will get the value for this entry. + * + * @return The value for this entry. + */ + public Object getValue() + { + return value; + } + + /** + * This will set the value for this entry. + * + * @param val the new value for this entry. + */ + public void setValue(Object val) + { + this.value = val; + } + + /** + * This will get the index of the array entry. + * + * @return The 0-based index into the array + */ + public int getIndex() + { + return index; + } + + /** + * This will set the index value. + * + * @param i The new index value. + */ + public void setIndex(int i) + { + index = i; + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdfviewer/MapEntry.java b/src/main/java/org/pdfbox/pdfviewer/MapEntry.java new file mode 100644 index 0000000..9fd73e5 --- /dev/null +++ b/src/main/java/org/pdfbox/pdfviewer/MapEntry.java @@ -0,0 +1,105 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdfviewer; + +import org.pdfbox.cos.COSName; + + +/** + * This is a simple class that will contain a key and a value. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.2 $ + */ +public class MapEntry +{ + private Object key; + private Object value; + + /** + * Get the key for this entry. + * + * @return The entry's key. + */ + public Object getKey() + { + return key; + } + + /** + * This will set the key for this entry. + * + * @param k the new key for this entry. + */ + public void setKey(Object k) + { + key = k; + } + + /** + * This will get the value for this entry. + * + * @return The value for this entry. + */ + public Object getValue() + { + return value; + } + + /** + * This will set the value for this entry. + * + * @param val the new value for this entry. + */ + public void setValue(Object val) + { + this.value = val; + } + + /** + * This will output a string representation of this class. + * + * @return A string representation of this class. + */ + public String toString() + { + String retval = null; + if( key instanceof COSName ) + { + retval = ((COSName)key).getName(); + } + else + { + retval = "" +key; + } + return retval; + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdfviewer/PDFPagePanel.java b/src/main/java/org/pdfbox/pdfviewer/PDFPagePanel.java new file mode 100644 index 0000000..1d28bd3 --- /dev/null +++ b/src/main/java/org/pdfbox/pdfviewer/PDFPagePanel.java @@ -0,0 +1,102 @@ +/** + * Copyright (c) 2004-2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdfviewer; + +import java.awt.Dimension; +import java.awt.Graphics; + +import java.io.IOException; + +import javax.swing.JPanel; + +import org.pdfbox.pdmodel.PDPage; + +import org.pdfbox.pdmodel.common.PDRectangle; + +/** + * This is a simple JPanel that can be used to display a PDF page. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.3 $ + */ +public class PDFPagePanel extends JPanel +{ + + private PDPage page; + private PageDrawer drawer = null; + private Dimension pageDimension = null; + + /** + * Constructor. + * + * @throws IOException If there is an error creating the Page drawing objects. + */ + public PDFPagePanel() throws IOException + { + drawer = new PageDrawer(); + } + + /** + * This will set the page that should be displayed in this panel. + * + * @param pdfPage The page to draw. + */ + public void setPage( PDPage pdfPage ) + { + page = pdfPage; + PDRectangle pageSize = page.findMediaBox(); + int rotation = page.findRotation(); + pageDimension = pageSize.createDimension(); + if( rotation == 90 || rotation == 270 ) + { + pageDimension = new Dimension( pageDimension.height, pageDimension.width ); + } + setSize( pageDimension ); + setBackground( java.awt.Color.white ); + } + + /** + * @see JPanel#paint( Graphics ) + */ + public void paint(Graphics g ) + { + try + { + g.setColor( getBackground() ); + g.fillRect( 0, 0, getWidth(), getHeight() ); + drawer.drawPage( g, page, pageDimension ); + } + catch( IOException e ) + { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdfviewer/PDFTreeCellRenderer.java b/src/main/java/org/pdfbox/pdfviewer/PDFTreeCellRenderer.java new file mode 100644 index 0000000..98c1f5a --- /dev/null +++ b/src/main/java/org/pdfbox/pdfviewer/PDFTreeCellRenderer.java @@ -0,0 +1,145 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdfviewer; + +import java.awt.Component; + +import javax.swing.JTree; + +import javax.swing.tree.DefaultTreeCellRenderer; + +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSName; +import org.pdfbox.cos.COSNull; +import org.pdfbox.cos.COSFloat; +import org.pdfbox.cos.COSInteger; +import org.pdfbox.cos.COSStream; +import org.pdfbox.cos.COSString; + +/** + * A class to render tree cells for the pdfviewer. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.5 $ + */ +public class PDFTreeCellRenderer extends DefaultTreeCellRenderer +{ + /** + * @see DefaultTreeCellRenderer#getTreeCellRendererComponent( JTree, Object, boolean, + * boolean, boolean, int, boolean ) + */ + public Component getTreeCellRendererComponent( + JTree tree, + Object nodeValue, + boolean isSelected, + boolean expanded, + boolean leaf, + int row, + boolean componentHasFocus) + { + nodeValue = convertToTreeObject( nodeValue ); + return super.getTreeCellRendererComponent( tree, nodeValue, isSelected, expanded, leaf, + row, componentHasFocus ); + } + + private Object convertToTreeObject( Object nodeValue ) + { + if( nodeValue instanceof MapEntry ) + { + MapEntry entry = (MapEntry)nodeValue; + COSName key = (COSName)entry.getKey(); + COSBase value = (COSBase)entry.getValue(); + nodeValue = key.getName() + ":" + convertToTreeObject( value ); + } + else if( nodeValue instanceof COSFloat ) + { + nodeValue = "" + ((COSFloat)nodeValue).floatValue(); + } + else if( nodeValue instanceof COSInteger ) + { + nodeValue = "" + ((COSInteger)nodeValue).intValue(); + } + else if( nodeValue instanceof COSString ) + { + nodeValue = ((COSString)nodeValue).getString(); + } + else if( nodeValue instanceof COSName ) + { + nodeValue = ((COSName)nodeValue).getName(); + } + else if( nodeValue instanceof ArrayEntry ) + { + ArrayEntry entry = (ArrayEntry)nodeValue; + nodeValue = "[" + entry.getIndex() + "]" + convertToTreeObject( entry.getValue() ); + } + else if( nodeValue instanceof COSNull ) + { + nodeValue = "null"; + } + else if( nodeValue instanceof COSDictionary ) + { + COSDictionary dict = (COSDictionary)nodeValue; + if( nodeValue instanceof COSStream ) + { + nodeValue = "Stream"; + } + else + { + nodeValue = "Dictionary"; + } + + COSName type = (COSName)dict.getDictionaryObject( COSName.TYPE ); + if( type != null ) + { + nodeValue = nodeValue + "(" + type.getName(); + COSName subType = (COSName)dict.getDictionaryObject( COSName.SUBTYPE ); + if( subType != null ) + { + nodeValue = nodeValue + ":" + subType.getName(); + } + + nodeValue = nodeValue + ")"; + } + } + else if( nodeValue instanceof COSArray ) + { + nodeValue="Array"; + } + else if( nodeValue instanceof COSString ) + { + nodeValue = ((COSString)nodeValue).getString(); + } + return nodeValue; + + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdfviewer/PDFTreeModel.java b/src/main/java/org/pdfbox/pdfviewer/PDFTreeModel.java new file mode 100644 index 0000000..368a2ca --- /dev/null +++ b/src/main/java/org/pdfbox/pdfviewer/PDFTreeModel.java @@ -0,0 +1,332 @@ +/** + * Copyright (c) 2003-2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdfviewer; + +/** + * A tree model that uses a cos document. + * + * + * @author wurtz + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.8 $ + */ +import javax.swing.tree.TreePath; +import javax.swing.tree.TreeModel; + +//import java.awt.event.*; +import javax.swing.event.TreeModelListener; + +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSDocument; +import org.pdfbox.cos.COSName; +import org.pdfbox.cos.COSObject; + +import org.pdfbox.pdmodel.PDDocument; + +import java.util.Collections; +import java.util.List; + +/** + * A class to model a PDF document as a tree structure. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.8 $ + */ +public class PDFTreeModel implements TreeModel +{ + private PDDocument document; + + /** + * constructor. + */ + public PDFTreeModel() + { + //default constructor + } + + /** + * Constructor to take a document. + * + * @param doc The document to display in the tree. + */ + public PDFTreeModel(PDDocument doc) + { + setDocument(doc); + } + + /** + * Set the document to display in the tree. + * + * @param doc The document to display in the tree. + */ + public void setDocument(PDDocument doc) + { + document = doc; + } + /** + * Adds a listener for the TreeModelEvent + * posted after the tree changes. + * + * @param l the listener to add + * @see #removeTreeModelListener + * + */ + public void addTreeModelListener(TreeModelListener l) + { + //required for interface + } + + /** + * Returns the child of parent at index index + * in the parent's + * child array. parent must be a node previously obtained + * from this data source. This should not return null + * if index + * is a valid index for parent (that is index >= 0 && + * index < getChildCount(parent)). + * + * @param parent a node in the tree, obtained from this data source + * @param index The index into the parent object to location the child object. + * @return the child of parent at index index + * + */ + public Object getChild(Object parent, int index) + { + Object retval = null; + if( parent instanceof COSArray ) + { + ArrayEntry entry = new ArrayEntry(); + entry.setIndex( index ); + entry.setValue( ((COSArray)parent).getObject( index ) ); + retval = entry; + } + else if( parent instanceof COSDictionary ) + { + COSDictionary dict = ((COSDictionary)parent); + List keys = dict.keyList(); + Collections.sort( keys ); + Object key = keys.get( index ); + Object value = dict.getDictionaryObject( (COSName)key ); + MapEntry entry = new MapEntry(); + entry.setKey( key ); + entry.setValue( value ); + retval = entry; + } + else if( parent instanceof MapEntry ) + { + retval = getChild( ((MapEntry)parent).getValue(), index ); + } + else if( parent instanceof ArrayEntry ) + { + retval = getChild( ((ArrayEntry)parent).getValue(), index ); + } + else if( parent instanceof COSDocument ) + { + retval = ((COSDocument)parent).getObjects().get( index ); + } + else if( parent instanceof COSObject ) + { + retval = ((COSObject)parent).getObject(); + } + else + { + throw new RuntimeException( "Unknown COS type " + parent.getClass().getName() ); + } + return retval; + } + + /** Returns the number of children of parent. + * Returns 0 if the node + * is a leaf or if it has no children. parent must be a node + * previously obtained from this data source. + * + * @param parent a node in the tree, obtained from this data source + * @return the number of children of the node parent + * + */ + public int getChildCount(Object parent) + { + int retval = 0; + if( parent instanceof COSArray ) + { + retval = ((COSArray)parent).size(); + } + else if( parent instanceof COSDictionary ) + { + retval = ((COSDictionary)parent).size(); + } + else if( parent instanceof MapEntry ) + { + retval = getChildCount( ((MapEntry)parent).getValue() ); + } + else if( parent instanceof ArrayEntry ) + { + retval = getChildCount( ((ArrayEntry)parent).getValue() ); + } + else if( parent instanceof COSDocument ) + { + retval = ((COSDocument)parent).getObjects().size(); + } + else if( parent instanceof COSObject ) + { + retval = 1; + } + return retval; + } + + /** Returns the index of child in parent. If parent + * is null or child is null, + * returns -1. + * + * @param parent a note in the tree, obtained from this data source + * @param child the node we are interested in + * @return the index of the child in the parent, or -1 if either + * child or parent are null + * + */ + public int getIndexOfChild(Object parent, Object child) + { + int retval = -1; + if( parent != null && child != null ) + { + if( parent instanceof COSArray ) + { + COSArray array = (COSArray)parent; + if( child instanceof ArrayEntry ) + { + ArrayEntry arrayEntry = (ArrayEntry)child; + retval = arrayEntry.getIndex(); + } + else + { + retval = array.indexOf( (COSBase)child ); + } + } + else if( parent instanceof COSDictionary ) + { + MapEntry entry = (MapEntry)child; + COSDictionary dict = (COSDictionary)parent; + List keys = dict.keyList(); + Collections.sort( keys ); + for( int i=0; retval == -1 && inull + * only if the tree has no nodes. + * + * @return the root of the tree + * + */ + public Object getRoot() + { + return document.getDocument().getTrailer(); + } + + /** Returns true if node is a leaf. + * It is possible for this method to return false + * even if node has no children. + * A directory in a filesystem, for example, + * may contain no files; the node representing + * the directory is not a leaf, but it also has no children. + * + * @param node a node in the tree, obtained from this data source + * @return true if node is a leaf + * + */ + public boolean isLeaf(Object node) + { + boolean isLeaf = !(node instanceof COSDictionary || + node instanceof COSArray || + node instanceof COSDocument || + node instanceof COSObject || + (node instanceof MapEntry && !isLeaf(((MapEntry)node).getValue()) ) || + (node instanceof ArrayEntry && !isLeaf(((ArrayEntry)node).getValue()) )); + return isLeaf; + } + + /** Removes a listener previously added with + * addTreeModelListener. + * + * @see #addTreeModelListener + * @param l the listener to remove + * + */ + + public void removeTreeModelListener(TreeModelListener l) + { + //required for interface + } + + /** Messaged when the user has altered the value for the item identified + * by path to newValue. + * If newValue signifies a truly new value + * the model should post a treeNodesChanged event. + * + * @param path path to the node that the user has altered + * @param newValue the new value from the TreeCellEditor + * + */ + public void valueForPathChanged(TreePath path, Object newValue) + { + //required for interface + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdfviewer/PageDrawer.java b/src/main/java/org/pdfbox/pdfviewer/PageDrawer.java new file mode 100644 index 0000000..7c39f7b --- /dev/null +++ b/src/main/java/org/pdfbox/pdfviewer/PageDrawer.java @@ -0,0 +1,268 @@ +/** + * Copyright (c) 2003-2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdfviewer; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.RenderingHints; + +import java.awt.geom.GeneralPath; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.pdfbox.pdmodel.PDPage; + +import org.pdfbox.pdmodel.font.PDFont; + +import org.pdfbox.util.PDFStreamEngine; +import org.pdfbox.util.ResourceLoader; +import org.pdfbox.util.TextPosition; + +/** + * This will paint a page in a PDF document to a graphics context. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.17 $ + */ +public class PageDrawer extends PDFStreamEngine +{ + + private Graphics2D graphics; + private Dimension pageSize; + private PDPage page; + + private List lineSubPaths = new ArrayList(); + private GeneralPath linePath = new GeneralPath(); + private Color strokingColor = Color.BLACK; + private Color nonStrokingColor = Color.BLACK; + + /** + * Default constructor, loads properties from file. + * + * @throws IOException If there is an error loading properties from the file. + */ + public PageDrawer() throws IOException + { + super( ResourceLoader.loadProperties( "Resources/PageDrawer.properties" ) ); + } + + /** + * This will draw the page to the requested context. + * + * @param g The graphics context to draw onto. + * @param p The page to draw. + * @param pageDimension The size of the page to draw. + * + * @throws IOException If there is an IO error while drawing the page. + */ + public void drawPage( Graphics g, PDPage p, Dimension pageDimension ) throws IOException + { + graphics = (Graphics2D)g; + page = p; + pageSize = pageDimension; + + graphics.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON ); + processStream( page, page.findResources(), page.getContents().getStream() ); + // Transformations should be done in order + // 1 - Translate + // 2 - Rotate + // 3 - Scale + // Refer to PDFReference p176 (or 188 in xpdf) + //AffineTransform transform = graphics.getTransform(); + //transform.setToTranslate( 0, page.findMediaBox().getHeight()/2 ); + //transform.setToRotation((double)p.getRotation()); + //transform.setTransform( 1, 0, 0, 1, 0, 0 ); + //transform.setToScale( 1, 1 ); + + //AffineTransform rotation = graphics.getTransform(); + //rotation.rotate( (page.findRotation() * Math.PI) / 180d ); + //graphics.setTransform( rotation ); + } + + /** + * You should override this method if you want to perform an action when a + * string is being shown. + * + * @param text The string to display. + */ + protected void showCharacter( TextPosition text ) + { + //should use colorspaces for the font color but for now assume that + //the font color is black + try + { + graphics.setColor( Color.black ); + PDFont font = text.getFont(); + font.drawString( text.getCharacter(), graphics, text.getFontSize(), text.getXScale(), text.getYScale(), + text.getX(), text.getY() ); + } + catch( IOException io ) + { + io.printStackTrace(); + } + } + + /** + * Get the graphics that we are currently drawing on. + * + * @return The graphics we are drawing on. + */ + public Graphics2D getGraphics() + { + return graphics; + } + + /** + * Get the page that is currently being drawn. + * + * @return The page that is being drawn. + */ + public PDPage getPage() + { + return page; + } + + /** + * Get the size of the page that is currently being drawn. + * + * @return The size of the page that is being drawn. + */ + public Dimension getPageSize() + { + return pageSize; + } + + /** + * Fix the y coordinate based on page rotation. + * + * @param x The x coordinate. + * @param y The y coordinate. + * @return The updated y coordinate. + */ + public double fixY( double x, double y ) + { + double retval = y; + int rotation = page.findRotation(); + if( rotation == 0 ) + { + retval = pageSize.getHeight() - y; + } + else if( rotation == 90 ) + { + retval = y; + } + return retval; + } + + /** + * Get the current line path to be drawn. + * + * @return The current line path to be drawn. + */ + public GeneralPath getLinePath() + { + return linePath; + } + + /** + * Set the line path to draw. + * + * @param newLinePath Set the line path to draw. + */ + public void setLinePath(GeneralPath newLinePath) + { + linePath = newLinePath; + } + + /** + * Get the current list of line paths to be drawn. + * + * @return The current list of line paths to be drawn. + */ + public List getLineSubPaths() + { + return lineSubPaths; + } + + /** + * Set the list of line paths to draw. + * + * @param newLineSubPaths Set the list of line paths to draw. + */ + public void setLineSubPaths(List newLineSubPaths) + { + lineSubPaths = newLineSubPaths; + } + + /** + * Get the non stroking color. + * + * @return The non stroking color. + */ + public Color getNonStrokingColor() + { + return nonStrokingColor; + } + + /** + * Set the non stroking color. + * + * @param newNonStrokingColor The non stroking color. + */ + public void setNonStrokingColor(Color newNonStrokingColor) + { + nonStrokingColor = newNonStrokingColor; + } + + /** + * Get the stroking color. + * + * @return The stroking color. + */ + public Color getStrokingColor() + { + return strokingColor; + } + + /** + * Set the stroking color. + * + * @param newStrokingColor The stroking color. + */ + public void setStrokingColor(Color newStrokingColor) + { + strokingColor = newStrokingColor; + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdfviewer/PageWrapper.java b/src/main/java/org/pdfbox/pdfviewer/PageWrapper.java new file mode 100644 index 0000000..b2dc275 --- /dev/null +++ b/src/main/java/org/pdfbox/pdfviewer/PageWrapper.java @@ -0,0 +1,118 @@ +/** + * Copyright (c) 2003-2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdfviewer; + +import java.awt.Dimension; +import java.awt.event.MouseEvent; +import java.awt.event.MouseMotionListener; +import java.io.IOException; + +import javax.swing.JPanel; + +import org.pdfbox.PDFReader; +import org.pdfbox.pdmodel.PDPage; + +/** + * A class to handle some prettyness around a single PDF page. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.4 $ + */ +public class PageWrapper implements MouseMotionListener +{ + private JPanel pageWrapper = new JPanel(); + private PDFPagePanel pagePanel = null; + private PDFReader reader = null; + + private static final int SPACE_AROUND_DOCUMENT = 20; + + /** + * Constructor. + * + * @param aReader The reader application that holds this page. + * + * @throws IOException If there is an error creating the page drawing objects. + */ + public PageWrapper( PDFReader aReader ) throws IOException + { + reader = aReader; + pagePanel = new PDFPagePanel(); + pageWrapper.setLayout( null ); + pageWrapper.add( pagePanel ); + pagePanel.setLocation( SPACE_AROUND_DOCUMENT, SPACE_AROUND_DOCUMENT ); + pageWrapper.setBorder( javax.swing.border.LineBorder.createBlackLineBorder() ); + pagePanel.addMouseMotionListener( this ); + } + + /** + * This will display the PDF page in this component. + * + * @param page The PDF page to display. + */ + public void displayPage( PDPage page ) + { + pagePanel.setPage( page ); + pagePanel.setPreferredSize( pagePanel.getSize() ); + Dimension d = pagePanel.getSize(); + d.width+=(SPACE_AROUND_DOCUMENT*2); + d.height+=(SPACE_AROUND_DOCUMENT*2); + + pageWrapper.setPreferredSize( d ); + pageWrapper.validate(); + } + + /** + * This will get the JPanel that can be displayed. + * + * @return The panel with the displayed PDF page. + */ + public JPanel getPanel() + { + return pageWrapper; + } + + /** + * @see MouseMotionListener#mouseDragged(MouseEvent) + */ + public void mouseDragged(MouseEvent e) + { + //do nothing when mouse moves. + } + + /** + * @see MouseMotionListener#mouseMoved( MouseEvent ) + */ + public void mouseMoved(MouseEvent e) + { + //reader.getBottomStatusPanel().getStatusLabel().setText( e.getX() + "," + (pagePanel.getHeight() - e.getY()) ); + reader.getBottomStatusPanel().getStatusLabel().setText( e.getX() + "," + e.getY() ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdfviewer/ReaderBottomPanel.java b/src/main/java/org/pdfbox/pdfviewer/ReaderBottomPanel.java new file mode 100644 index 0000000..516d2c2 --- /dev/null +++ b/src/main/java/org/pdfbox/pdfviewer/ReaderBottomPanel.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdfviewer; + +import java.awt.Dimension; + +import javax.swing.JPanel; + +import javax.swing.JLabel; +import java.awt.FlowLayout; +/** + * A panel to display at the bottom of the window for status and other stuff. + * + * @author Ben Litchfield (ben@pdfbox.org) + * @version $Revision: 1.1 $ + */ +public class ReaderBottomPanel extends JPanel +{ + + private JLabel statusLabel = null; + + /** + * This is the default constructor. + */ + public ReaderBottomPanel() + { + super(); + initialize(); + } + + /** + * This method initializes this. + */ + private void initialize() + { + FlowLayout flowLayout1 = new FlowLayout(); + this.setLayout(flowLayout1); + this.setComponentOrientation(java.awt.ComponentOrientation.LEFT_TO_RIGHT); + this.setPreferredSize( new Dimension( 1000, 20 ) ); + flowLayout1.setAlignment(java.awt.FlowLayout.LEFT); + this.add(getStatusLabel(), null); + } + + /** + * This method initializes status label. + * + * @return javax.swing.JLabel + */ + public JLabel getStatusLabel() + { + if (statusLabel == null) + { + statusLabel = new JLabel(); + statusLabel.setText("Ready"); + } + return statusLabel; + } + } diff --git a/src/main/java/org/pdfbox/pdfviewer/package.html b/src/main/java/org/pdfbox/pdfviewer/package.html new file mode 100644 index 0000000..85ec4b6 --- /dev/null +++ b/src/main/java/org/pdfbox/pdfviewer/package.html @@ -0,0 +1,9 @@ + + + + + + +The pdfviewer package contains classes to graphically display information about a PDF document. + + diff --git a/src/main/java/org/pdfbox/pdfwriter/COSStandardOutputStream.java b/src/main/java/org/pdfbox/pdfwriter/COSStandardOutputStream.java new file mode 100644 index 0000000..1881bf2 --- /dev/null +++ b/src/main/java/org/pdfbox/pdfwriter/COSStandardOutputStream.java @@ -0,0 +1,180 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdfwriter; + + + +import java.io.FilterOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * simple output stream with some minor features for generating "pretty" + * pdf files. + * + * @author Michael Traut + * @version $Revision: 1.4 $ + */ +public class COSStandardOutputStream extends FilterOutputStream +{ + + /** + * To be used when 2 byte sequence is enforced. + */ + public static final byte[] CRLF = "\r\n".getBytes(); + + /** + * Line feed character. + */ + public static final byte[] LF = "\n".getBytes(); + + /** + * standard line separator on this platform. + */ + public static final byte[] EOL = System.getProperty("line.separator").getBytes(); + + // current byte pos in the output stream + private long pos = 0; + // flag to prevent generating two newlines in sequence + private boolean onNewLine = false; + + /** + * COSOutputStream constructor comment. + * + * @param out The underlying stream to write to. + */ + public COSStandardOutputStream(OutputStream out) + { + super(out); + } + /** + * This will get the current position in the stream. + * + * @return The current position in the stream. + */ + public long getPos() + { + return pos; + } + /** + * This will tell if we are on a newling. + * + * @return true If we are on a newline. + */ + public boolean isOnNewLine() + { + return onNewLine; + } + /** + * This will set a flag telling if we are on a newline. + * + * @param newOnNewLine The new value for the onNewLine attribute. + */ + public void setOnNewLine(boolean newOnNewLine) + { + onNewLine = newOnNewLine; + } + /** + * This will set the position in the stream. + * + * @param newPos The new position in the stream. + */ + private void setPos(int newPos) + { + pos = newPos; + } + + /** + * This will write some byte to the stream. + * + * @param b The source byte array. + * @param off The offset into the array to start writing. + * @param len The number of bytes to write. + * + * @throws IOException If the underlying stream throws an exception. + */ + public void write(byte[] b, int off, int len) throws IOException + { + setOnNewLine(false); + out.write(b, off, len); + pos += len; + } + + /** + * This will write a single byte to the stream. + * + * @param b The byte to write to the stream. + * + * @throws IOException If there is an error writing to the underlying stream. + */ + public void write(int b) throws IOException + { + setOnNewLine(false); + out.write(b); + pos++; + } + + /** + * This will write a CRLF to the stream. + * + * @throws IOException If there is an error writing the data to the stream. + */ + public void writeCRLF() throws IOException + { + write(CRLF); + // setOnNewLine(true); + } + + /** + * This will write an EOL to the stream. + * + * @throws IOException If there is an error writing to the stream + */ + public void writeEOL() throws IOException + { + if (!isOnNewLine()) + { + write(EOL); + setOnNewLine(true); + } + } + + /** + * This will write a Linefeed to the stream. + * + * @throws IOException If there is an error writing to the underlying stream. + */ + public void writeLF() throws IOException + { + write(LF); + // setOnNewLine(true); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdfwriter/COSWriter.java b/src/main/java/org/pdfbox/pdfwriter/COSWriter.java new file mode 100644 index 0000000..fa9cf48 --- /dev/null +++ b/src/main/java/org/pdfbox/pdfwriter/COSWriter.java @@ -0,0 +1,1091 @@ +/** + * Copyright (c) 2003-2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdfwriter; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +import java.text.DecimalFormat; +import java.text.NumberFormat; + +import org.pdfbox.persistence.util.COSObjectKey; + +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSFloat; +import org.pdfbox.cos.ICOSVisitor; +import org.pdfbox.cos.COSName; +import org.pdfbox.cos.COSString; +import org.pdfbox.cos.COSBoolean; +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSDocument; +import org.pdfbox.cos.COSStream; +import org.pdfbox.cos.COSObject; +import org.pdfbox.encryption.DocumentEncryption; +import org.pdfbox.exceptions.COSVisitorException; +import org.pdfbox.exceptions.CryptographyException; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSInteger; +import org.pdfbox.cos.COSNull; + +import org.pdfbox.pdmodel.PDDocument; + +import org.apache.log4j.Logger; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +/** + * this class acts on a in-memory representation of a pdf document. + * + * todo no support for incremental updates + * todo single xref section only + * todo no linearization + * + * @author Michael Traut + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.32 $ + */ +public class COSWriter implements ICOSVisitor +{ + + private static Logger log = Logger.getLogger( COSWriter.class ); + /** + * The dictionary open token. + */ + public static final byte[] DICT_OPEN = "<<".getBytes(); + /** + * The dictionary close token. + */ + public static final byte[] DICT_CLOSE = ">>".getBytes(); + /** + * space character. + */ + public static final byte[] SPACE = " ".getBytes(); + /** + * The start to a PDF comment. + */ + public static final byte[] COMMENT = "%".getBytes(); + + /** + * The output version of the PDF. + */ + public static final byte[] VERSION = "PDF-1.4".getBytes(); + /** + * Garbage bytes used to create the PDF header. + */ + public static final byte[] GARBAGE = new byte[] {(byte)0xf6, (byte)0xe4, (byte)0xfc, (byte)0xdf}; + /** + * The EOF constant. + */ + public static final byte[] EOF = "%%EOF".getBytes(); + // pdf tokens + + /** + * The reference token. + */ + public static final byte[] REFERENCE = "R".getBytes(); + /** + * The XREF token. + */ + public static final byte[] XREF = "xref".getBytes(); + /** + * The xref free token. + */ + public static final byte[] XREF_FREE = "f".getBytes(); + /** + * The xref used token. + */ + public static final byte[] XREF_USED = "n".getBytes(); + /** + * The trailer token. + */ + public static final byte[] TRAILER = "trailer".getBytes(); + /** + * The start xref token. + */ + public static final byte[] STARTXREF = "startxref".getBytes(); + /** + * The starting object token. + */ + public static final byte[] OBJ = "obj".getBytes(); + /** + * The end object token. + */ + public static final byte[] ENDOBJ = "endobj".getBytes(); + /** + * The array open token. + */ + public static final byte[] ARRAY_OPEN = "[".getBytes(); + /** + * The array close token. + */ + public static final byte[] ARRAY_CLOSE = "]".getBytes(); + /** + * The open stream token. + */ + public static final byte[] STREAM = "stream".getBytes(); + /** + * The close stream token. + */ + public static final byte[] ENDSTREAM = "endstream".getBytes(); + + private NumberFormat formatXrefOffset = new DecimalFormat("0000000000"); + /** + * The decimal format for the xref object generation number data. + */ + private NumberFormat formatXrefGeneration = new DecimalFormat("00000"); + + private NumberFormat formatDecimal = NumberFormat.getNumberInstance( Locale.US ); + + // the stream where we create the pdf output + private OutputStream output; + // the stream used to write standard cos data + private COSStandardOutputStream standardOutput; + + // the start position of the x ref section + private long startxref = 0; + + // the current object number + private long number = 0; + + // maps the object to the keys generated in the writer + // these are used for indirect refrences in other objects + //A hashtable is used on purpose over a hashmap + //so that null entries will not get added. + private Map objectKeys = new Hashtable(); + + // the list of x ref entries to be made so far + private List xRefEntries = new ArrayList(); + + //A list of objects to write. + private List objectsToWrite = new ArrayList(); + + //a list of objects already written + private Set writtenObjects = new HashSet(); + //An 'actual' is any COSBase that is not a COSObject. + //need to keep a list of the actuals that are added + //as well as the objects because there is a problem + //when adding a COSObject and then later adding + //the actual for that object, so we will track + //actuals separately. + private Set actualsAdded = new HashSet(); + + private COSObjectKey currentObjectKey = null; + private PDDocument document = null; + private DocumentEncryption enc = null; + + /** + * COSWriter constructor comment. + * + * @param os The wrapped output stream. + */ + public COSWriter(OutputStream os) + { + super(); + setOutput(os); + setStandardOutput(new COSStandardOutputStream(getOutput())); + formatDecimal.setMaximumFractionDigits( 10 ); + formatDecimal.setGroupingUsed( false ); + } + /** + * add an entry in the x ref table for later dump. + * + * @param entry The new entry to add. + */ + protected void addXRefEntry(COSWriterXRefEntry entry) + { + getXRefEntries().add(entry); + } + + /** + * This will close the stream. + * + * @throws IOException If the underlying stream throws an exception. + */ + public void close() throws IOException + { + if (getStandardOutput() != null) + { + getStandardOutput().close(); + } + if (getOutput() != null) + { + getOutput().close(); + } + } + + /** + * This will get the current object number. + * + * @return The current object number. + */ + protected long getNumber() + { + return number; + } + + /** + * This will get all available object keys. + * + * @return A map of all object keys. + */ + public java.util.Map getObjectKeys() + { + return objectKeys; + } + + /** + * This will get the output stream. + * + * @return The output stream. + */ + protected java.io.OutputStream getOutput() + { + return output; + } + + /** + * This will get the standard output stream. + * + * @return The standard output stream. + */ + protected COSStandardOutputStream getStandardOutput() + { + return standardOutput; + } + + /** + * This will get the current start xref. + * + * @return The current start xref. + */ + protected long getStartxref() + { + return startxref; + } + /** + * This will get the xref entries. + * + * @return All available xref entries. + */ + protected java.util.List getXRefEntries() + { + return xRefEntries; + } + + /** + * This will set the current object number. + * + * @param newNumber The new object number. + */ + protected void setNumber(long newNumber) + { + number = newNumber; + } + + /** + * This will set the output stream. + * + * @param newOutput The new output stream. + */ + private void setOutput( OutputStream newOutput ) + { + output = newOutput; + } + + /** + * This will set the standard output stream. + * + * @param newStandardOutput The new standard output stream. + */ + private void setStandardOutput(COSStandardOutputStream newStandardOutput) + { + standardOutput = newStandardOutput; + } + + /** + * This will set the start xref. + * + * @param newStartxref The new start xref attribute. + */ + protected void setStartxref(long newStartxref) + { + startxref = newStartxref; + } + + /** + * This will write the body of the document. + * + * @param doc The document to write the body for. + * + * @throws IOException If there is an error writing the data. + * @throws COSVisitorException If there is an error generating the data. + */ + protected void doWriteBody(COSDocument doc) throws IOException, COSVisitorException + { + COSDictionary trailer = doc.getTrailer(); + COSDictionary root = (COSDictionary)trailer.getDictionaryObject( COSName.ROOT ); + COSDictionary info = (COSDictionary)trailer.getDictionaryObject( COSName.getPDFName( "Info" ) ); + COSDictionary encrypt = (COSDictionary)trailer.getDictionaryObject( COSName.getPDFName( "Encrypt" ) ); + if( root != null ) + { + addObjectToWrite( root ); + } + if( info != null ) + { + addObjectToWrite( info ); + } + + + while( objectsToWrite.size() > 0 ) + { + COSBase nextObject = (COSBase)objectsToWrite.remove( 0 ); + doWriteObject( nextObject ); + } + + document.clearWillEncryptWhenSaving(); + if( encrypt != null ) + { + addObjectToWrite( encrypt ); + } + + while( objectsToWrite.size() > 0 ) + { + COSBase nextObject = (COSBase)objectsToWrite.remove( 0 ); + doWriteObject( nextObject ); + } + + // write all objects + /** + for (Iterator i = doc.getObjects().iterator(); i.hasNext();) + { + COSObject obj = (COSObject) i.next(); + doWriteObject(obj); + }**/ + } + + private void addObjectToWrite( COSBase object ) + { + COSBase actual = object; + if( actual instanceof COSObject ) + { + actual = ((COSObject)actual).getObject(); + } + + if( !writtenObjects.contains( object ) && + !objectsToWrite.contains( object ) && + !actualsAdded.contains( actual ) ) + { + objectsToWrite.add( object ); + if( actual != null ) + { + actualsAdded.add( actual ); + } + } + } + + /** + * This will write a COS object. + * + * @param obj The object to write. + * + * @throws COSVisitorException If there is an error visiting objects. + */ + public void doWriteObject( COSBase obj ) throws COSVisitorException + { + try + { + writtenObjects.add( obj ); + // find the physical reference + currentObjectKey = getObjectKey( obj ); + // add a x ref entry + addXRefEntry( new COSWriterXRefEntry(getStandardOutput().getPos(), obj, currentObjectKey)); + // write the object + getStandardOutput().write(String.valueOf(currentObjectKey.getNumber()).getBytes()); + getStandardOutput().write(SPACE); + getStandardOutput().write(String.valueOf(currentObjectKey.getGeneration()).getBytes()); + getStandardOutput().write(SPACE); + getStandardOutput().write(OBJ); + getStandardOutput().writeEOL(); + obj.accept( this ); + getStandardOutput().writeEOL(); + getStandardOutput().write(ENDOBJ); + getStandardOutput().writeEOL(); + } + catch (IOException e) + { + throw new COSVisitorException(e); + } + } + + /** + * This will write the header to the PDF document. + * + * @param doc The document to get the data from. + * + * @throws IOException If there is an error writing to the stream. + */ + protected void doWriteHeader(COSDocument doc) throws IOException + { + getStandardOutput().write( doc.getHeaderString().getBytes() ); + getStandardOutput().writeEOL(); + getStandardOutput().write(COMMENT); + getStandardOutput().write(GARBAGE); + getStandardOutput().writeEOL(); + } + + + /** + * This will write the trailer to the PDF document. + * + * @param doc The document to create the trailer for. + * + * @throws IOException If there is an IOError while writing the document. + * @throws COSVisitorException If there is an error while generating the data. + */ + protected void doWriteTrailer(COSDocument doc) throws IOException, COSVisitorException + { + getStandardOutput().write(TRAILER); + getStandardOutput().writeEOL(); + + COSDictionary trailer = doc.getTrailer(); + //sort xref, needed only if object keys not regenerated + Collections.sort(getXRefEntries()); + COSWriterXRefEntry lastEntry = (COSWriterXRefEntry)getXRefEntries().get( getXRefEntries().size()-1); + trailer.setInt(COSName.getPDFName("Size"), (int)lastEntry.getKey().getNumber()+1); + trailer.removeItem( COSName.PREV ); + /** + COSObject catalog = doc.getCatalog(); + if (catalog != null) + { + trailer.setItem(COSName.getPDFName("Root"), catalog); + } + */ + trailer.accept(this); + + getStandardOutput().write(STARTXREF); + getStandardOutput().writeEOL(); + getStandardOutput().write(String.valueOf(getStartxref()).getBytes()); + getStandardOutput().writeEOL(); + getStandardOutput().write(EOF); + } + + /** + * write the x ref section for the pdf file + * + * currently, the pdf is reconstructed from the scratch, so we write a single section + * + * todo support for incremental writing? + * + * @param doc The document to write the xref from. + * + * @throws IOException If there is an error writing the data to the stream. + */ + protected void doWriteXRef(COSDocument doc) throws IOException + { + String offset; + String generation; + + // sort xref, needed only if object keys not regenerated + Collections.sort(getXRefEntries()); + COSWriterXRefEntry lastEntry = (COSWriterXRefEntry)getXRefEntries().get( getXRefEntries().size()-1 ); + + // remember the position where x ref is written + setStartxref(getStandardOutput().getPos()); + // + getStandardOutput().write(XREF); + getStandardOutput().writeEOL(); + // write start object number and object count for this x ref section + // we assume starting from scratch + getStandardOutput().write(String.valueOf(0).getBytes()); + getStandardOutput().write(SPACE); + getStandardOutput().write(String.valueOf(lastEntry.getKey().getNumber() + 1).getBytes()); + getStandardOutput().writeEOL(); + // write initial start object with ref to first deleted object and magic generation number + offset = formatXrefOffset.format(0); + generation = formatXrefGeneration.format(65535); + getStandardOutput().write(offset.getBytes()); + getStandardOutput().write(SPACE); + getStandardOutput().write(generation.getBytes()); + getStandardOutput().write(SPACE); + getStandardOutput().write(XREF_FREE); + getStandardOutput().writeCRLF(); + // write entry for every object + long lastObjectNumber = 0; + for (Iterator i = getXRefEntries().iterator(); i.hasNext();) + { + COSWriterXRefEntry entry = (COSWriterXRefEntry) i.next(); + while( lastObjectNumber + + + + + +This is the persistence layer used to write the PDFBox documents to a stream. + + diff --git a/src/main/java/org/pdfbox/pdmodel/PDDestinationNameTreeNode.java b/src/main/java/org/pdfbox/pdmodel/PDDestinationNameTreeNode.java new file mode 100644 index 0000000..6c8956c --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/PDDestinationNameTreeNode.java @@ -0,0 +1,90 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel; + +import java.io.IOException; + +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.pdmodel.common.PDNameTreeNode; +import org.pdfbox.pdmodel.interactive.documentnavigation.destination.PDDestination; +import org.pdfbox.pdmodel.interactive.documentnavigation.destination.PDPageDestination; + +/** + * This class holds all of the name trees that are available at the document level. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.1 $ + */ +public class PDDestinationNameTreeNode extends PDNameTreeNode +{ + /** + * Constructor. + */ + public PDDestinationNameTreeNode() + { + super( PDPageDestination.class ); + } + + /** + * Constructor. + * + * @param dic The COS dictionary. + */ + public PDDestinationNameTreeNode( COSDictionary dic ) + { + super( dic, PDPageDestination.class ); + } + + /** + * @see PDNameTreeNode#convertCOSToPD( COSBase ) + */ + protected Object convertCOSToPD( COSBase base ) throws IOException + { + COSBase destination = base; + if( base instanceof COSDictionary ) + { + //the destination is sometimes stored in the D dictionary + //entry instead of being directly an array, so just dereference + //it for now + destination = ((COSDictionary)base).getDictionaryObject( "D" ); + } + return PDDestination.create( destination ); + } + + /** + * @see PDNameTreeNode#createChildNode( COSDictionary ) + */ + protected PDNameTreeNode createChildNode( COSDictionary dic ) + { + return new PDDestinationNameTreeNode(dic); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/PDDocument.java b/src/main/java/org/pdfbox/pdmodel/PDDocument.java new file mode 100644 index 0000000..94150fb --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/PDDocument.java @@ -0,0 +1,725 @@ +/** + * Copyright (c) 2003-2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel; + +import java.awt.print.PageFormat; +import java.awt.print.Pageable; +import java.awt.print.Paper; +import java.awt.print.Printable; +import java.awt.print.PrinterException; +import java.awt.print.PrinterIOException; +import java.awt.print.PrinterJob; +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.List; + +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSDocument; +import org.pdfbox.cos.COSInteger; +import org.pdfbox.cos.COSName; +import org.pdfbox.cos.COSStream; +import org.pdfbox.cos.COSString; + +import org.pdfbox.encryption.PDFEncryption; +import org.pdfbox.encryption.DocumentEncryption; + +import org.pdfbox.exceptions.COSVisitorException; +import org.pdfbox.exceptions.CryptographyException; +import org.pdfbox.exceptions.InvalidPasswordException; + +import org.pdfbox.pdfparser.PDFParser; + +import org.pdfbox.pdfwriter.COSWriter; + +import org.pdfbox.pdmodel.common.PDRectangle; +import org.pdfbox.pdmodel.common.PDStream; + +import org.pdfbox.pdmodel.encryption.PDEncryptionDictionary; +import org.pdfbox.pdmodel.encryption.PDEncryptionManager; +import org.pdfbox.pdmodel.encryption.PDStandardEncryption; + +/** + * This is the in-memory representation of the PDF document. You need to call + * close() on this object when you are done using it!! + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.35 $ + */ +public class PDDocument implements Pageable +{ + private COSDocument document; + private boolean encryptOnSave = false; + private String encryptUserPassword = null; + private String encryptOwnerPassword = null; + + //cached values + private PDDocumentInformation documentInformation; + private PDDocumentCatalog documentCatalog; + + //The encParameters will be cached here. When the document is decrypted then + //the COSDocument will not have an "Encrypt" dictionary anymore and this object + //must be used. + private PDEncryptionDictionary encParameters = null; + /** + * This will tell if the document was decrypted with the master password. + */ + private boolean decryptedWithOwnerPassword = false; + + /** + * Constructor, creates a new PDF Document with no pages. You need to add + * at least one page for the document to be valid. + * + * @throws IOException If there is an error creating this document. + */ + public PDDocument() throws IOException + { + document = new COSDocument(); + + //First we need a trailer + COSDictionary trailer = new COSDictionary(); + document.setTrailer( trailer ); + + //Next we need the root dictionary. + COSDictionary rootDictionary = new COSDictionary(); + trailer.setItem( COSName.ROOT, rootDictionary ); + rootDictionary.setItem( COSName.TYPE, COSName.CATALOG ); + rootDictionary.setItem( COSName.VERSION, COSName.getPDFName( "1.4" ) ); + + //next we need the pages tree structure + COSDictionary pages = new COSDictionary(); + rootDictionary.setItem( COSName.PAGES, pages ); + pages.setItem( COSName.TYPE, COSName.PAGES ); + COSArray kidsArray = new COSArray(); + pages.setItem( COSName.KIDS, kidsArray ); + pages.setItem( COSName.COUNT, new COSInteger( 0 ) ); + } + + /** + * This will add a page to the document. This is a convenience method, that + * will add the page to the root of the hierarchy and set the parent of the + * page to the root. + * + * @param page The page to add to the document. + */ + public void addPage( PDPage page ) + { + PDPageNode rootPages = getDocumentCatalog().getPages(); + rootPages.getKids().add( page ); + page.setParent( rootPages ); + rootPages.updateCount(); + } + + /** + * Remove the page from the document. + * + * @param page The page to remove from the document. + * + * @return true if the page was found false otherwise. + */ + public boolean removePage( PDPage page ) + { + PDPageNode parent = page.getParent(); + boolean retval = parent.getKids().remove( page ); + if( retval ) + { + //do a recursive updateCount starting at the root + //of the document + getDocumentCatalog().getPages().updateCount(); + } + return retval; + } + + /** + * Remove the page from the document. + * + * @param pageNumber 0 based index to page number. + * @return true if the page was found false otherwise. + */ + public boolean removePage( int pageNumber ) + { + boolean removed = false; + List allPages = getDocumentCatalog().getAllPages(); + if( allPages.size() > pageNumber) + { + PDPage page = (PDPage)allPages.get( pageNumber ); + removed = removePage( page ); + } + return removed; + } + + /** + * This will import and copy the contents from another location. Currently + * the content stream is stored in a scratch file. The scratch file is + * associated with the document. If you are adding a page to this document + * from another document and want to copy the contents to this document's + * scratch file then use this method otherwise just use the addPage method. + * + * @param page The page to import. + * @return The page that was imported. + * + * @throws IOException If there is an error copying the page. + */ + public PDPage importPage( PDPage page ) throws IOException + { + PDPage importedPage = new PDPage( new COSDictionary( page.getCOSDictionary() ) ); + InputStream is = null; + OutputStream os = null; + try + { + PDStream src = page.getContents(); + PDStream dest = new PDStream( new COSStream( src.getStream(), document.getScratchFile() ) ); + importedPage.setContents( dest ); + os = dest.createOutputStream(); + + byte[] buf = new byte[10240]; + int amountRead = 0; + is = src.createInputStream(); + while((amountRead = is.read(buf,0,10240)) > -1) + { + os.write(buf, 0, amountRead); + } + addPage( importedPage ); + } + finally + { + if( is != null ) + { + is.close(); + } + if( os != null ) + { + os.close(); + } + } + return importedPage; + + } + + /** + * Constructor that uses an existing document. The COSDocument that + * is passed in must be valid. + * + * @param doc The COSDocument that this document wraps. + */ + public PDDocument( COSDocument doc ) + { + document = doc; + } + + /** + * This will get the low level document. + * + * @return The document that this layer sits on top of. + */ + public COSDocument getDocument() + { + return document; + } + + /** + * This will get the document info dictionary. This is guaranteed to not return null. + * + * @return The documents /Info dictionary + */ + public PDDocumentInformation getDocumentInformation() + { + if( documentInformation == null ) + { + COSDictionary trailer = document.getTrailer(); + COSDictionary infoDic = (COSDictionary)trailer.getDictionaryObject( COSName.INFO ); + if( infoDic == null ) + { + infoDic = new COSDictionary(); + trailer.setItem( COSName.INFO, infoDic ); + } + documentInformation = new PDDocumentInformation( infoDic ); + } + return documentInformation; + } + + /** + * This will set the document information for this document. + * + * @param info The updated document information. + */ + public void setDocumentInformation( PDDocumentInformation info ) + { + documentInformation = info; + document.getTrailer().setItem( COSName.INFO, info.getDictionary() ); + } + + /** + * This will get the document CATALOG. This is guaranteed to not return null. + * + * @return The documents /Root dictionary + */ + public PDDocumentCatalog getDocumentCatalog() + { + if( documentCatalog == null ) + { + COSDictionary trailer = document.getTrailer(); + COSDictionary infoDic = (COSDictionary)trailer.getDictionaryObject( COSName.ROOT ); + if( infoDic == null ) + { + documentCatalog = new PDDocumentCatalog( this ); + } + else + { + documentCatalog = new PDDocumentCatalog( this, infoDic ); + } + + } + return documentCatalog; + } + + /** + * This will tell if this document is encrypted or not. + * + * @return true If this document is encrypted. + */ + public boolean isEncrypted() + { + return document.isEncrypted(); + } + + /** + * This will get the encryption dictionary for this document. This will still + * return the parameters if the document was decrypted. If the document was + * never encrypted then this will return null. As the encryption architecture + * in PDF documents is plugable this returns an abstract class, but the only + * supported subclass at this time is a PDStandardEncryption object. + * + * @return The encryption dictionary(most likely a PDStandardEncryption object) + * + * @throws IOException If there is an error determining which security handler to use. + */ + public PDEncryptionDictionary getEncryptionDictionary() throws IOException + { + if( encParameters == null ) + { + encParameters = PDEncryptionManager.getEncryptionDictionary( document.getEncryptionDictionary() ); + } + return encParameters; + } + + /** + * This will set the encryption dictionary for this document. + * + * @param encDictionary The encryption dictionary(most likely a PDStandardEncryption object) + * + * @throws IOException If there is an error determining which security handler to use. + */ + public void setEncryptionDictionary( PDEncryptionDictionary encDictionary ) throws IOException + { + encParameters = encDictionary; + } + + /** + * This will determine if this is the user password. This only applies when + * the document is encrypted and uses standard encryption. + * + * @param password The plain text user password. + * + * @return true If the password passed in matches the user password used to encrypt the document. + * + * @throws IOException If there is an error determining if it is the user password. + * @throws CryptographyException If there is an error in the encryption algorithms. + */ + public boolean isUserPassword( String password ) throws IOException, CryptographyException + { + boolean retval = false; + if( password == null ) + { + password = ""; + } + PDFEncryption encryptor = new PDFEncryption(); + PDEncryptionDictionary encryptionDictionary = getEncryptionDictionary(); + if( encryptionDictionary == null ) + { + throw new IOException( "Error: Document is not encrypted" ); + } + else + { + if( encryptionDictionary instanceof PDStandardEncryption ) + { + COSString documentID = (COSString)document.getDocumentID().get(0); + PDStandardEncryption standard = (PDStandardEncryption)encryptionDictionary; + retval = encryptor.isUserPassword( + password.getBytes(), + standard.getUserKey(), + standard.getOwnerKey(), + standard.getPermissions(), + documentID.getBytes(), + standard.getRevision(), + standard.getLength()/8 ); + } + else + { + throw new IOException( "Error: Encyption dictionary is not 'Standard'" + + encryptionDictionary.getClass().getName() ); + } + } + return retval; + } + + /** + * This will determine if this is the owner password. This only applies when + * the document is encrypted and uses standard encryption. + * + * @param password The plain text owner password. + * + * @return true If the password passed in matches the owner password used to encrypt the document. + * + * @throws IOException If there is an error determining if it is the user password. + * @throws CryptographyException If there is an error in the encryption algorithms. + */ + public boolean isOwnerPassword( String password ) throws IOException, CryptographyException + { + boolean retval = false; + if( password == null ) + { + password = ""; + } + PDFEncryption encryptor = new PDFEncryption(); + PDEncryptionDictionary encryptionDictionary = getEncryptionDictionary(); + if( encryptionDictionary == null ) + { + throw new IOException( "Error: Document is not encrypted" ); + } + else + { + if( encryptionDictionary instanceof PDStandardEncryption ) + { + COSString documentID = (COSString)document.getDocumentID().get( 0 ); + PDStandardEncryption standard = (PDStandardEncryption)encryptionDictionary; + retval = encryptor.isOwnerPassword( + password.getBytes(), + standard.getUserKey(), + standard.getOwnerKey(), + standard.getPermissions(), + documentID.getBytes(), + standard.getRevision(), + standard.getLength()/8 ); + } + else + { + throw new IOException( "Error: Encyption dictionary is not 'Standard'" + + encryptionDictionary.getClass().getName() ); + } + } + return retval; + } + + /** + * This will decrypt a document. + * + * @param password Either the user or owner password. + * + * @throws CryptographyException If there is an error decrypting the document. + * @throws IOException If there is an error getting the stream data. + * @throws InvalidPasswordException If the password is not a user or owner password. + */ + public void decrypt( String password ) throws CryptographyException, IOException, InvalidPasswordException + { + decryptedWithOwnerPassword = isOwnerPassword( password ); + DocumentEncryption decryptor = new DocumentEncryption( this ); + decryptor.decryptDocument( password ); + document.dereferenceObjectStreams(); + } + + /** + * This will tell if the document was decrypted with the master password. This + * entry is invalid if the PDF was not decrypted. + * + * @return true if the pdf was decrypted with the master password. + */ + public boolean wasDecryptedWithOwnerPassword() + { + return decryptedWithOwnerPassword; + } + + /** + * This will mark a document to be encrypted. The actual encryption + * will occur when the document is saved. + * + * @param ownerPassword The owner password to encrypt the document. + * @param userPassword The user password to encrypt the document. + * + * @throws CryptographyException If an error occurs during encryption. + * @throws IOException If there is an error accessing the data. + */ + public void encrypt( String ownerPassword, String userPassword ) + throws CryptographyException, IOException + { + encryptOnSave = true; + encryptOwnerPassword = ownerPassword; + encryptUserPassword = userPassword; + } + + + /** + * The owner password that was passed into the encrypt method. You should + * never use this method. This will not longer be valid once encryption + * has occured. + * + * @return The owner password passed to the encrypt method. + */ + public String getOwnerPasswordForEncryption() + { + return encryptOwnerPassword; + } + + /** + * The user password that was passed into the encrypt method. You should + * never use this method. This will not longer be valid once encryption + * has occured. + * + * @return The user password passed to the encrypt method. + */ + public String getUserPasswordForEncryption() + { + return encryptUserPassword; + } + + /** + * Internal method do determine if the document will be encrypted when it is saved. + * + * @return True if encrypt has been called and the document + * has not been saved yet. + */ + public boolean willEncryptWhenSaving() + { + return encryptOnSave; + } + + /** + * This shoule only be called by the COSWriter after encryption has completed. + * + */ + public void clearWillEncryptWhenSaving() + { + encryptOnSave = false; + } + + /** + * This will load a document from a file. + * + * @param filename The name of the file to load. + * + * @return The document that was loaded. + * + * @throws IOException If there is an error reading from the stream. + */ + public static PDDocument load( String filename ) throws IOException + { + return load( new BufferedInputStream( new FileInputStream( filename ) ) ); + } + + /** + * This will load a document from a file. + * + * @param file The name of the file to load. + * + * @return The document that was loaded. + * + * @throws IOException If there is an error reading from the stream. + */ + public static PDDocument load( File file ) throws IOException + { + return load( new BufferedInputStream( new FileInputStream( file ) ) ); + } + + /** + * This will load a document from an input stream. + * + * @param input The stream that contains the document. + * + * @return The document that was loaded. + * + * @throws IOException If there is an error reading from the stream. + */ + public static PDDocument load( InputStream input ) throws IOException + { + PDFParser parser = new PDFParser( input ); + parser.parse(); + return parser.getPDDocument(); + } + + /** + * This will save this document to the filesystem. + * + * @param fileName The file to save as. + * + * @throws IOException If there is an error saving the document. + * @throws COSVisitorException If an error occurs while generating the data. + */ + public void save( String fileName ) throws IOException, COSVisitorException + { + save( new FileOutputStream( fileName ) ); + } + + /** + * This will save the document to an output stream. + * + * @param output The stream to write to. + * + * @throws IOException If there is an error writing the document. + * @throws COSVisitorException If an error occurs while generating the data. + */ + public void save( OutputStream output ) throws IOException, COSVisitorException + { + //update the count in case any pages have been added behind the scenes. + getDocumentCatalog().getPages().updateCount(); + COSWriter writer = null; + try + { + writer = new COSWriter( output ); + writer.write( this ); + writer.close(); + } + finally + { + if( writer != null ) + { + writer.close(); + } + } + + } + + /** + * This will return the total page count of the PDF document. Note: This method + * is deprecated in favor of the getNumberOfPages method. The getNumberOfPages is + * a required interface method of the Pageable interface. This method will + * be removed in a future version of PDFBox!! + * + * @return The total number of pages in the PDF document. + * @deprecated Use the getNumberOfPages method instead! + */ + public int getPageCount() + { + return getNumberOfPages(); + } + + /** + * @see Pageable#getNumberOfPages() + */ + public int getNumberOfPages() + { + PDDocumentCatalog cat = getDocumentCatalog(); + return (int)cat.getPages().getCount(); + } + + /** + * @see Pageable#getPageFormat(int) + */ + public PageFormat getPageFormat(int pageIndex) + { + PDPage page = (PDPage)getDocumentCatalog().getAllPages().get( pageIndex ); + PDRectangle mediaBox = page.findMediaBox(); + PageFormat format = new PageFormat(); + Paper paper = new Paper(); + //hmm the imageable area might need to be the CropBox instead + //of the media box??? + paper.setImageableArea( 0,0,mediaBox.getWidth(),mediaBox.getHeight()); + paper.setSize( mediaBox.getWidth(), mediaBox.getHeight() ); + format.setPaper( paper ); + return format; + } + + /** + * @see Pageable#getPrintable(int) + */ + public Printable getPrintable(int pageIndex) + { + return (Printable)getDocumentCatalog().getAllPages().get( pageIndex ); + } + + /** + * This will send the PDF document to a printer. The printing functionality + * depends on the org.pdfbox.pdfviewer.PageDrawer functionality. The PageDrawer + * is a work in progress and some PDFs will print correctly and some will + * not. This is a convenience method to create the java.awt.print.PrinterJob. + * The PDDocument implements the java.awt.print.Pageable interface and + * PDPage implementes the java.awt.print.Printable interface, so advanced printing + * capabilities can be done by using those interfaces instead of this method. + * + * @throws PrinterException If there is an error while sending the PDF to + * the printer, or you do not have permissions to print this document. + */ + public void print() throws PrinterException + { + PDEncryptionDictionary encDictionary = null; + try + { + encDictionary = getEncryptionDictionary(); + } + catch( IOException io ) + { + throw new PrinterIOException( io ); + } + + //only care about standard encryption and if it was decrypted with the + //user password + if( encDictionary instanceof PDStandardEncryption && + !wasDecryptedWithOwnerPassword() ) + { + PDStandardEncryption stdEncryption = (PDStandardEncryption)encDictionary; + if( !stdEncryption.canPrint() ) + { + throw new PrinterException( "You do not have permission to print this document." ); + } + } + + PrinterJob printJob = PrinterJob.getPrinterJob(); + printJob.setPageable(this); + if( printJob.printDialog() ) + { + printJob.print(); + } + } + + /** + * This will close the underlying COSDocument object. + * + * @throws IOException If there is an error releasing resources. + */ + public void close() throws IOException + { + document.close(); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/PDDocumentCatalog.java b/src/main/java/org/pdfbox/pdmodel/PDDocumentCatalog.java new file mode 100644 index 0000000..552d404 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/PDDocumentCatalog.java @@ -0,0 +1,378 @@ +/** + * Copyright (c) 2003-2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel; + +import java.util.ArrayList; +import java.util.List; + +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSName; +import org.pdfbox.cos.COSStream; +import org.pdfbox.cos.COSString; + +import org.pdfbox.pdmodel.common.COSArrayList; +import org.pdfbox.pdmodel.common.COSObjectable; +import org.pdfbox.pdmodel.common.PDMetadata; +import org.pdfbox.pdmodel.documentinterchange.logicalstructure.PDMarkInfo; +import org.pdfbox.pdmodel.interactive.action.type.PDAction; +import org.pdfbox.pdmodel.interactive.action.PDActionFactory; +import org.pdfbox.pdmodel.interactive.action.PDDocumentCatalogAdditionalActions; +import org.pdfbox.pdmodel.interactive.documentnavigation.outline.PDDocumentOutline; +import org.pdfbox.pdmodel.interactive.form.PDAcroForm; + +import org.pdfbox.pdmodel.interactive.pagenavigation.PDThread; +import org.pdfbox.pdmodel.interactive.viewerpreferences.PDViewerPreferences; + +/** + * This class represents the acroform of a PDF document. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.16 $ + */ +public class PDDocumentCatalog implements COSObjectable +{ + private COSDictionary root; + private PDDocument document; + + private PDAcroForm acroForm = null; + + /** + * Constructor. + * + * @param doc The document that this catalog is part of. + */ + public PDDocumentCatalog( PDDocument doc ) + { + document = doc; + root = new COSDictionary(); + root.setItem( COSName.TYPE, new COSString( "Catalog" ) ); + document.getDocument().getTrailer().setItem( COSName.ROOT, root ); + } + + /** + * Constructor. + * + * @param doc The document that this catalog is part of. + * @param rootDictionary The root dictionary that this object wraps. + */ + public PDDocumentCatalog( PDDocument doc, COSDictionary rootDictionary ) + { + document = doc; + root = rootDictionary; + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSBase getCOSObject() + { + return root; + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSDictionary getCOSDictionary() + { + return root; + } + + /** + * This will get the documents acroform. This will return null if + * no acroform is part of the document. + * + * @return The documents acroform. + */ + public PDAcroForm getAcroForm() + { + if( acroForm == null ) + { + COSDictionary acroFormDic = + (COSDictionary)root.getDictionaryObject( COSName.ACRO_FORM ); + if( acroFormDic == null ) + { + acroForm = new PDAcroForm( document ); + root.setItem( COSName.ACRO_FORM, acroForm.getDictionary() ); + } + else + { + acroForm = new PDAcroForm( document, acroFormDic ); + } + } + return acroForm; + } + + /** + * This will get the root node for the pages. + * + * @return The parent page node. + */ + public PDPageNode getPages() + { + return new PDPageNode( (COSDictionary)root.getDictionaryObject( COSName.PAGES ) ); + } + + /** + * The PDF document contains a hierarchical structure of PDPageNode and PDPages, which + * is mostly just a way to store this information. This method will return a flat list + * of all PDPage objects in this document. + * + * @return A list of PDPage objects. + */ + public List getAllPages() + { + List retval = new ArrayList(); + PDPageNode rootNode = getPages(); + //old (slower): + //getPageObjects( rootNode, retval ); + rootNode.getAllKids(retval); + return retval; + } + + /** + * Get the viewer preferences associated with this document or null if they + * do not exist. + * + * @return The document's viewer preferences. + */ + public PDViewerPreferences getViewerPreferences() + { + PDViewerPreferences retval = null; + COSDictionary dict = (COSDictionary)root.getDictionaryObject( "ViewerPreferences" ); + if( dict != null ) + { + retval = new PDViewerPreferences( dict ); + } + + return retval; + } + + /** + * Set the viewer preferences. + * + * @param prefs The new viewer preferences. + */ + public void setViewerPreferences( PDViewerPreferences prefs ) + { + root.setItem( "ViewerPreferences", prefs ); + } + + /** + * Get the outline associated with this document or null if it + * does not exist. + * + * @return The document's outline. + */ + public PDDocumentOutline getDocumentOutline() + { + PDDocumentOutline retval = null; + COSDictionary dict = (COSDictionary)root.getDictionaryObject( "Outlines" ); + if( dict != null ) + { + retval = new PDDocumentOutline( dict ); + } + + return retval; + } + + /** + * Set the document outlines. + * + * @param outlines The new document outlines. + */ + public void setDocumentOutline( PDDocumentOutline outlines ) + { + root.setItem( "Outlines", outlines ); + } + + /** + * Get the list threads for this pdf document. + * + * @return A list of PDThread objects. + */ + public List getThreads() + { + COSArray array = (COSArray)root.getDictionaryObject( "Threads" ); + if( array == null ) + { + array = new COSArray(); + root.setItem( "Threads", array ); + } + List pdObjects = new ArrayList(); + for( int i=0; i= 0 ) + { + actual.remove( index ); + array.remove( index ); + } + else + { + retval = false; + } + return retval; + } + + /** + * @see List#containsAll( Collection ) + */ + public boolean containsAll(Collection c) + { + return actual.containsAll( c ); + } + + /** + * @see List#addAll( Collection ) + */ + public boolean addAll(Collection c) + { + //when adding if there is a parentDict then change the item + //in the dictionary from a single item to an array. + if( parentDict != null && c.size() > 0) + { + parentDict.setItem( dictKey, array ); + //clear the parent dict so it doesn't happen again, there might be + //a usecase for keeping the parentDict around but not now. + parentDict = null; + } + array.addAll( toCOSObjectList( c ) ); + return actual.addAll( c ); + } + + /** + * @see List#addAll( int, Collection ) + */ + public boolean addAll(int index, Collection c) + { + //when adding if there is a parentDict then change the item + //in the dictionary from a single item to an array. + if( parentDict != null && c.size() > 0) + { + parentDict.setItem( dictKey, array ); + //clear the parent dict so it doesn't happen again, there might be + //a usecase for keeping the parentDict around but not now. + parentDict = null; + } + + if( c.size() >0 && c.toArray()[0] instanceof DualCOSObjectable ) + { + array.addAll( index*2, toCOSObjectList( c ) ); + } + else + { + array.addAll( index, toCOSObjectList( c ) ); + } + return actual.addAll( index, c ); + } + + /** + * This will take an array of COSNumbers and return a COSArrayList of + * java.lang.Integer values. + * + * @param intArray The existing integer Array. + * + * @return A list that is part of the core Java collections. + */ + public static List convertIntegerCOSArrayToList( COSArray intArray ) + { + List numbers = new ArrayList(); + for( int i=0; i index && array.get( index ) instanceof DualCOSObjectable ) + { + //remove both objects + array.remove( index ); + array.remove( index ); + } + else + { + array.remove( index ); + } + return actual.remove( index ); + } + + /** + * @see List#indexOf( Object ) + */ + public int indexOf(Object o) + { + return actual.indexOf( o ); + } + + /** + * @see List#lastIndexOf( Object ) + */ + public int lastIndexOf(Object o) + { + return actual.indexOf( o ); + + } + + /** + * @see List#listIterator() + */ + public ListIterator listIterator() + { + return actual.listIterator(); + } + + /** + * @see List#listIterator( int ) + */ + public ListIterator listIterator(int index) + { + return actual.listIterator( index ); + } + + /** + * @see List#subList( int, int ) + */ + public List subList(int fromIndex, int toIndex) + { + return actual.subList( fromIndex, toIndex ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/common/COSDictionaryMap.java b/src/main/java/org/pdfbox/pdmodel/common/COSDictionaryMap.java new file mode 100644 index 0000000..ca3821d --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/common/COSDictionaryMap.java @@ -0,0 +1,278 @@ +/** + * Copyright (c) 2003-2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.common; + +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSBoolean; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSFloat; +import org.pdfbox.cos.COSInteger; +import org.pdfbox.cos.COSName; +import org.pdfbox.cos.COSString; + +import java.io.IOException; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +/** + * This is a Map that will automatically sync the contents to a COSDictionary. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.9 $ + */ +public class COSDictionaryMap implements Map +{ + private COSDictionary map; + private Map actuals; + + /** + * Constructor for this map. + * + * @param actualsMap The map with standard java objects as values. + * @param dicMap The map with COSBase objects as values. + */ + public COSDictionaryMap( Map actualsMap, COSDictionary dicMap ) + { + actuals = actualsMap; + map = dicMap; + } + + + /** + * @see java.util.Map#size() + */ + public int size() + { + return map.size(); + } + + /** + * @see java.util.Map#isEmpty() + */ + public boolean isEmpty() + { + return size() == 0; + } + + /** + * @see java.util.Map#containsKey() + */ + public boolean containsKey(Object key) + { + return map.keyList().contains( key ); + } + + /** + * @see java.util.Map#containsValue() + */ + public boolean containsValue(Object value) + { + return actuals.containsValue( value ); + } + + /** + * @see java.util.Map#get() + */ + public Object get(Object key) + { + return actuals.get( key ); + } + + /** + * @see java.util.Map#put() + */ + public Object put(Object key, Object value) + { + COSObjectable object = (COSObjectable)value; + + map.setItem( COSName.getPDFName( (String)key ), object.getCOSObject() ); + return actuals.put( key, value ); + } + + /** + * @see java.util.Map#remove() + */ + public Object remove(Object key) + { + map.removeItem( COSName.getPDFName( (String)key ) ); + return actuals.remove( key ); + } + + /** + * @see java.util.Map#putAll() + */ + public void putAll(Map t) + { + throw new RuntimeException( "Not yet implemented" ); + } + + /** + * @see java.util.Map#clear() + */ + public void clear() + { + map.clear(); + actuals.clear(); + } + + /** + * @see java.util.Map#keySet() + */ + public Set keySet() + { + return actuals.keySet(); + } + + /** + * @see java.util.Map#values() + */ + public Collection values() + { + return actuals.values(); + } + + /** + * @see java.util.Map#entrySet() + */ + public Set entrySet() + { + throw new RuntimeException( "Not yet implemented" ); + } + + /** + * @see java.util.Map#equals() + */ + public boolean equals(Object o) + { + boolean retval = false; + if( o instanceof COSDictionaryMap ) + { + COSDictionaryMap other = (COSDictionaryMap)o; + retval = other.map.equals( this.map ); + } + return retval; + } + + /** + * This will get a string representation of this map. + * + * @return A human readable form of this map. + */ + public String toString() + { + return actuals.toString(); + } + + /** + * @see java.util.Map#hashCode() + */ + public int hashCode() + { + return map.hashCode(); + } + + /** + * This will take a map<java.lang.String,org.pdfbox.pdmodel.COSObjectable> + * and convert it into a COSDictionary<COSName,COSBase>. + * + * @param someMap A map containing COSObjectables + * + * @return A proper COSDictionary + */ + public static COSDictionary convert( Map someMap ) + { + Iterator iter = someMap.keySet().iterator(); + COSDictionary dic = new COSDictionary(); + while( iter.hasNext() ) + { + String name = (String)iter.next(); + COSObjectable object = (COSObjectable)someMap.get( name ); + dic.setItem( COSName.getPDFName( name ), object.getCOSObject() ); + } + return dic; + } + + /** + * This will take a COS dictionary and convert it into COSDictionaryMap. All cos + * objects will be converted to their primitive form. + * + * @param map The COS mappings. + * @return A standard java map. + * @throws IOException If there is an error during the conversion. + */ + public static COSDictionaryMap convertBasicTypesToMap( COSDictionary map ) throws IOException + { + COSDictionaryMap retval = null; + if( map != null ) + { + Map actualMap = new HashMap(); + Iterator keyIter = map.keyList().iterator(); + while( keyIter.hasNext() ) + { + COSName key = (COSName)keyIter.next(); + COSBase cosObj = map.getDictionaryObject( key ); + Object actualObject = null; + if( cosObj instanceof COSString ) + { + actualObject = ((COSString)cosObj).getString(); + } + else if( cosObj instanceof COSInteger ) + { + actualObject = new Integer( ((COSInteger)cosObj).intValue() ); + } + else if( cosObj instanceof COSName ) + { + actualObject = ((COSName)cosObj).getName(); + } + else if( cosObj instanceof COSFloat ) + { + actualObject = new Float( ((COSInteger)cosObj).floatValue() ); + } + else if( cosObj instanceof COSBoolean ) + { + actualObject = ((COSBoolean)cosObj).getValue() ? Boolean.TRUE : Boolean.FALSE; + } + else + { + throw new IOException( "Error:unknown type of object to convert:" + cosObj ); + } + actualMap.put( key.getName(), actualObject ); + } + retval = new COSDictionaryMap( actualMap, map ); + } + + return retval; + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/common/COSObjectable.java b/src/main/java/org/pdfbox/pdmodel/common/COSObjectable.java new file mode 100644 index 0000000..5bf7bfc --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/common/COSObjectable.java @@ -0,0 +1,49 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.common; + +import org.pdfbox.cos.COSBase; + +/** + * This is an interface used to get/create the underlying COSObject. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.2 $ + */ +public interface COSObjectable +{ + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSBase getCOSObject(); +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/common/COSStreamArray.java b/src/main/java/org/pdfbox/pdmodel/common/COSStreamArray.java new file mode 100644 index 0000000..87dbb6a --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/common/COSStreamArray.java @@ -0,0 +1,304 @@ +/** + * Copyright (c) 2003-2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.common; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.RandomAccessFile; +import java.io.SequenceInputStream; + +import java.util.ArrayList; +import java.util.List; +import java.util.Vector; + +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSName; +import org.pdfbox.cos.COSStream; +import org.pdfbox.cos.ICOSVisitor; + +import org.pdfbox.exceptions.COSVisitorException; + +import org.pdfbox.pdfparser.PDFStreamParser; + +/** + * This will take an array of streams and sequence them together. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.7 $ + */ +public class COSStreamArray extends COSStream +{ + private COSArray streams; + + /** + * The first stream will be used to delegate some of the methods for this + * class. + */ + private COSStream firstStream; + + /** + * Constructor. + * + * @param array The array of COSStreams to concatenate together. + */ + public COSStreamArray( COSArray array ) + { + super( new COSDictionary(), null ); + streams = array; + if( array.size() > 0 ) + { + firstStream = (COSStream)array.getObject( 0 ); + } + } + /** + * This will get the scratch file associated with this stream. + * + * @return The scratch file where this stream is being stored. + */ + public RandomAccessFile getScratchFile() + { + return firstStream.getScratchFile(); + } + + /** + * This will get an object from this streams dictionary. + * + * @param key The key to the object. + * + * @return The dictionary object with the key or null if one does not exist. + */ + public COSBase getItem( COSName key ) + { + return firstStream.getItem( key ); + } + + /** + * This will get an object from this streams dictionary and dereference it + * if necessary. + * + * @param key The key to the object. + * + * @return The dictionary object with the key or null if one does not exist. + */ + public COSBase getDictionaryObject( COSName key ) + { + return firstStream.getDictionaryObject( key ); + } + + /** + * @see Object#toString() + */ + public String toString() + { + String result = "COSStream{}"; + return result; + } + + /** + * This will get all the tokens in the stream. + * + * @return All of the tokens in the stream. + * + * @throws IOException If there is an error parsing the stream. + */ + public List getStreamTokens() throws IOException + { + List retval = null; + if( streams.size() > 0 ) + { + PDFStreamParser parser = new PDFStreamParser( this ); + parser.parse(); + retval = parser.getTokens(); + } + else + { + retval = new ArrayList(); + } + return retval; + } + + /** + * This will get the dictionary that is associated with this stream. + * + * @return the object that is associated with this stream. + */ + public COSDictionary getDictionary() + { + return firstStream; + } + + /** + * This will get the stream with all of the filters applied. + * + * @return the bytes of the physical (endoced) stream + * + * @throws IOException when encoding/decoding causes an exception + */ + public InputStream getFilteredStream() throws IOException + { + throw new IOException( "Error: Not allowed to get filtered stream from array of streams." ); + /** + Vector inputStreams = new Vector(); + byte[] inbetweenStreamBytes = "\n".getBytes(); + + for( int i=0;i= 0 ) + { + retval = childNode.getValue( name ); + } + } + } + return retval; + } + + + /** + * This will return a map of names. The key will be a java.lang.String the value will + * depend on where this class is being used. + * + * @return A map of cos objects. + * + * @throws IOException If there is an error while creating the sub types. + */ + public Map getNames() throws IOException + { + Map names = null; + COSArray namesArray = (COSArray)node.getDictionaryObject( "Names" ); + if( namesArray != null ) + { + names = new HashMap(); + for( int i=0; i 0 ) + { + lower = (String)keys.get( 0 ); + upper = (String)keys.get( keys.size()-1 ); + } + setUpperLimit( upper ); + setLowerLimit( lower ); + node.setItem( "Names", array ); + } + } + + /** + * Get the highest value for a key in the name map. + * + * @return The highest value for a key in the map. + */ + public String getUpperLimit() + { + String retval = null; + COSArray arr = (COSArray)node.getDictionaryObject( "Limits" ); + if( arr != null ) + { + retval = arr.getString( 1 ); + } + return retval; + } + + /** + * Set the highest value for the key in the map. + * + * @param upper The new highest value for a key in the map. + */ + private void setUpperLimit( String upper ) + { + COSArray arr = (COSArray)node.getDictionaryObject( "Limits" ); + if( arr == null ) + { + arr = new COSArray(); + arr.add( null ); + arr.add( null ); + } + arr.setString( 1, upper ); + } + + /** + * Get the lowest value for a key in the name map. + * + * @return The lowest value for a key in the map. + */ + public String getLowerLimit() + { + String retval = null; + COSArray arr = (COSArray)node.getDictionaryObject( "Limits" ); + if( arr != null ) + { + retval = arr.getString( 0 ); + } + return retval; + } + + /** + * Set the lowest value for the key in the map. + * + * @param lower The new lowest value for a key in the map. + */ + private void setLowerLimit( String lower ) + { + COSArray arr = (COSArray)node.getDictionaryObject( "Limits" ); + if( arr == null ) + { + arr = new COSArray(); + arr.add( null ); + arr.add( null ); + } + arr.setString( 0, lower ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/common/PDNamedTextStream.java b/src/main/java/org/pdfbox/pdmodel/common/PDNamedTextStream.java new file mode 100644 index 0000000..2321683 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/common/PDNamedTextStream.java @@ -0,0 +1,137 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.common; + +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSName; + +/** + * A named text stream is a combination of a name and a PDTextStream object. This + * is used in name trees. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.2 $ + */ +public class PDNamedTextStream implements DualCOSObjectable +{ + private COSName streamName; + private PDTextStream stream; + + /** + * Constructor. + */ + public PDNamedTextStream() + { + //default constructor + } + + /** + * Constructor. + * + * @param name The name of the stream. + * @param str The stream. + */ + public PDNamedTextStream( COSName name, COSBase str ) + { + streamName = name; + stream = PDTextStream.createTextStream( str ); + } + + /** + * The name of the named text stream. + * + * @return The stream name. + */ + public String getName() + { + String name = null; + if( streamName != null ) + { + name = streamName.getName(); + } + return name; + } + + /** + * This will set the name of the named text stream. + * + * @param name The name of the named text stream. + */ + public void setName( String name ) + { + streamName = COSName.getPDFName( name ); + } + + /** + * This will get the stream. + * + * @return The stream associated with this name. + */ + public PDTextStream getStream() + { + return stream; + } + + /** + * This will set the stream. + * + * @param str The stream associated with this name. + */ + public void setStream( PDTextStream str ) + { + stream = str; + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSBase getFirstCOSObject() + { + return streamName; + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSBase getSecondCOSObject() + { + COSBase retval = null; + if( stream != null ) + { + retval = stream.getCOSObject(); + } + return retval; + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/common/PDObjectStream.java b/src/main/java/org/pdfbox/pdmodel/common/PDObjectStream.java new file mode 100644 index 0000000..3d31c1a --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/common/PDObjectStream.java @@ -0,0 +1,151 @@ +/** + * Copyright (c) 2004-2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.common; + +import org.pdfbox.cos.COSStream; + +import org.pdfbox.pdmodel.PDDocument; + + + +/** + * A PDStream represents a stream in a PDF document. Streams are tied to a single + * PDF document. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.2 $ + */ +public class PDObjectStream extends PDStream +{ + + /** + * Constructor. + * + * @param str The stream parameter. + */ + public PDObjectStream( COSStream str ) + { + super( str ); + } + + /** + * This will create a new PDStream object. + * + * @param document The document that the stream will be part of. + * @return A new stream object. + */ + public static PDObjectStream createStream( PDDocument document ) + { + COSStream cosStream = new COSStream( document.getDocument().getScratchFile() ); + PDObjectStream strm = new PDObjectStream( cosStream ); + strm.getStream().setName( "Type", "ObjStm" ); + return strm; + } + + /** + * Get the type of this object, should always return "ObjStm". + * + * @return The type of this object. + */ + public String getType() + { + return getStream().getNameAsString( "Type" ); + } + + /** + * Get the number of compressed object. + * + * @return The number of compressed objects. + */ + public int getNumberOfObjects() + { + return getStream().getInt( "N", 0 ); + } + + /** + * Set the number of objects. + * + * @param n The new number of objects. + */ + public void setNumberOfObjects( int n ) + { + getStream().setInt( "N", n ); + } + + /** + * The byte offset (in the decoded stream) of the first compressed object. + * + * @return The byte offset to the first object. + */ + public int getFirstByteOffset() + { + return getStream().getInt( "First", 0 ); + } + + /** + * The byte offset (in the decoded stream) of the first compressed object. + * + * @param n The byte offset to the first object. + */ + public void setFirstByteOffset( int n ) + { + getStream().setInt( "First", n ); + } + + /** + * A reference to an object stream, of which the current object stream is + * considered an extension. + * + * @return The object that this stream is an extension. + */ + public PDObjectStream getExtends() + { + PDObjectStream retval = null; + COSStream stream = (COSStream)getStream().getDictionaryObject( "Extends" ); + if( stream != null ) + { + retval = new PDObjectStream( stream ); + } + return retval; + + } + + /** + * A reference to an object stream, of which the current object stream is + * considered an extension. + * + * @param stream The object stream extension. + */ + public void setExtends( PDObjectStream stream ) + { + getStream().setItem( "Extends", stream ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/common/PDRange.java b/src/main/java/org/pdfbox/pdmodel/common/PDRange.java new file mode 100644 index 0000000..2493d87 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/common/PDRange.java @@ -0,0 +1,146 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.common; + +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSFloat; +import org.pdfbox.cos.COSNumber; + +/** + * This class will be used to signify a range. a(min) <= a* <= a(max) + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.2 $ + */ +public class PDRange implements COSObjectable +{ + private COSArray rangeArray; + private int startingIndex; + + /** + * Constructor with an initial range of 0..1. + */ + public PDRange() + { + rangeArray = new COSArray(); + rangeArray.add( new COSFloat( 0.0f ) ); + rangeArray.add( new COSFloat( 1.0f ) ); + startingIndex = 0; + } + + /** + * Constructor assumes a starting index of 0. + * + * @param range The array that describes the range. + */ + public PDRange( COSArray range ) + { + rangeArray = range; + } + + /** + * Constructor with an index into an array. Because some arrays specify + * multiple ranges ie [ 0,1, 0,2, 2,3 ] It is convenient for this + * class to take an index into an array. So if you want this range to + * represent 0,2 in the above example then you would say new PDRange( array, 2 ). + * + * @param range The array that describes the index + * @param index The index into the array for the start of the range. + */ + public PDRange( COSArray range, int index ) + { + rangeArray = range; + startingIndex = index; + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSBase getCOSObject() + { + return rangeArray; + } + + /** + * This will get the underlying array value. + * + * @return The cos object that this object wraps. + */ + public COSArray getCOSArray() + { + return rangeArray; + } + + /** + * This will get the minimum value of the range. + * + * @return The min value. + */ + public float getMin() + { + COSNumber min = (COSNumber)rangeArray.getObject( startingIndex ); + return min.floatValue(); + } + + /** + * This will set the minimum value for the range. + * + * @param min The new minimum for the range. + */ + public void setMin( float min ) + { + rangeArray.set( startingIndex, new COSFloat( min ) ); + } + + /** + * This will get the maximum value of the range. + * + * @return The max value. + */ + public float getMax() + { + COSNumber max = (COSNumber)rangeArray.getObject( startingIndex+1 ); + return max.floatValue(); + } + + /** + * This will set the maximum value for the range. + * + * @param max The new maximum for the range. + */ + public void setMax( float max ) + { + rangeArray.set( startingIndex+1, new COSFloat( max ) ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/common/PDRectangle.java b/src/main/java/org/pdfbox/pdmodel/common/PDRectangle.java new file mode 100644 index 0000000..b9f3267 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/common/PDRectangle.java @@ -0,0 +1,295 @@ +/** + * Copyright (c) 2003-2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.common; + +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSFloat; +import org.pdfbox.cos.COSNumber; + +import org.pdfbox.util.BoundingBox; + +import java.awt.Dimension; + +/** + * This represents a rectangle in a PDF document. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.10 $ + */ +public class PDRectangle implements COSObjectable +{ + private COSArray rectArray; + + /** + * Constructor. + * + * Initializes to 0,0,0,0 + */ + public PDRectangle() + { + rectArray = new COSArray(); + rectArray.add( new COSFloat( 0.0f ) ); + rectArray.add( new COSFloat( 0.0f ) ); + rectArray.add( new COSFloat( 0.0f ) ); + rectArray.add( new COSFloat( 0.0f ) ); + } + + /** + * Constructor. + * + * @param width The width of the rectangle. + * @param height The height of the rectangle. + */ + public PDRectangle( float width, float height ) + { + rectArray = new COSArray(); + rectArray.add( new COSFloat( 0.0f ) ); + rectArray.add( new COSFloat( 0.0f ) ); + rectArray.add( new COSFloat( width ) ); + rectArray.add( new COSFloat( height ) ); + } + + /** + * Constructor. + * + * @param box The non PD bouding box. + */ + public PDRectangle( BoundingBox box ) + { + rectArray = new COSArray(); + rectArray.add( new COSFloat( box.getLowerLeftX() ) ); + rectArray.add( new COSFloat( box.getLowerLeftY() ) ); + rectArray.add( new COSFloat( box.getUpperRightX() ) ); + rectArray.add( new COSFloat( box.getUpperRightY() ) ); + } + + /** + * Constructor. + * + * @param array An array of numbers as specified in the PDF Reference for a rectangle type. + */ + public PDRectangle( COSArray array ) + { + rectArray = array; + } + + /** + * Method to determine if the x/y point is inside this rectangle. + * @param x The x-coordinate to test. + * @param y The y-coordinate to test. + * @return True if the point is inside this rectangle. + */ + public boolean contains( float x, float y ) + { + float llx = getLowerLeftX(); + float urx = getUpperRightX(); + float lly = getLowerLeftY(); + float ury = getUpperRightY(); + return x >= llx && x <= urx && + y >= lly && y <= ury; + } + + /** + * This will create a translated rectangle based off of this rectangle, such + * that the new rectangle retains the same dimensions(height/width), but the + * lower left x,y values are zero.
+ * 100, 100, 400, 400 (llx, lly, urx, ury )
+ * will be translated to 0,0,300,300 + * + * @return A new rectangle that has been translated back to the origin. + */ + public PDRectangle createRetranslatedRectangle() + { + PDRectangle retval = new PDRectangle(); + retval.setUpperRightX( getWidth() ); + retval.setUpperRightY( getHeight() ); + return retval; + } + + /** + * This will get the underlying array for this rectangle. + * + * @return The cos array. + */ + public COSArray getCOSArray() + { + return rectArray; + } + + /** + * This will get the lower left x coordinate. + * + * @return The lower left x. + */ + public float getLowerLeftX() + { + return ((COSNumber)rectArray.get(0)).floatValue(); + } + + /** + * This will set the lower left x coordinate. + * + * @param value The lower left x. + */ + public void setLowerLeftX(float value) + { + rectArray.set(0, new COSFloat( value ) ); + } + + /** + * This will get the lower left y coordinate. + * + * @return The lower left y. + */ + public float getLowerLeftY() + { + return ((COSNumber)rectArray.get(1)).floatValue(); + } + + /** + * This will set the lower left y coordinate. + * + * @param value The lower left y. + */ + public void setLowerLeftY(float value) + { + rectArray.set(1, new COSFloat( value ) ); + } + + /** + * This will get the upper right x coordinate. + * + * @return The upper right x . + */ + public float getUpperRightX() + { + return ((COSNumber)rectArray.get(2)).floatValue(); + } + + /** + * This will set the upper right x coordinate. + * + * @param value The upper right x . + */ + public void setUpperRightX(float value) + { + rectArray.set(2, new COSFloat( value ) ); + } + + /** + * This will get the upper right y coordinate. + * + * @return The upper right y. + */ + public float getUpperRightY() + { + return ((COSNumber)rectArray.get(3)).floatValue(); + } + + /** + * This will set the upper right y coordinate. + * + * @param value The upper right y. + */ + public void setUpperRightY(float value) + { + rectArray.set(3, new COSFloat( value ) ); + } + + /** + * This will get the width of this rectangle as calculated by + * upperRightX - lowerLeftX. + * + * @return The width of this rectangle. + */ + public float getWidth() + { + return getUpperRightX() - getLowerLeftX(); + } + + /** + * This will get the height of this rectangle as calculated by + * upperRightY - lowerLeftY. + * + * @return The height of this rectangle. + */ + public float getHeight() + { + return getUpperRightY() - getLowerLeftY(); + } + + /** + * A convenience method to create a dimension object for AWT operations. + * + * @return A dimension that matches the width and height of this rectangle. + */ + public Dimension createDimension() + { + return new Dimension( (int)getWidth(), (int)getHeight() ); + } + + /** + * This will move the rectangle the given relative amount. + * + * @param horizontalAmount positive values will move rectangle to the right, negative's to the left. + * @param verticalAmount positive values will move the rectangle up, negative's down. + */ + public void move(float horizontalAmount, float verticalAmount) + { + setUpperRightX(getUpperRightX() + horizontalAmount); + setLowerLeftX(getLowerLeftX() + horizontalAmount); + setUpperRightY(getUpperRightY() + verticalAmount); + setLowerLeftY(getLowerLeftY() + verticalAmount); + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSBase getCOSObject() + { + return rectArray; + } + + + /** + * This will return a string representation of this rectangle. + * + * @return This object as a string. + */ + public String toString() + { + return "[" + getLowerLeftX() + "," + getLowerLeftY() + "," + + getUpperRightX() + "," + getUpperRightY() +"]"; + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/common/PDStream.java b/src/main/java/org/pdfbox/pdmodel/common/PDStream.java new file mode 100644 index 0000000..74398b2 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/common/PDStream.java @@ -0,0 +1,538 @@ +/** + * Copyright (c) 2004-2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.common; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSName; +import org.pdfbox.cos.COSStream; + +import org.pdfbox.filter.Filter; +import org.pdfbox.filter.FilterManager; + +import org.pdfbox.pdmodel.PDDocument; + +import org.pdfbox.pdmodel.common.filespecification.PDFileSpecification; + +/** + * A PDStream represents a stream in a PDF document. Streams are tied to a single + * PDF document. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.14 $ + */ +public class PDStream implements COSObjectable +{ + private COSStream stream; + + /** + * This will create a new PDStream object. + */ + protected PDStream() + { + //should only be called by PDMemoryStream + } + + /** + * This will create a new PDStream object. + * + * @param document The document that the stream will be part of. + */ + public PDStream( PDDocument document ) + { + stream = new COSStream( document.getDocument().getScratchFile() ); + } + + /** + * Constructor. + * + * @param str The stream parameter. + */ + public PDStream( COSStream str ) + { + stream = str; + } + + /** + * Constructor. Reads all data from the input stream and embeds it into the + * document, this will close the InputStream. + * + * @param doc The document that will hold the stream. + * @param str The stream parameter. + * @throws IOException If there is an error creating the stream in the document. + */ + public PDStream( PDDocument doc, InputStream str ) throws IOException + { + this( doc, str, false ); + } + + /** + * Constructor. Reads all data from the input stream and embeds it into the + * document, this will close the InputStream. + * + * @param doc The document that will hold the stream. + * @param str The stream parameter. + * @param filtered True if the stream already has a filter applied. + * @throws IOException If there is an error creating the stream in the document. + */ + public PDStream( PDDocument doc, InputStream str, boolean filtered ) throws IOException + { + OutputStream output = null; + try + { + stream = new COSStream( doc.getDocument().getScratchFile() ); + if( filtered ) + { + output = stream.createFilteredStream(); + } + else + { + output = stream.createUnfilteredStream(); + } + byte[] buffer = new byte[ 1024 ]; + int amountRead = -1; + while( (amountRead = str.read(buffer)) != -1 ) + { + output.write( buffer, 0, amountRead ); + } + } + finally + { + if( output != null ) + { + output.close(); + } + if( str != null ) + { + str.close(); + } + } + } + + /** + * If there are not compression filters on the current stream then this + * will add a compression filter, flate compression for example. + */ + public void addCompression() + { + List filters = getFilters(); + if( filters == null ) + { + filters = new ArrayList(); + filters.add( COSName.FLATE_DECODE ); + setFilters( filters ); + } + } + + /** + * Create a pd stream from either a regular COSStream on a COSArray of cos streams. + * @param base Either a COSStream or COSArray. + * @return A PDStream or null if base is null. + * @throws IOException If there is an error creating the PDStream. + */ + public static PDStream createFromCOS( COSBase base ) throws IOException + { + PDStream retval = null; + if( base instanceof COSStream ) + { + retval = new PDStream( (COSStream)base ); + } + else if( base instanceof COSArray ) + { + retval = new PDStream( new COSStreamArray( (COSArray)base ) ); + } + else + { + if( base != null ) + { + throw new IOException( "Contents are unknown type:" + base.getClass().getName() ); + } + } + return retval; + } + + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSBase getCOSObject() + { + return stream; + } + + /** + * This will get a stream that can be written to. + * + * @return An output stream to write data to. + * + * @throws IOException If an IO error occurs during writing. + */ + public OutputStream createOutputStream() throws IOException + { + return stream.createUnfilteredStream(); + } + + /** + * This will get a stream that can be read from. + * + * @return An input stream that can be read from. + * + * @throws IOException If an IO error occurs during reading. + */ + public InputStream createInputStream() throws IOException + { + return stream.getUnfilteredStream(); + } + + /** + * This will get a stream with some filters applied but not others. This is useful + * when doing images, ie filters = [flate,dct], we want to remove flate but leave dct + * + * @param stopFilters A list of filters to stop decoding at. + * @return A stream with decoded data. + * @throws IOException If there is an error processing the stream. + */ + public InputStream getPartiallyFilteredStream( List stopFilters ) throws IOException + { + FilterManager manager = stream.getFilterManager(); + InputStream is = stream.getFilteredStream(); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + List filters = getFilters(); + Iterator iter = filters.iterator(); + String nextFilter = null; + boolean done = false; + while( iter.hasNext() && !done ) + { + os.reset(); + nextFilter = (String)iter.next(); + if( stopFilters.contains( nextFilter ) ) + { + done = true; + } + else + { + Filter filter = manager.getFilter( COSName.getPDFName(nextFilter) ); + filter.decode( is, os, stream ); + is = new ByteArrayInputStream( os.toByteArray() ); + } + } + return is; + } + + /** + * Get the cos stream associated with this object. + * + * @return The cos object that matches this Java object. + */ + public COSStream getStream() + { + return stream; + } + + /** + * This will get the length of the filtered/compressed stream. This is readonly in the + * PD Model and will be managed by this class. + * + * @return The length of the filtered stream. + */ + public int getLength() + { + return stream.getInt( "Length", 0 ); + } + + /** + * This will get the list of filters that are associated with this stream. Or + * null if there are none. + * @return A list of all encoding filters to apply to this stream. + */ + public List getFilters() + { + List retval = null; + COSBase filters = stream.getFilters(); + if( filters instanceof COSName ) + { + COSName name = (COSName)filters; + retval = new COSArrayList( name.getName(), name, stream, "Filter" ); + } + else if( filters instanceof COSArray ) + { + retval = COSArrayList.convertCOSNameCOSArrayToList( (COSArray)filters ); + } + return retval; + } + + /** + * This will set the filters that are part of this stream. + * + * @param filters The filters that are part of this stream. + */ + public void setFilters( List filters ) + { + COSBase obj = COSArrayList.convertStringListToCOSNameCOSArray( filters ); + stream.setItem( "Filter", obj ); + } + + /** + * Get the list of decode parameters. Each entry in the list will refer to + * an entry in the filters list. + * + * @return The list of decode parameters. + * + * @throws IOException if there is an error retrieving the parameters. + */ + public List getDecodeParams() throws IOException + { + List retval = null; + + COSBase dp = stream.getDictionaryObject( "DecodeParms" ); + if( dp == null ) + { + //See PDF Ref 1.5 implementation note 7, the DP is sometimes used instead. + dp = stream.getDictionaryObject( "DP" ); + } + if( dp instanceof COSDictionary ) + { + Map map = COSDictionaryMap.convertBasicTypesToMap( (COSDictionary)dp ); + retval = new COSArrayList(map, dp, stream, "DecodeParams" ); + } + else if( dp instanceof COSArray ) + { + COSArray array = (COSArray)dp; + List actuals = new ArrayList(); + for( int i=0; i + + + + + +The file specification package defines classes that are used for the PDF File Specification logic. + + diff --git a/src/main/java/org/pdfbox/pdmodel/common/package.html b/src/main/java/org/pdfbox/pdmodel/common/package.html new file mode 100644 index 0000000..9d81599 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/common/package.html @@ -0,0 +1,9 @@ + + + + + + +High level PD classes that are used throughout several packages are placed in the PDModel common package. + + diff --git a/src/main/java/org/pdfbox/pdmodel/documentinterchange/logicalstructure/PDMarkInfo.java b/src/main/java/org/pdfbox/pdmodel/documentinterchange/logicalstructure/PDMarkInfo.java new file mode 100644 index 0000000..47a8ff3 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/documentinterchange/logicalstructure/PDMarkInfo.java @@ -0,0 +1,149 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.documentinterchange.logicalstructure; + +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.pdmodel.common.COSObjectable; + +/** + * The MarkInfo provides additional information relevant to specialized + * uses of structured documents. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.3 $ + */ +public class PDMarkInfo implements COSObjectable +{ + private COSDictionary dictionary; + + /** + * Default Constructor. + * + */ + public PDMarkInfo() + { + dictionary = new COSDictionary(); + } + + /** + * Constructor for an existing MarkInfo element. + * + * @param dic The existing dictionary. + */ + public PDMarkInfo( COSDictionary dic ) + { + dictionary = dic; + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSBase getCOSObject() + { + return dictionary; + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSDictionary getDictionary() + { + return dictionary; + } + + /** + * Tells if this is a tagged PDF. + * + * @return true If this is a tagged PDF. + */ + public boolean isMarked() + { + return dictionary.getBoolean( "Marked", false ); + } + + /** + * Set if this is a tagged PDF. + * + * @param value The new marked value. + */ + public void setMarked( boolean value ) + { + dictionary.setBoolean( "Marked", value ); + } + + /** + * Tells if structure elements use user properties. + * + * @return A boolean telling if the structure elements use user properties. + */ + public boolean usesUserProperties() + { + return dictionary.getBoolean( "UserProperties", false ); + } + + /** + * Set if the structure elements contain user properties. + * + * @param userProps The new value for this property. + */ + public void setUserProperties( boolean userProps ) + { + dictionary.setBoolean( "UserProperties", userProps ); + } + + /** + * Tells if this PDF contain 'suspect' tags. See PDF Reference 1.6 + * section 10.6 "Logical Structure" for more information about this property. + * + * @return true if the suspect flag has been set. + */ + public boolean isSuspect() + { + return dictionary.getBoolean( "Suspects", false ); + } + + /** + * Set the value of the suspects property. See PDF Reference 1.6 + * section 10.6 "Logical Structure" for more information about this + * property. + * + * @param suspect The new "Suspects" value. + */ + public void setSuspect( boolean suspect ) + { + dictionary.setBoolean( "Suspects", false ); + } +} diff --git a/src/main/java/org/pdfbox/pdmodel/documentinterchange/logicalstructure/PDStructureElement.java b/src/main/java/org/pdfbox/pdmodel/documentinterchange/logicalstructure/PDStructureElement.java new file mode 100644 index 0000000..9760b1b --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/documentinterchange/logicalstructure/PDStructureElement.java @@ -0,0 +1,76 @@ +/** + * Copyright (c) 2003-2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.documentinterchange.logicalstructure; + +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.pdmodel.common.COSObjectable; + +/** + * A structure element. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.1 $ + */ +public class PDStructureElement implements COSObjectable +{ + private COSDictionary dictionary; + + /** + * Default Constructor. + * + */ + public PDStructureElement() + { + dictionary = new COSDictionary(); + } + + /** + * Constructor for an existing structure element. + * + * @param dic The existing dictionary. + */ + public PDStructureElement( COSDictionary dic ) + { + dictionary = dic; + } + + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSBase getCOSObject() + { + return dictionary; + } +} diff --git a/src/main/java/org/pdfbox/pdmodel/documentinterchange/logicalstructure/package.html b/src/main/java/org/pdfbox/pdmodel/documentinterchange/logicalstructure/package.html new file mode 100644 index 0000000..7039586 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/documentinterchange/logicalstructure/package.html @@ -0,0 +1,10 @@ + + + + + + +The logical structure package provides a mechanism for incorporating +structural information about a document's content into a PDF file. + + diff --git a/src/main/java/org/pdfbox/pdmodel/documentinterchange/prepress/PDBoxStyle.java b/src/main/java/org/pdfbox/pdmodel/documentinterchange/prepress/PDBoxStyle.java new file mode 100644 index 0000000..4f092ef --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/documentinterchange/prepress/PDBoxStyle.java @@ -0,0 +1,222 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.documentinterchange.prepress; + +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSInteger; +import org.pdfbox.pdmodel.common.COSObjectable; +import org.pdfbox.pdmodel.graphics.PDLineDashPattern; +import org.pdfbox.pdmodel.graphics.color.PDColorSpaceInstance; +import org.pdfbox.pdmodel.graphics.color.PDDeviceRGB; + +/** + * The Box Style specifies visual characteristics for displaying box areas. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.2 $ + */ +public class PDBoxStyle implements COSObjectable +{ + /** + * Style for guideline. + */ + public static final String GUIDELINE_STYLE_SOLID = "S"; + /** + * Style for guideline. + */ + public static final String GUIDELINE_STYLE_DASHED = "D"; + + private COSDictionary dictionary; + + /** + * Default Constructor. + * + */ + public PDBoxStyle() + { + dictionary = new COSDictionary(); + } + + /** + * Constructor for an existing BoxStyle element. + * + * @param dic The existing dictionary. + */ + public PDBoxStyle( COSDictionary dic ) + { + dictionary = dic; + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSBase getCOSObject() + { + return dictionary; + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSDictionary getDictionary() + { + return dictionary; + } + + /** + * Get the color to be used for the guidelines. This is guaranteed to + * not return null. The color space will always be DeviceRGB and the + * default color is [0,0,0]. + * + *@return The guideline color. + */ + public PDColorSpaceInstance getGuidelineColor() + { + COSArray colorValues = (COSArray)dictionary.getDictionaryObject( "C" ); + if( colorValues == null ) + { + colorValues = new COSArray(); + colorValues.add( COSInteger.ZERO ); + colorValues.add( COSInteger.ZERO ); + colorValues.add( COSInteger.ZERO ); + dictionary.setItem( "C", colorValues ); + } + PDColorSpaceInstance instance = new PDColorSpaceInstance( colorValues ); + instance.setColorSpace( PDDeviceRGB.INSTANCE ); + return instance; + } + + /** + * Set the color space instance for this box style. This must be a + * PDDeviceRGB! + * + * @param color The new colorspace value. + */ + public void setGuideLineColor( PDColorSpaceInstance color ) + { + COSArray values = null; + if( color != null ) + { + values = color.getCOSColorSpaceValue(); + } + dictionary.setItem( "C", values ); + } + + /** + * Get the width of the of the guideline in default user space units. + * The default is 1. + * + * @return The width of the guideline. + */ + public float getGuidelineWidth() + { + return dictionary.getFloat( "W", 1 ); + } + + /** + * Set the guideline width. + * + * @param width The width in default user space units. + */ + public void setGuidelineWidth( float width ) + { + dictionary.setFloat( "W", width ); + } + + /** + * Get the style for the guideline. The default is "S" for solid. + * + * @return The guideline style. + * @see PDBoxStyle#GUIDELINE_STYLE_DASHED + * @see PDBoxStyle#GUIDELINE_STYLE_SOLID + */ + public String getGuidelineStyle() + { + return dictionary.getNameAsString( "S", GUIDELINE_STYLE_SOLID ); + } + + /** + * Set the style for the box. + * + * @param style The style for the box line. + * @see PDBoxStyle#GUIDELINE_STYLE_DASHED + * @see PDBoxStyle#GUIDELINE_STYLE_SOLID + */ + public void setGuidelineStyle( String style ) + { + dictionary.setName( "S", style ); + } + + /** + * Get the line dash pattern for this box style. This is guaranteed to not + * return null. The default is [3],0. + * + * @return The line dash pattern. + */ + public PDLineDashPattern getLineDashPattern() + { + PDLineDashPattern pattern = null; + COSArray d = (COSArray)dictionary.getDictionaryObject( "D" ); + if( d == null ) + { + d = new COSArray(); + d.add( new COSInteger(3) ); + dictionary.setItem( "D", d ); + } + COSArray lineArray = new COSArray(); + lineArray.add( d ); + //dash phase is not specified and assumed to be zero. + lineArray.add( new COSInteger( 0 ) ); + pattern = new PDLineDashPattern( lineArray ); + return pattern; + } + + /** + * Set the line dash pattern associated with this box style. + * + * @param pattern The patter for this box style. + */ + public void setLineDashPattern( PDLineDashPattern pattern ) + { + COSArray array = null; + if( pattern != null ) + { + array = pattern.getCOSDashPattern(); + } + dictionary.setItem( "D", array ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/documentinterchange/prepress/package.html b/src/main/java/org/pdfbox/pdmodel/documentinterchange/prepress/package.html new file mode 100644 index 0000000..8285a3f --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/documentinterchange/prepress/package.html @@ -0,0 +1,9 @@ + + + + + + +This package contains classes for prepress support in PDFBox. + + diff --git a/src/main/java/org/pdfbox/pdmodel/edit/PDPageContentStream.java b/src/main/java/org/pdfbox/pdmodel/edit/PDPageContentStream.java new file mode 100644 index 0000000..1e3b25f --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/edit/PDPageContentStream.java @@ -0,0 +1,648 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.edit; + +import java.awt.Color; +import java.awt.color.ColorSpace; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import java.text.NumberFormat; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.HashMap; + +import org.pdfbox.pdmodel.PDDocument; +import org.pdfbox.pdmodel.PDPage; +import org.pdfbox.pdmodel.PDResources; + +import org.pdfbox.pdmodel.common.COSStreamArray; +import org.pdfbox.pdmodel.common.PDStream; + +import org.pdfbox.pdmodel.font.PDFont; +import org.pdfbox.pdmodel.graphics.xobject.PDXObjectImage; + +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSName; +import org.pdfbox.cos.COSString; + + +/** + * This class will is a convenience for creating page content streams. You MUST + * call close() when you are finished with this object. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.14 $ + */ +public class PDPageContentStream +{ + private PDPage page; + private OutputStream output; + private boolean inTextMode = false; + private Map fontMappings = new HashMap(); + private Map imageMappings = new HashMap(); + private int fontNumber = 1; + private int imageNumber = 1; + private PDResources resources; + + //cached storage component for getting color values + private float[] colorComponents = new float[4]; + + private NumberFormat formatDecimal = NumberFormat.getNumberInstance( Locale.US ); + + private static final String BEGIN_TEXT = "BT\n"; + private static final String END_TEXT = "ET\n"; + private static final String SET_FONT = "Tf\n"; + private static final String MOVE_TEXT_POSITION = "Td\n"; + private static final String SHOW_TEXT = "Tj\n"; + + private static final String SAVE_GRAPHICS_STATE = "q\n"; + private static final String RESTORE_GRAPHICS_STATE = "Q\n"; + private static final String CONCATENATE_MATRIX = "cm\n"; + private static final String XOBJECT_DO = "Do\n"; + private static final String RG_STROKING = "RG\n"; + private static final String RG_NON_STROKING = "rg\n"; + private static final String K_STROKING = "K\n"; + private static final String K_NON_STROKING = "k\n"; + private static final String G_STROKING = "G\n"; + private static final String G_NON_STROKING = "g\n"; + private static final String APPEND_RECTANGLE = "re\n"; + private static final String FILL = "f\n"; + + + private static final int SPACE = 32; + + + /** + * Create a new PDPage content stream. + * + * @param document The document the page is part of. + * @param sourcePage The page to write the contents to. + * @throws IOException If there is an error writing to the page contents. + */ + public PDPageContentStream( PDDocument document, PDPage sourcePage ) throws IOException + { + this(document,sourcePage,false,true); + } + + /** + * Create a new PDPage content stream. + * + * @param document The document the page is part of. + * @param sourcePage The page to write the contents to. + * @param appendContent Indicates whether content will be overwritten. If false all previous content is deleted. + * @param compress Tell if the content stream should compress the page contents. + * @throws IOException If there is an error writing to the page contents. + */ + public PDPageContentStream( PDDocument document, PDPage sourcePage, boolean appendContent, boolean compress ) + throws IOException + { + page = sourcePage; + resources = page.getResources(); + if( resources == null ) + { + resources = new PDResources(); + page.setResources( resources ); + } + // If request specifies the need to append to the document + if(appendContent) + { + // Get the pdstream from the source page instead of creating a new one + PDStream contents = sourcePage.getContents(); + + // Create a pdstream to append new content + PDStream contentsToAppend = new PDStream( document ); + + // This will be the resulting COSStreamArray after existing and new streams are merged + COSStreamArray compoundStream = null; + + // If contents is already an array, a new stream is simply appended to it + if(contents.getStream() instanceof COSStreamArray) + { + compoundStream = (COSStreamArray)contents.getStream(); + compoundStream.appendStream( contentsToAppend.getStream()); + } + else + { + // Creates the COSStreamArray and adds the current stream plus a new one to it + COSArray newArray = new COSArray(); + newArray.add(contents.getCOSObject()); + newArray.add(contentsToAppend.getCOSObject()); + compoundStream = new COSStreamArray(newArray); + } + + if( compress ) + { + List filters = new ArrayList(); + filters.add( COSName.FLATE_DECODE ); + contentsToAppend.setFilters( filters ); + } + + // Sets the compoundStream as page contents + sourcePage.setContents( new PDStream(compoundStream) ); + output = contentsToAppend.createOutputStream(); + } + else + { + PDStream contents = new PDStream( document ); + if( compress ) + { + List filters = new ArrayList(); + filters.add( COSName.FLATE_DECODE ); + contents.setFilters( filters ); + } + sourcePage.setContents( contents ); + output = contents.createOutputStream(); + } + formatDecimal.setMaximumFractionDigits( 10 ); + formatDecimal.setGroupingUsed( false ); + } + + /** + * Begin some text operations. + * + * @throws IOException If there is an error writing to the stream or if you attempt to + * nest beginText calls. + */ + public void beginText() throws IOException + { + if( inTextMode ) + { + throw new IOException( "Error: Nested beginText() calls are not allowed." ); + } + appendRawCommands( BEGIN_TEXT ); + inTextMode = true; + } + + /** + * End some text operations. + * + * @throws IOException If there is an error writing to the stream or if you attempt to + * nest endText calls. + */ + public void endText() throws IOException + { + if( !inTextMode ) + { + throw new IOException( "Error: You must call beginText() before calling endText." ); + } + appendRawCommands( END_TEXT ); + inTextMode = false; + } + + /** + * Set the font to draw text with. + * + * @param font The font to use. + * @param fontSize The font size to draw the text. + * @throws IOException If there is an error writing the font information. + */ + public void setFont( PDFont font, float fontSize ) throws IOException + { + String fontMapping = (String)fontMappings.get( font ); + if( fontMapping == null ) + { + fontMapping = "F" + fontNumber++; + fontMappings.put( font, fontMapping ); + resources.getFonts().put( fontMapping, font ); + } + appendRawCommands( "/"); + appendRawCommands( fontMapping ); + appendRawCommands( SPACE ); + appendRawCommands( formatDecimal.format( fontSize ) ); + appendRawCommands( SPACE ); + appendRawCommands( SET_FONT ); + } + + /** + * Draw an image at the x,y coordinates, with the default size of the image. + * + * @param image The image to draw. + * @param x The x-coordinate to draw the image. + * @param y The y-coordinate to draw the image. + * + * @throws IOException If there is an error writing to the stream. + */ + public void drawImage( PDXObjectImage image, int x, int y ) throws IOException + { + drawImage( image, x, y, image.getWidth(), image.getHeight() ); + } + + /** + * Draw an image at the x,y coordinates and a certain width and height. + * + * @param image The image to draw. + * @param x The x-coordinate to draw the image. + * @param y The y-coordinate to draw the image. + * @param width The width of the image to draw. + * @param height The height of the image to draw. + * + * @throws IOException If there is an error writing to the stream. + */ + public void drawImage( PDXObjectImage image, int x, int y, int width, int height ) throws IOException + { + String imageMapping = (String)imageMappings.get( image ); + if( imageMapping == null ) + { + imageMapping = "Im" + imageNumber++; + imageMappings.put( image, imageMapping ); + resources.getImages().put( imageMapping, image ); + } + appendRawCommands( SAVE_GRAPHICS_STATE ); + appendRawCommands( formatDecimal.format( width ) ); + appendRawCommands( SPACE ); + appendRawCommands( formatDecimal.format( 0 ) ); + appendRawCommands( SPACE ); + appendRawCommands( formatDecimal.format( 0 ) ); + appendRawCommands( SPACE ); + appendRawCommands( formatDecimal.format( height ) ); + appendRawCommands( SPACE ); + appendRawCommands( formatDecimal.format( x ) ); + appendRawCommands( SPACE ); + appendRawCommands( formatDecimal.format( y ) ); + appendRawCommands( SPACE ); + appendRawCommands( CONCATENATE_MATRIX ); + appendRawCommands( SPACE ); + appendRawCommands( "/" ); + appendRawCommands( imageMapping ); + appendRawCommands( SPACE ); + appendRawCommands( XOBJECT_DO ); + appendRawCommands( SPACE ); + appendRawCommands( RESTORE_GRAPHICS_STATE ); + } + + /** + * The Td operator. + * @param x The x coordinate. + * @param y The y coordinate. + * @throws IOException If there is an error writing to the stream. + */ + public void moveTextPositionByAmount( float x, float y ) throws IOException + { + if( !inTextMode ) + { + throw new IOException( "Error: must call beginText() before moveTextPositionByAmount"); + } + appendRawCommands( formatDecimal.format( x ) ); + appendRawCommands( SPACE ); + appendRawCommands( formatDecimal.format( y ) ); + appendRawCommands( SPACE ); + appendRawCommands( MOVE_TEXT_POSITION ); + } + + /** + * This will draw a string at the current location on the screen. + * + * @param text The text to draw. + * @throws IOException If an io exception occurs. + */ + public void drawString( String text ) throws IOException + { + if( !inTextMode ) + { + throw new IOException( "Error: must call beginText() before drawString"); + } + COSString string = new COSString( text ); + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + string.writePDF( buffer ); + appendRawCommands( new String( buffer.toByteArray(), "ISO-8859-1")); + appendRawCommands( SPACE ); + appendRawCommands( SHOW_TEXT ); + } + + /** + * Set the stroking color, specified as RGB. + * + * @param color The color to set. + * @throws IOException If an IO error occurs while writing to the stream. + */ + public void setStrokingColor( Color color ) throws IOException + { + ColorSpace colorSpace = color.getColorSpace(); + if( colorSpace.getType() == ColorSpace.TYPE_RGB ) + { + setStrokingColor( color.getRed(), color.getGreen(), color.getBlue() ); + } + else if( colorSpace.getType() == ColorSpace.TYPE_GRAY ) + { + color.getColorComponents( colorComponents ); + setStrokingColor( colorComponents[0] ); + } + else if( colorSpace.getType() == ColorSpace.TYPE_CMYK ) + { + color.getColorComponents( colorComponents ); + setStrokingColor( colorComponents[0], colorComponents[2], colorComponents[2], colorComponents[3] ); + } + else + { + throw new IOException( "Error: unknown colorspace:" + colorSpace ); + } + } + + /** + * Set the non stroking color, specified as RGB. + * + * @param color The color to set. + * @throws IOException If an IO error occurs while writing to the stream. + */ + public void setNonStrokingColor( Color color ) throws IOException + { + ColorSpace colorSpace = color.getColorSpace(); + if( colorSpace.getType() == ColorSpace.TYPE_RGB ) + { + setNonStrokingColor( color.getRed(), color.getGreen(), color.getBlue() ); + } + else if( colorSpace.getType() == ColorSpace.TYPE_GRAY ) + { + color.getColorComponents( colorComponents ); + setNonStrokingColor( colorComponents[0] ); + } + else if( colorSpace.getType() == ColorSpace.TYPE_CMYK ) + { + color.getColorComponents( colorComponents ); + setNonStrokingColor( colorComponents[0], colorComponents[2], colorComponents[2], colorComponents[3] ); + } + else + { + throw new IOException( "Error: unknown colorspace:" + colorSpace ); + } + } + + /** + * Set the stroking color, specified as RGB, 0-255. + * + * @param r The red value. + * @param g The green value. + * @param b The blue value. + * @throws IOException If an IO error occurs while writing to the stream. + */ + public void setStrokingColor( int r, int g, int b ) throws IOException + { + appendRawCommands( formatDecimal.format( r/255d ) ); + appendRawCommands( SPACE ); + appendRawCommands( formatDecimal.format( g/255d ) ); + appendRawCommands( SPACE ); + appendRawCommands( formatDecimal.format( b/255d ) ); + appendRawCommands( SPACE ); + appendRawCommands( RG_STROKING ); + } + + /** + * Set the stroking color, specified as CMYK, 0-255. + * + * @param c The cyan value. + * @param m The magenta value. + * @param y The yellow value. + * @param k The black value. + * @throws IOException If an IO error occurs while writing to the stream. + */ + public void setStrokingColor( int c, int m, int y, int k) throws IOException + { + appendRawCommands( formatDecimal.format( c/255d ) ); + appendRawCommands( SPACE ); + appendRawCommands( formatDecimal.format( m/255d ) ); + appendRawCommands( SPACE ); + appendRawCommands( formatDecimal.format( y/255d ) ); + appendRawCommands( SPACE ); + appendRawCommands( formatDecimal.format( k/255d ) ); + appendRawCommands( SPACE ); + appendRawCommands( K_STROKING ); + } + + /** + * Set the stroking color, specified as CMYK, 0.0-1.0. + * + * @param c The cyan value. + * @param m The magenta value. + * @param y The yellow value. + * @param k The black value. + * @throws IOException If an IO error occurs while writing to the stream. + */ + public void setStrokingColor( double c, double m, double y, double k) throws IOException + { + appendRawCommands( formatDecimal.format( c ) ); + appendRawCommands( SPACE ); + appendRawCommands( formatDecimal.format( m ) ); + appendRawCommands( SPACE ); + appendRawCommands( formatDecimal.format( y ) ); + appendRawCommands( SPACE ); + appendRawCommands( formatDecimal.format( k ) ); + appendRawCommands( SPACE ); + appendRawCommands( K_STROKING ); + } + + /** + * Set the stroking color, specified as grayscale, 0-255. + * + * @param g The gray value. + * @throws IOException If an IO error occurs while writing to the stream. + */ + public void setStrokingColor( int g ) throws IOException + { + appendRawCommands( formatDecimal.format( g/255d ) ); + appendRawCommands( SPACE ); + appendRawCommands( G_STROKING ); + } + + /** + * Set the stroking color, specified as Grayscale 0.0-1.0. + * + * @param g The gray value. + * @throws IOException If an IO error occurs while writing to the stream. + */ + public void setStrokingColor( double g ) throws IOException + { + appendRawCommands( formatDecimal.format( g ) ); + appendRawCommands( SPACE ); + appendRawCommands( G_STROKING ); + } + + /** + * Set the non stroking color, specified as RGB, 0-255. + * + * @param r The red value. + * @param g The green value. + * @param b The blue value. + * @throws IOException If an IO error occurs while writing to the stream. + */ + public void setNonStrokingColor( int r, int g, int b ) throws IOException + { + appendRawCommands( formatDecimal.format( r/255d ) ); + appendRawCommands( SPACE ); + appendRawCommands( formatDecimal.format( g/255d ) ); + appendRawCommands( SPACE ); + appendRawCommands( formatDecimal.format( b/255d ) ); + appendRawCommands( SPACE ); + appendRawCommands( RG_NON_STROKING ); + } + + /** + * Set the non stroking color, specified as CMYK, 0-255. + * + * @param c The cyan value. + * @param m The magenta value. + * @param y The yellow value. + * @param k The black value. + * @throws IOException If an IO error occurs while writing to the stream. + */ + public void setNonStrokingColor( int c, int m, int y, int k) throws IOException + { + appendRawCommands( formatDecimal.format( c/255d ) ); + appendRawCommands( SPACE ); + appendRawCommands( formatDecimal.format( m/255d ) ); + appendRawCommands( SPACE ); + appendRawCommands( formatDecimal.format( y/255d ) ); + appendRawCommands( SPACE ); + appendRawCommands( formatDecimal.format( k/255d ) ); + appendRawCommands( SPACE ); + appendRawCommands( K_NON_STROKING ); + } + + /** + * Set the non stroking color, specified as CMYK, 0.0-1.0. + * + * @param c The cyan value. + * @param m The magenta value. + * @param y The yellow value. + * @param k The black value. + * @throws IOException If an IO error occurs while writing to the stream. + */ + public void setNonStrokingColor( double c, double m, double y, double k) throws IOException + { + appendRawCommands( formatDecimal.format( c ) ); + appendRawCommands( SPACE ); + appendRawCommands( formatDecimal.format( m ) ); + appendRawCommands( SPACE ); + appendRawCommands( formatDecimal.format( y ) ); + appendRawCommands( SPACE ); + appendRawCommands( formatDecimal.format( k ) ); + appendRawCommands( SPACE ); + appendRawCommands( K_NON_STROKING ); + } + + /** + * Set the non stroking color, specified as grayscale, 0-255. + * + * @param g The gray value. + * @throws IOException If an IO error occurs while writing to the stream. + */ + public void setNonStrokingColor( int g ) throws IOException + { + appendRawCommands( formatDecimal.format( g/255d ) ); + appendRawCommands( SPACE ); + appendRawCommands( G_NON_STROKING ); + } + + /** + * Set the non stroking color, specified as Grayscale 0.0-1.0. + * + * @param g The gray value. + * @throws IOException If an IO error occurs while writing to the stream. + */ + public void setNonStrokingColor( double g ) throws IOException + { + appendRawCommands( formatDecimal.format( g ) ); + appendRawCommands( SPACE ); + appendRawCommands( G_NON_STROKING ); + } + + /** + * Draw a rectangle on the page using the current non stroking color. + * + * @param x The lower left x coordinate. + * @param y The lower left y coordinate. + * @param width The width of the rectangle. + * @param height The height of the rectangle. + * @throws IOException If there is an error while drawing on the screen. + */ + public void fillRect( float x, float y, float width, float height ) throws IOException + { + appendRawCommands( formatDecimal.format( x ) ); + appendRawCommands( SPACE ); + appendRawCommands( formatDecimal.format( y ) ); + appendRawCommands( SPACE ); + appendRawCommands( formatDecimal.format( width ) ); + appendRawCommands( SPACE ); + appendRawCommands( formatDecimal.format( height ) ); + appendRawCommands( SPACE ); + appendRawCommands( APPEND_RECTANGLE ); + appendRawCommands( FILL ); + } + + + /** + * This will append raw commands to the content stream. + * + * @param commands The commands to append to the stream. + * @throws IOException If an error occurs while writing to the stream. + */ + public void appendRawCommands( String commands ) throws IOException + { + appendRawCommands( commands.getBytes( "ISO-8859-1" ) ); + } + + /** + * This will append raw commands to the content stream. + * + * @param commands The commands to append to the stream. + * @throws IOException If an error occurs while writing to the stream. + */ + public void appendRawCommands( byte[] commands ) throws IOException + { + output.write( commands ); + } + + /** + * This will append raw commands to the content stream. + * + * @param data Append a raw byte to the stream. + * + * @throws IOException If an error occurs while writing to the stream. + */ + public void appendRawCommands( int data ) throws IOException + { + output.write( data ); + } + + /** + * Close the content stream. This must be called when you are done with this + * object. + * @throws IOException If the underlying stream has a problem being written to. + */ + public void close() throws IOException + { + output.close(); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/edit/package.html b/src/main/java/org/pdfbox/pdmodel/edit/package.html new file mode 100644 index 0000000..f6b0ffd --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/edit/package.html @@ -0,0 +1,9 @@ + + + + + + +The PDModel edit package will be used to store classes for creating page content. + + diff --git a/src/main/java/org/pdfbox/pdmodel/encryption/PDEncryptionDictionary.java b/src/main/java/org/pdfbox/pdmodel/encryption/PDEncryptionDictionary.java new file mode 100644 index 0000000..08f18fb --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/encryption/PDEncryptionDictionary.java @@ -0,0 +1,193 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.encryption; + +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSInteger; +import org.pdfbox.cos.COSName; +import org.pdfbox.cos.COSNumber; + +/** + * This represents the base class for encryption dictionaries. All PDF implementations + * are expected to implement the Standard encryption algorithm, but others can be plugged in. + * + * See PDF Reference 1.4 section "3.5 Encryption" + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.5 $ + */ +public abstract class PDEncryptionDictionary +{ + /** + * See PDF Reference 1.4 Table 3.13. + */ + public static final int VERSION0_UNDOCUMENTED_UNSUPPORTED = 0; + /** + * See PDF Reference 1.4 Table 3.13. + */ + public static final int VERSION1_40_BIT_ALGORITHM = 1; + /** + * See PDF Reference 1.4 Table 3.13. + */ + public static final int VERSION2_VARIABLE_LENGTH_ALGORITHM = 2; + /** + * See PDF Reference 1.4 Table 3.13. + */ + public static final int VERSION3_UNPUBLISHED_ALGORITHM = 3; + /** + * See PDF Reference 1.4 Table 3.13. + */ + public static final int VERSION4_SECURITY_HANDLER = 4; + + /** + * The default security handler. + */ + public static final String DEFAULT_NAME = "Standard"; + + /** + * The default length for the encryption key. + */ + public static final int DEFAULT_LENGTH = 40; + + /** + * The default version, according to the PDF Reference. + */ + public static final int DEFAULT_VERSION = VERSION0_UNDOCUMENTED_UNSUPPORTED; + + /** + * The cos model wrapped object. + */ + protected COSDictionary encryptionDictionary = null; + + /** + * Constructor. + * + * @param dictionary The pre-existing encryption dictionary. + */ + protected PDEncryptionDictionary( COSDictionary dictionary ) + { + encryptionDictionary = dictionary; + } + + /** + * Constructor, sub classes need to fill out the required fields. + */ + protected PDEncryptionDictionary() + { + encryptionDictionary = new COSDictionary(); + setLength( DEFAULT_LENGTH ); + setVersion( DEFAULT_VERSION ); + } + + /** + * This will get the dictionary associated with this encryption dictionary. + * + * @return The COS dictionary that this object wraps. + */ + public COSDictionary getCOSDictionary() + { + return encryptionDictionary; + } + + /** + * Read-only field of the encryption filter name. The default value is + * "Standard" for the built in security handler. + * + * @return The name of the encryption handler. + */ + public String getFilter() + { + String filter = DEFAULT_NAME; + COSName cosFilter = (COSName)encryptionDictionary.getDictionaryObject( COSName.FILTER ); + if( cosFilter != null ) + { + filter = cosFilter.getName(); + } + return filter; + } + + /** + * This will return the V entry of the encryption dictionary.

+ * See PDF Reference 1.4 Table 3.13. + * + * @return The encryption version to use. + */ + public int getVersion() + { + int version = DEFAULT_VERSION; + COSNumber cosVersion = (COSNumber)encryptionDictionary.getDictionaryObject( COSName.getPDFName( "V" ) ); + if( cosVersion != null ) + { + version = cosVersion.intValue(); + } + return version; + } + + /** + * This will set the V entry of the encryption dictionary.

+ * See PDF Reference 1.4 Table 3.13.

+ * Note: This value is used to decrypt the pdf document. If you change this when + * the document is encrypted then decryption will fail!. + * + * @param version The new encryption version. + */ + public void setVersion( int version ) + { + encryptionDictionary.setItem( COSName.getPDFName( "V" ), new COSInteger( version ) ); + } + + /** + * This will return the Length entry of the encryption dictionary.

+ * The length in bits for the encryption algorithm. This will return a multiple of 8. + * + * @return The length in bits for the encryption algorithm + */ + public int getLength() + { + int length = DEFAULT_LENGTH; + COSNumber cosLength = (COSNumber)encryptionDictionary.getDictionaryObject( COSName.LENGTH ); + if( cosLength != null ) + { + length = cosLength.intValue(); + } + return length; + } + + /** + * This will set the number of bits to use for the encryption algorithm. + * + * @param length The new key length. + */ + public void setLength( int length ) + { + encryptionDictionary.setItem( COSName.LENGTH, new COSInteger( length ) ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/encryption/PDEncryptionManager.java b/src/main/java/org/pdfbox/pdmodel/encryption/PDEncryptionManager.java new file mode 100644 index 0000000..9dfc36e --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/encryption/PDEncryptionManager.java @@ -0,0 +1,131 @@ +/** + * Copyright (c) 2003-2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.encryption; + +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSName; +import java.io.IOException; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * This class will handle loading of the different security handlers. + * + * See PDF Reference 1.4 section "3.5 Encryption" + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.5 $ + */ +public class PDEncryptionManager +{ + private static Map handlerMap = Collections.synchronizedMap( new HashMap() ); + + static + { + registerSecurityHandler( PDStandardEncryption.FILTER_NAME, PDStandardEncryption.class ); + } + + private PDEncryptionManager() + { + } + + /** + * This will allow the user to register new security handlers when unencrypting a + * document. + * + * @param filterName As described in the encryption dictionary. + * @param handlerClass A subclass of PDEncryptionDictionary that has a constructor that takes + * a COSDictionary. + */ + public static void registerSecurityHandler( String filterName, Class handlerClass ) + { + handlerMap.put( COSName.getPDFName( filterName ), handlerClass ); + } + + /** + * This will get the correct security handler for the encryption dictionary. + * + * @param dictionary The encryption dictionary. + * + * @return An implementation of PDEncryptionDictionary(PDStandardEncryption for most cases). + * + * @throws IOException If a security handler could not be found. + */ + public static PDEncryptionDictionary getEncryptionDictionary( COSDictionary dictionary ) + throws IOException + { + Object retval = null; + if( dictionary != null ) + { + COSName filter = (COSName)dictionary.getDictionaryObject( COSName.FILTER ); + Class handlerClass = (Class)handlerMap.get( filter ); + if( handlerClass == null ) + { + throw new IOException( "No handler for security handler '" + filter.getName() + "'" ); + } + else + { + try + { + Constructor ctor = handlerClass.getConstructor( new Class[] { + COSDictionary.class + } ); + retval = ctor.newInstance( new Object[] { + dictionary + } ); + } + catch( NoSuchMethodException e ) + { + throw new IOException( e.getMessage() ); + } + catch( InstantiationException e ) + { + throw new IOException( e.getMessage() ); + } + catch( IllegalAccessException e ) + { + throw new IOException( e.getMessage() ); + } + catch( InvocationTargetException e ) + { + throw new IOException( e.getMessage() ); + } + } + } + return (PDEncryptionDictionary)retval; + + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/encryption/PDStandardEncryption.java b/src/main/java/org/pdfbox/pdmodel/encryption/PDStandardEncryption.java new file mode 100644 index 0000000..5b3be3b --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/encryption/PDStandardEncryption.java @@ -0,0 +1,416 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.encryption; + +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSInteger; +import org.pdfbox.cos.COSName; +import org.pdfbox.cos.COSNumber; +import org.pdfbox.cos.COSString; + +import java.io.IOException; + +/** + * This class holds information that is related to the standard PDF encryption. + * + * See PDF Reference 1.4 section "3.5 Encryption" + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.5 $ + */ +public class PDStandardEncryption extends PDEncryptionDictionary +{ + /** + * The 'Filter' name for this security handler. + */ + public static final String FILTER_NAME = "Standard"; + + /** + * The default revision of one is not specified. + */ + public static final int DEFAULT_REVISION = 3; + + /** + * Encryption revision 2. + */ + public static final int REVISION2 = 2; + /** + * Encryption revision 3. + */ + public static final int REVISION3 = 3; + /** + * Encryption revision 4. + */ + public static final int REVISION4 = 4; + + /** + * The default set of permissions which is to allow all. + */ + public static final int DEFAULT_PERMISSIONS = 0xFFFFFFFF ^ 3;//bits 0 & 1 need to be zero + + private static final int PRINT_BIT = 3; + private static final int MODIFICATION_BIT = 4; + private static final int EXTRACT_BIT = 5; + private static final int MODIFY_ANNOTATIONS_BIT = 6; + private static final int FILL_IN_FORM_BIT = 9; + private static final int EXTRACT_FOR_ACCESSIBILITY_BIT = 10; + private static final int ASSEMBLE_DOCUMENT_BIT = 11; + private static final int DEGRADED_PRINT_BIT = 12; + + /** + * Default constructor that uses Version 2, Revision 3, 40 bit encryption, + * all permissions allowed. + */ + public PDStandardEncryption() + { + super(); + encryptionDictionary.setItem( COSName.FILTER, COSName.getPDFName( FILTER_NAME ) ); + setVersion( PDEncryptionDictionary.VERSION1_40_BIT_ALGORITHM ); + setRevision( PDStandardEncryption.REVISION2 ); + setPermissions( DEFAULT_PERMISSIONS ); + } + + /** + * Constructor from existing dictionary. + * + * @param dict The existing encryption dictionary. + */ + public PDStandardEncryption( COSDictionary dict ) + { + super( dict ); + } + + /** + * This will return the R entry of the encryption dictionary.

+ * See PDF Reference 1.4 Table 3.14. + * + * @return The encryption revision to use. + */ + public int getRevision() + { + int revision = DEFAULT_VERSION; + COSNumber cosRevision = (COSNumber)encryptionDictionary.getDictionaryObject( COSName.getPDFName( "R" ) ); + if( cosRevision != null ) + { + revision = cosRevision.intValue(); + } + return revision; + } + + /** + * This will set the R entry of the encryption dictionary.

+ * See PDF Reference 1.4 Table 3.14.

+ * + * Note: This value is used to decrypt the pdf document. If you change this when + * the document is encrypted then decryption will fail!. + * + * @param revision The new encryption version. + */ + public void setRevision( int revision ) + { + encryptionDictionary.setItem( COSName.getPDFName( "R" ), new COSInteger( revision ) ); + } + + /** + * This will get the O entry in the standard encryption dictionary. + * + * @return A 32 byte array or null if there is no owner key. + */ + public byte[] getOwnerKey() + { + byte[] o = null; + COSString owner = (COSString)encryptionDictionary.getDictionaryObject( COSName.getPDFName( "O" ) ); + if( owner != null ) + { + o = owner.getBytes(); + } + return o; + } + + /** + * This will set the O entry in the standard encryption dictionary. + * + * @param o A 32 byte array or null if there is no owner key. + * + * @throws IOException If there is an error setting the data. + */ + public void setOwnerKey( byte[] o ) throws IOException + { + COSString owner = new COSString(); + owner.append( o ); + encryptionDictionary.setItem( COSName.getPDFName( "O" ), owner ); + } + + /** + * This will get the U entry in the standard encryption dictionary. + * + * @return A 32 byte array or null if there is no user key. + */ + public byte[] getUserKey() + { + byte[] u = null; + COSString user = (COSString)encryptionDictionary.getDictionaryObject( COSName.getPDFName( "U" ) ); + if( user != null ) + { + u = user.getBytes(); + } + return u; + } + + /** + * This will set the U entry in the standard encryption dictionary. + * + * @param u A 32 byte array. + * + * @throws IOException If there is an error setting the data. + */ + public void setUserKey( byte[] u ) throws IOException + { + COSString user = new COSString(); + user.append( u ); + encryptionDictionary.setItem( COSName.getPDFName( "U" ), user ); + } + + /** + * This will get the permissions bit mask. + * + * @return The permissions bit mask. + */ + public int getPermissions() + { + int permissions = 0; + COSInteger p = (COSInteger)encryptionDictionary.getDictionaryObject( COSName.getPDFName( "P" ) ); + if( p != null ) + { + permissions = p.intValue(); + } + return permissions; + } + + /** + * This will set the permissions bit mask. + * + * @param p The new permissions bit mask + */ + public void setPermissions( int p ) + { + encryptionDictionary.setItem( COSName.getPDFName( "P" ), new COSInteger( p ) ); + } + + private boolean isPermissionBitOn( int bit ) + { + return (getPermissions() & (1 << (bit-1))) != 0; + } + + private boolean setPermissionBit( int bit, boolean value ) + { + int permissions = getPermissions(); + if( value ) + { + permissions = permissions | (1 << (bit-1)); + } + else + { + permissions = permissions & (0xFFFFFFFF ^ (1 << (bit-1))); + } + setPermissions( permissions ); + + return (getPermissions() & (1 << (bit-1))) != 0; + } + + /** + * This will tell if the user can print. + * + * @return true If supplied with the user password they are allowed to print. + */ + public boolean canPrint() + { + return isPermissionBitOn( PRINT_BIT ); + } + + /** + * Set if the user can print. + * + * @param allowPrinting A boolean determining if the user can print. + */ + public void setCanPrint( boolean allowPrinting ) + { + setPermissionBit( PRINT_BIT, allowPrinting ); + } + + /** + * This will tell if the user can modify contents of the document. + * + * @return true If supplied with the user password they are allowed to modify the document + */ + public boolean canModify() + { + return isPermissionBitOn( MODIFICATION_BIT ); + } + + /** + * Set if the user can modify the document. + * + * @param allowModifications A boolean determining if the user can modify the document. + */ + public void setCanModify( boolean allowModifications ) + { + setPermissionBit( MODIFICATION_BIT, allowModifications ); + } + + /** + * This will tell if the user can extract text and images from the PDF document. + * + * @return true If supplied with the user password they are allowed to extract content + * from the PDF document + */ + public boolean canExtractContent() + { + return isPermissionBitOn( EXTRACT_BIT ); + } + + /** + * Set if the user can extract content from the document. + * + * @param allowExtraction A boolean determining if the user can extract content + * from the document. + */ + public void setCanExtractContent( boolean allowExtraction ) + { + setPermissionBit( EXTRACT_BIT, allowExtraction ); + } + + /** + * This will tell if the user can add/modify text annotations, fill in interactive forms fields. + * + * @return true If supplied with the user password they are allowed to modify annotations. + */ + public boolean canModifyAnnotations() + { + return isPermissionBitOn( MODIFY_ANNOTATIONS_BIT ); + } + + /** + * Set if the user can modify annotations. + * + * @param allowAnnotationModification A boolean determining if the user can modify annotations. + */ + public void setCanModifyAnnotations( boolean allowAnnotationModification ) + { + setPermissionBit( MODIFY_ANNOTATIONS_BIT, allowAnnotationModification ); + } + + /** + * This will tell if the user can fill in interactive forms. + * + * @return true If supplied with the user password they are allowed to fill in form fields. + */ + public boolean canFillInForm() + { + return isPermissionBitOn( FILL_IN_FORM_BIT ); + } + + /** + * Set if the user can fill in interactive forms. + * + * @param allowFillingInForm A boolean determining if the user can fill in interactive forms. + */ + public void setCanFillInForm( boolean allowFillingInForm ) + { + setPermissionBit( FILL_IN_FORM_BIT, allowFillingInForm ); + } + + /** + * This will tell if the user can extract text and images from the PDF document + * for accessibility purposes. + * + * @return true If supplied with the user password they are allowed to extract content + * from the PDF document + */ + public boolean canExtractForAccessibility() + { + return isPermissionBitOn( EXTRACT_FOR_ACCESSIBILITY_BIT ); + } + + /** + * Set if the user can extract content from the document for accessibility purposes. + * + * @param allowExtraction A boolean determining if the user can extract content + * from the document. + */ + public void setCanExtractForAccessibility( boolean allowExtraction ) + { + setPermissionBit( EXTRACT_FOR_ACCESSIBILITY_BIT, allowExtraction ); + } + + /** + * This will tell if the user can insert/rotate/delete pages. + * + * @return true If supplied with the user password they are allowed to extract content + * from the PDF document + */ + public boolean canAssembleDocument() + { + return isPermissionBitOn( ASSEMBLE_DOCUMENT_BIT ); + } + + /** + * Set if the user can insert/rotate/delete pages. + * + * @param allowAssembly A boolean determining if the user can assemble the document. + */ + public void setCanAssembleDocument( boolean allowAssembly ) + { + setPermissionBit( ASSEMBLE_DOCUMENT_BIT, allowAssembly ); + } + + /** + * This will tell if the user can print the document in a degraded format. + * + * @return true If supplied with the user password they are allowed to print the + * document in a degraded format. + */ + public boolean canPrintDegraded() + { + return isPermissionBitOn( DEGRADED_PRINT_BIT ); + } + + /** + * Set if the user can print the document in a degraded format. + * + * @param allowAssembly A boolean determining if the user can print the + * document in a degraded format. + */ + public void setCanPrintDegraded( boolean allowAssembly ) + { + setPermissionBit( DEGRADED_PRINT_BIT, allowAssembly ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/encryption/package.html b/src/main/java/org/pdfbox/pdmodel/encryption/package.html new file mode 100644 index 0000000..a458817 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/encryption/package.html @@ -0,0 +1,9 @@ + + + + + + +The encryption package will handle the PDF document security handlers and the functionality of pluggable security handlers. + + diff --git a/src/main/java/org/pdfbox/pdmodel/fdf/FDFAnnotation.java b/src/main/java/org/pdfbox/pdmodel/fdf/FDFAnnotation.java new file mode 100644 index 0000000..3d121e7 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/fdf/FDFAnnotation.java @@ -0,0 +1,114 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.fdf; + +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSInteger; +import org.pdfbox.cos.COSNumber; + +import org.pdfbox.pdmodel.common.COSObjectable; + +/** + * This represents an FDF annotation that is part of the FDF document. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.2 $ + */ +public class FDFAnnotation implements COSObjectable +{ + private COSDictionary annot; + + /** + * Default constructor. + */ + public FDFAnnotation() + { + annot = new COSDictionary(); + } + + /** + * Constructor. + * + * @param a The FDF annotation. + */ + public FDFAnnotation( COSDictionary a ) + { + annot = a; + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSBase getCOSObject() + { + return annot; + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSDictionary getCOSDictionary() + { + return annot; + } + + /** + * This will get the page number or null if it does not exist. + * + * @return The page number. + */ + public Integer getPage() + { + Integer retval = null; + COSNumber page = (COSNumber)annot.getDictionaryObject( "Page" ); + if( page != null ) + { + retval = new Integer( page.intValue() ); + } + return retval; + } + + /** + * This will set the page. + * + * @param page The page number. + */ + public void setPage( int page ) + { + annot.setItem( "Page", new COSInteger( page ) ); + } + +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/fdf/FDFCatalog.java b/src/main/java/org/pdfbox/pdmodel/fdf/FDFCatalog.java new file mode 100644 index 0000000..f6959ee --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/fdf/FDFCatalog.java @@ -0,0 +1,195 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.fdf; + +import java.io.IOException; +import java.io.Writer; + +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSDictionary; + +import org.pdfbox.pdmodel.common.COSObjectable; + +import org.pdfbox.pdmodel.interactive.digitalsignature.PDSignature; + +import org.w3c.dom.Element; + +/** + * This represents an FDF catalog that is part of the FDF document. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.2 $ + */ +public class FDFCatalog implements COSObjectable +{ + private COSDictionary catalog; + + /** + * Default constructor. + */ + public FDFCatalog() + { + catalog = new COSDictionary(); + } + + /** + * Constructor. + * + * @param cat The FDF documents catalog. + */ + public FDFCatalog( COSDictionary cat ) + { + catalog = cat; + } + + /** + * This will create an FDF catalog from an XFDF XML document. + * + * @param element The XML document that contains the XFDF data. + * @throws IOException If there is an error reading from the dom. + */ + public FDFCatalog( Element element ) throws IOException + { + this(); + FDFDictionary fdfDict = new FDFDictionary( element ); + setFDF( fdfDict ); + } + + /** + * This will write this element as an XML document. + * + * @param output The stream to write the xml to. + * + * @throws IOException If there is an error writing the XML. + */ + public void writeXML( Writer output ) throws IOException + { + FDFDictionary fdf = getFDF(); + fdf.writeXML( output ); + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSBase getCOSObject() + { + return catalog; + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSDictionary getCOSDictionary() + { + return catalog; + } + + /** + * This will get the version that was specified in the catalog dictionary. + * + * @return The FDF version. + */ + public String getVersion() + { + return catalog.getNameAsString( "Version" ); + } + + /** + * This will set the version of the FDF document. + * + * @param version The new version for the FDF document. + */ + public void setVersion( String version ) + { + catalog.setName( "Version", version ); + } + + /** + * This will get the FDF dictionary. + * + * @return The FDF dictionary. + */ + public FDFDictionary getFDF() + { + COSDictionary fdf = (COSDictionary)catalog.getDictionaryObject( "FDF" ); + FDFDictionary retval = null; + if( fdf != null ) + { + retval = new FDFDictionary( fdf ); + } + else + { + retval = new FDFDictionary(); + setFDF( retval ); + } + return retval; + } + + /** + * This will set the FDF document. + * + * @param fdf The new FDF dictionary. + */ + public void setFDF( FDFDictionary fdf ) + { + catalog.setItem( "FDF", fdf ); + } + + /** + * This will get the signature or null if there is none. + * + * @return The signature. + */ + public PDSignature getSignature() + { + PDSignature signature = null; + COSDictionary sig = (COSDictionary)catalog.getDictionaryObject( "Sig" ); + if( sig != null ) + { + signature = new PDSignature( sig ); + } + return signature; + } + + /** + * This will set the signature that is associated with this catalog. + * + * @param sig The new signature. + */ + public void setSignature( PDSignature sig ) + { + catalog.setItem( "Sig", sig ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/fdf/FDFDictionary.java b/src/main/java/org/pdfbox/pdmodel/fdf/FDFDictionary.java new file mode 100644 index 0000000..ab25bc7 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/fdf/FDFDictionary.java @@ -0,0 +1,465 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.fdf; + +import java.io.IOException; +import java.io.Writer; +import java.util.ArrayList; +import java.util.List; + +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSStream; +import org.pdfbox.cos.COSString; + +import org.pdfbox.pdmodel.common.COSObjectable; +import org.pdfbox.pdmodel.common.COSArrayList; +import org.pdfbox.pdmodel.common.filespecification.PDFileSpecification; +import org.pdfbox.pdmodel.common.filespecification.PDSimpleFileSpecification; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** + * This represents an FDF dictionary that is part of the FDF document. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.6 $ + */ +public class FDFDictionary implements COSObjectable +{ + private COSDictionary fdf; + + /** + * Default constructor. + */ + public FDFDictionary() + { + fdf = new COSDictionary(); + } + + /** + * Constructor. + * + * @param fdfDictionary The FDF documents catalog. + */ + public FDFDictionary( COSDictionary fdfDictionary ) + { + fdf = fdfDictionary; + } + + /** + * This will create an FDF dictionary from an XFDF XML document. + * + * @param fdfXML The XML document that contains the XFDF data. + * @throws IOException If there is an error reading from the dom. + */ + public FDFDictionary( Element fdfXML ) throws IOException + { + this(); + NodeList nodeList = fdfXML.getChildNodes(); + for( int i=0; i\n" ); + } + COSArray ids = this.getID(); + if( ids != null ) + { + COSString original = (COSString)ids.getObject( 0 ); + COSString modified = (COSString)ids.getObject( 1 ); + output.write( "\n"); + } + List fields = getFields(); + if( fields != null && fields.size() > 0 ) + { + output.write( "\n" ); + for( int i=0; i\n" ); + } + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSBase getCOSObject() + { + return fdf; + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSDictionary getCOSDictionary() + { + return fdf; + } + + /** + * The source file or target file: the PDF document file that + * this FDF file was exported from or is intended to be imported into. + * + * @return The F entry of the FDF dictionary. + */ + public PDFileSpecification getFile() + { + return PDFileSpecification.createFS( fdf.getDictionaryObject( "F" ) ); + } + + /** + * This will set the file specification. + * + * @param fs The file specification. + */ + public void setFile( PDFileSpecification fs ) + { + fdf.setItem( "F", fs ); + } + + /** + * This is the FDF id. + * + * @return The FDF ID. + */ + public COSArray getID() + { + return (COSArray)fdf.getDictionaryObject( "ID" ); + } + + /** + * This will set the FDF id. + * + * @param id The new id for the FDF. + */ + public void setID( COSArray id ) + { + fdf.setItem( "ID", id ); + } + + /** + * This will get the list of FDF Fields. This will return a list of FDFField + * objects. + * + * @return A list of FDF fields. + */ + public List getFields() + { + List retval = null; + COSArray fieldArray = (COSArray)fdf.getDictionaryObject( "Fields" ); + if( fieldArray != null ) + { + List fields = new ArrayList(); + for( int i=0; i\n" ); + output.write( "\n" ); + + getCatalog().writeXML( output ); + + output.write( "\n" ); + } + + + + /** + * This will get the low level document. + * + * @return The document that this layer sits on top of. + */ + public COSDocument getDocument() + { + return document; + } + + /** + * This will get the FDF Catalog. This is guaranteed to not return null. + * + * @return The documents /Root dictionary + */ + public FDFCatalog getCatalog() + { + FDFCatalog retval = null; + COSDictionary trailer = document.getTrailer(); + COSDictionary root = (COSDictionary)trailer.getDictionaryObject( COSName.ROOT ); + if( root == null ) + { + retval = new FDFCatalog(); + setCatalog( retval ); + } + else + { + retval = new FDFCatalog( root ); + } + return retval; + } + + /** + * This will set the FDF catalog for this FDF document. + * + * @param cat The FDF catalog. + */ + public void setCatalog( FDFCatalog cat ) + { + COSDictionary trailer = document.getTrailer(); + trailer.setItem( COSName.ROOT, cat ); + } + + /** + * This will load a document from a file. + * + * @param filename The name of the file to load. + * + * @return The document that was loaded. + * + * @throws IOException If there is an error reading from the stream. + */ + public static FDFDocument load( String filename ) throws IOException + { + return load( new BufferedInputStream( new FileInputStream( filename ) ) ); + } + + /** + * This will load a document from a file. + * + * @param file The name of the file to load. + * + * @return The document that was loaded. + * + * @throws IOException If there is an error reading from the stream. + */ + public static FDFDocument load( File file ) throws IOException + { + return load( new BufferedInputStream( new FileInputStream( file ) ) ); + } + + /** + * This will load a document from an input stream. + * + * @param input The stream that contains the document. + * + * @return The document that was loaded. + * + * @throws IOException If there is an error reading from the stream. + */ + public static FDFDocument load( InputStream input ) throws IOException + { + PDFParser parser = new PDFParser( input ); + parser.parse(); + return parser.getFDFDocument(); + } + + /** + * This will load a document from a file. + * + * @param filename The name of the file to load. + * + * @return The document that was loaded. + * + * @throws IOException If there is an error reading from the stream. + */ + public static FDFDocument loadXFDF( String filename ) throws IOException + { + return loadXFDF( new BufferedInputStream( new FileInputStream( filename ) ) ); + } + + /** + * This will load a document from a file. + * + * @param file The name of the file to load. + * + * @return The document that was loaded. + * + * @throws IOException If there is an error reading from the stream. + */ + public static FDFDocument loadXFDF( File file ) throws IOException + { + return loadXFDF( new BufferedInputStream( new FileInputStream( file ) ) ); + } + + /** + * This will load a document from an input stream. + * + * @param input The stream that contains the document. + * + * @return The document that was loaded. + * + * @throws IOException If there is an error reading from the stream. + */ + public static FDFDocument loadXFDF( InputStream input ) throws IOException + { + Document doc = XMLUtil.parse( input ); + return new FDFDocument( doc ); + } + + /** + * This will save this document to the filesystem. + * + * @param fileName The file to save as. + * + * @throws IOException If there is an error saving the document. + * @throws COSVisitorException If an error occurs while generating the data. + */ + public void save( File fileName ) throws IOException, COSVisitorException + { + save( new FileOutputStream( fileName ) ); + } + + /** + * This will save this document to the filesystem. + * + * @param fileName The file to save as. + * + * @throws IOException If there is an error saving the document. + * @throws COSVisitorException If an error occurs while generating the data. + */ + public void save( String fileName ) throws IOException, COSVisitorException + { + save( new FileOutputStream( fileName ) ); + } + + /** + * This will save the document to an output stream. + * + * @param output The stream to write to. + * + * @throws IOException If there is an error writing the document. + * @throws COSVisitorException If an error occurs while generating the data. + */ + public void save( OutputStream output ) throws IOException, COSVisitorException + { + COSWriter writer = null; + try + { + writer = new COSWriter( output ); + writer.write( document ); + writer.close(); + } + finally + { + if( writer != null ) + { + writer.close(); + } + } + } + + /** + * This will save this document to the filesystem. + * + * @param fileName The file to save as. + * + * @throws IOException If there is an error saving the document. + * @throws COSVisitorException If an error occurs while generating the data. + */ + public void saveXFDF( File fileName ) throws IOException, COSVisitorException + { + saveXFDF( new BufferedWriter( new FileWriter( fileName ) ) ); + } + + /** + * This will save this document to the filesystem. + * + * @param fileName The file to save as. + * + * @throws IOException If there is an error saving the document. + * @throws COSVisitorException If an error occurs while generating the data. + */ + public void saveXFDF( String fileName ) throws IOException, COSVisitorException + { + saveXFDF( new BufferedWriter( new FileWriter( fileName ) ) ); + } + + /** + * This will save the document to an output stream and close the stream. + * + * @param output The stream to write to. + * + * @throws IOException If there is an error writing the document. + * @throws COSVisitorException If an error occurs while generating the data. + */ + public void saveXFDF( Writer output ) throws IOException, COSVisitorException + { + try + { + writeXML( output ); + } + finally + { + if( output != null ) + { + output.close(); + } + } + } + + /** + * This will close the underlying COSDocument object. + * + * @throws IOException If there is an error releasing resources. + */ + public void close() throws IOException + { + document.close(); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/fdf/FDFField.java b/src/main/java/org/pdfbox/pdmodel/fdf/FDFField.java new file mode 100644 index 0000000..35b90ed --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/fdf/FDFField.java @@ -0,0 +1,763 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.fdf; + +import java.io.IOException; +import java.io.Writer; + +import java.util.ArrayList; +import java.util.List; + +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSInteger; +import org.pdfbox.cos.COSName; +import org.pdfbox.cos.COSNumber; +import org.pdfbox.cos.COSStream; +import org.pdfbox.cos.COSString; + +import org.pdfbox.pdmodel.common.COSObjectable; +import org.pdfbox.pdmodel.common.COSArrayList; +import org.pdfbox.pdmodel.common.PDTextStream; + +import org.pdfbox.pdmodel.interactive.action.PDActionFactory; +import org.pdfbox.pdmodel.interactive.action.PDAdditionalActions; +import org.pdfbox.pdmodel.interactive.action.type.PDAction; + +import org.pdfbox.pdmodel.interactive.annotation.PDAppearanceDictionary; + +import org.pdfbox.util.XMLUtil; + +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** + * This represents an FDF field that is part of the FDF document. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.4 $ + */ +public class FDFField implements COSObjectable +{ + private COSDictionary field; + + /** + * Default constructor. + */ + public FDFField() + { + field = new COSDictionary(); + } + + /** + * Constructor. + * + * @param f The FDF field. + */ + public FDFField( COSDictionary f ) + { + field = f; + } + + /** + * This will create an FDF field from an XFDF XML document. + * + * @param fieldXML The XML document that contains the XFDF data. + * @throws IOException If there is an error reading from the dom. + */ + public FDFField( Element fieldXML ) throws IOException + { + this(); + this.setPartialFieldName( fieldXML.getAttribute( "name" ) ); + NodeList nodeList = fieldXML.getChildNodes(); + List kids = new ArrayList(); + for( int i=0; i 0 ) + { + setKids( kids ); + } + + } + + /** + * This will write this element as an XML document. + * + * @param output The stream to write the xml to. + * + * @throws IOException If there is an error writing the XML. + */ + public void writeXML( Writer output ) throws IOException + { + output.write( "\n"); + Object value = getValue(); + if( value != null ) + { + output.write( "" + value + "\n" ); + } + PDTextStream rt = getRichText(); + if( rt != null ) + { + output.write( "" + rt.getAsString() + "\n" ); + } + List kids = getKids(); + if( kids != null ) + { + for( int i=0; i\n"); + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSBase getCOSObject() + { + return field; + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSDictionary getCOSDictionary() + { + return field; + } + + /** + * This will get the list of kids. This will return a list of FDFField objects. + * This will return null if the underlying list is null. + * + * @return The list of kids. + */ + public List getKids() + { + COSArray kids = (COSArray)field.getDictionaryObject( "Kids" ); + List retval = null; + if( kids != null ) + { + List actuals = new ArrayList(); + for( int i=0; i + * Address.State
+ * Address.City
+ * + * @return The partial field name. + */ + public String getPartialFieldName() + { + return field.getString( "T" ); + } + + /** + * This will set the partial field name. + * + * @param partial The partial field name. + */ + public void setPartialFieldName( String partial ) + { + field.setString( "T", partial ); + } + + /** + * This will set the value for the field. This will return type will either be
+ * String : Checkboxes, Radio Button
+ * java.util.List of strings: Choice Field + * PDTextStream: Textfields + * + * @return The value of the field. + * + * @throws IOException If there is an error getting the value. + */ + public Object getValue() throws IOException + { + Object retval = null; + COSBase value = field.getDictionaryObject( "V" ); + if( value instanceof COSName ) + { + retval = ((COSName)value).getName(); + } + else if( value instanceof COSArray ) + { + retval = COSArrayList.convertCOSStringCOSArrayToList( (COSArray)value ); + } + else if( value instanceof COSString || value instanceof COSStream ) + { + retval = PDTextStream.createTextStream( value ); + } + else if( value == null ) + { + //Ok, value is null so do nothing + } + else + { + throw new IOException( "Error:Unknown type for field import" + value ); + } + return retval; + } + + /** + * You should pass in a string, or a java.util.List of strings to set the + * value. + * + * @param value The value that should populate when imported. + * + * @throws IOException If there is an error setting the value. + */ + public void setValue( Object value ) throws IOException + { + COSBase cos = null; + if( value instanceof List ) + { + cos = COSArrayList.convertStringListToCOSStringCOSArray( (List)value ); + } + else if( value instanceof String ) + { + cos = COSName.getPDFName( (String)value ); + } + else if( value instanceof COSObjectable ) + { + cos = ((COSObjectable)value).getCOSObject(); + } + else if( value == null ) + { + //do nothing and let cos remain null as well. + } + else + { + throw new IOException( "Error:Unknown type for field import" + value ); + } + field.setItem( "V", cos ); + } + + /** + * This will get the Ff entry of the cos dictionary. If it it not present then + * this method will return null. + * + * @return The field flags. + */ + public Integer getFieldFlags() + { + Integer retval = null; + COSNumber ff = (COSNumber)field.getDictionaryObject( "Ff" ); + if( ff != null ) + { + retval = new Integer( ff.intValue() ); + } + return retval; + } + + /** + * This will get the field flags that are associated with this field. The Ff entry + * in the FDF field dictionary. + * + * @param ff The new value for the field flags. + */ + public void setFieldFlags( Integer ff ) + { + COSInteger value = null; + if( ff != null ) + { + value = new COSInteger( ff.intValue() ); + } + field.setItem( "Ff", value ); + } + + /** + * This will get the field flags that are associated with this field. The Ff entry + * in the FDF field dictionary. + * + * @param ff The new value for the field flags. + */ + public void setFieldFlags( int ff ) + { + field.setItem( "Ff", new COSInteger( ff ) ); + } + + /** + * This will get the SetFf entry of the cos dictionary. If it it not present then + * this method will return null. + * + * @return The field flags. + */ + public Integer getSetFieldFlags() + { + Integer retval = null; + COSNumber ff = (COSNumber)field.getDictionaryObject( "SetFf" ); + if( ff != null ) + { + retval = new Integer( ff.intValue() ); + } + return retval; + } + + /** + * This will get the field flags that are associated with this field. The SetFf entry + * in the FDF field dictionary. + * + * @param ff The new value for the "set field flags". + */ + public void setSetFieldFlags( Integer ff ) + { + COSInteger value = null; + if( ff != null ) + { + value = new COSInteger( ff.intValue() ); + } + field.setItem( "SetFf", value ); + } + + /** + * This will get the field flags that are associated with this field. The SetFf entry + * in the FDF field dictionary. + * + * @param ff The new value for the "set field flags". + */ + public void setSetFieldFlags( int ff ) + { + field.setItem( "SetFf", new COSInteger( ff ) ); + } + + /** + * This will get the ClrFf entry of the cos dictionary. If it it not present then + * this method will return null. + * + * @return The field flags. + */ + public Integer getClearFieldFlags() + { + Integer retval = null; + COSNumber ff = (COSNumber)field.getDictionaryObject( "ClrFf" ); + if( ff != null ) + { + retval = new Integer( ff.intValue() ); + } + return retval; + } + + /** + * This will get the field flags that are associated with this field. The ClrFf entry + * in the FDF field dictionary. + * + * @param ff The new value for the "clear field flags". + */ + public void setClearFieldFlags( Integer ff ) + { + COSInteger value = null; + if( ff != null ) + { + value = new COSInteger( ff.intValue() ); + } + field.setItem( "ClrFf", value ); + } + + /** + * This will get the field flags that are associated with this field. The ClrFf entry + * in the FDF field dictionary. + * + * @param ff The new value for the "clear field flags". + */ + public void setClearFieldFlags( int ff ) + { + field.setItem( "ClrFf", new COSInteger( ff ) ); + } + + /** + * This will get the F entry of the cos dictionary. If it it not present then + * this method will return null. + * + * @return The widget field flags. + */ + public Integer getWidgetFieldFlags() + { + Integer retval = null; + COSNumber f = (COSNumber)field.getDictionaryObject( "F" ); + if( f != null ) + { + retval = new Integer( f.intValue() ); + } + return retval; + } + + /** + * This will get the widget field flags that are associated with this field. The F entry + * in the FDF field dictionary. + * + * @param f The new value for the field flags. + */ + public void setWidgetFieldFlags( Integer f ) + { + COSInteger value = null; + if( f != null ) + { + value = new COSInteger( f.intValue() ); + } + field.setItem( "F", value ); + } + + /** + * This will get the field flags that are associated with this field. The F entry + * in the FDF field dictionary. + * + * @param f The new value for the field flags. + */ + public void setWidgetFieldFlags( int f ) + { + field.setItem( "F", new COSInteger( f ) ); + } + + /** + * This will get the SetF entry of the cos dictionary. If it it not present then + * this method will return null. + * + * @return The field flags. + */ + public Integer getSetWidgetFieldFlags() + { + Integer retval = null; + COSNumber ff = (COSNumber)field.getDictionaryObject( "SetF" ); + if( ff != null ) + { + retval = new Integer( ff.intValue() ); + } + return retval; + } + + /** + * This will get the widget field flags that are associated with this field. The SetF entry + * in the FDF field dictionary. + * + * @param ff The new value for the "set widget field flags". + */ + public void setSetWidgetFieldFlags( Integer ff ) + { + COSInteger value = null; + if( ff != null ) + { + value = new COSInteger( ff.intValue() ); + } + field.setItem( "SetF", value ); + } + + /** + * This will get the widget field flags that are associated with this field. The SetF entry + * in the FDF field dictionary. + * + * @param ff The new value for the "set widget field flags". + */ + public void setSetWidgetFieldFlags( int ff ) + { + field.setItem( "SetF", new COSInteger( ff ) ); + } + + /** + * This will get the ClrF entry of the cos dictionary. If it it not present then + * this method will return null. + * + * @return The widget field flags. + */ + public Integer getClearWidgetFieldFlags() + { + Integer retval = null; + COSNumber ff = (COSNumber)field.getDictionaryObject( "ClrF" ); + if( ff != null ) + { + retval = new Integer( ff.intValue() ); + } + return retval; + } + + /** + * This will get the field flags that are associated with this field. The ClrF entry + * in the FDF field dictionary. + * + * @param ff The new value for the "clear widget field flags". + */ + public void setClearWidgetFieldFlags( Integer ff ) + { + COSInteger value = null; + if( ff != null ) + { + value = new COSInteger( ff.intValue() ); + } + field.setItem( "ClrF", value ); + } + + /** + * This will get the field flags that are associated with this field. The ClrF entry + * in the FDF field dictionary. + * + * @param ff The new value for the "clear field flags". + */ + public void setClearWidgetFieldFlags( int ff ) + { + field.setItem( "ClrF", new COSInteger( ff ) ); + } + + /** + * This will get the appearance dictionary that specifies the appearance of + * a pushbutton field. + * + * @return The AP entry of this dictionary. + */ + public PDAppearanceDictionary getAppearanceDictionary() + { + PDAppearanceDictionary retval = null; + COSDictionary dict = (COSDictionary)field.getDictionaryObject( "AP" ); + if( dict != null ) + { + retval = new PDAppearanceDictionary( dict ); + } + return retval; + } + + /** + * This will set the appearance dictionary. + * + * @param ap The apperance dictionary. + */ + public void setAppearanceDictionary( PDAppearanceDictionary ap ) + { + field.setItem( "AP", ap ); + } + + /** + * This will get named page references.. + * + * @return The named page references. + */ + public FDFNamedPageReference getAppearanceStreamReference() + { + FDFNamedPageReference retval = null; + COSDictionary ref = (COSDictionary)field.getDictionaryObject( "APRef" ); + if( ref != null ) + { + retval = new FDFNamedPageReference( ref ); + } + return retval; + } + + /** + * This will set the named page references. + * + * @param ref The named page references. + */ + public void setAppearanceStreamReference( FDFNamedPageReference ref ) + { + field.setItem( "APRef", ref ); + } + + /** + * This will get the icon fit that is associated with this field. + * + * @return The IF entry. + */ + public FDFIconFit getIconFit() + { + FDFIconFit retval = null; + COSDictionary dic = (COSDictionary)field.getDictionaryObject( "IF" ); + if( dic != null ) + { + retval = new FDFIconFit( dic ); + } + return retval; + } + + /** + * This will set the icon fit entry. + * + * @param fit The icon fit object. + */ + public void setIconFit( FDFIconFit fit ) + { + field.setItem( "IF", fit ); + } + + /** + * This will return a list of options for a choice field. The value in the + * list will be 1 of 2 types. java.lang.String or FDFOptionElement. + * + * @return A list of all options. + */ + public List getOptions() + { + List retval = null; + COSArray array = (COSArray)field.getDictionaryObject( "Opt" ); + if( array != null ) + { + List objects = new ArrayList(); + for( int i=0; i + * + * To quote the PDF Spec + * "An array of two numbers between 0.0 and 1.0 indicating the fraction of leftover + * space to allocate at the left and bottom of the icon. A value of [0.0 0.0] positions the + * icon at the bottom-left corner of the annotation rectangle; a value of [0.5 0.5] centers it + * within the rectangle. This entry is used only if the icon is scaled proportionally. Default + * value: [0.5 0.5]." + * + * @return The fractional space to allocate. + */ + public PDRange getFractionalSpaceToAllocate() + { + PDRange retval = null; + COSArray array = (COSArray)fit.getDictionaryObject( "A" ); + if( array == null ) + { + retval = new PDRange(); + retval.setMin( .5f ); + retval.setMax( .5f ); + setFractionalSpaceToAllocate( retval ); + } + else + { + retval = new PDRange( array ); + } + return retval; + } + + /** + * This will set frational space to allocate. + * + * @param space The space to allocate. + */ + public void setFractionalSpaceToAllocate( PDRange space ) + { + fit.setItem( "A", space ); + } + + /** + * This will tell if the icon should scale to fit the annotation bounds. Default: false + * + * @return A flag telling if the icon should scale. + */ + public boolean shouldScaleToFitAnnotation() + { + return fit.getBoolean( "FB", false ); + } + + /** + * This will tell the icon to scale. + * + * @param value The flag value. + */ + public void setScaleToFitAnnotation( boolean value ) + { + fit.setBoolean( "FB", value ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/fdf/FDFJavaScript.java b/src/main/java/org/pdfbox/pdmodel/fdf/FDFJavaScript.java new file mode 100644 index 0000000..dfa6b0f --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/fdf/FDFJavaScript.java @@ -0,0 +1,172 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.fdf; + +import java.util.ArrayList; +import java.util.List; + +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSName; + +import org.pdfbox.pdmodel.common.COSObjectable; +import org.pdfbox.pdmodel.common.COSArrayList; +import org.pdfbox.pdmodel.common.PDTextStream; +import org.pdfbox.pdmodel.common.PDNamedTextStream; + +/** + * This represents an FDF JavaScript dictionary that is part of the FDF document. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.2 $ + */ +public class FDFJavaScript implements COSObjectable +{ + private COSDictionary js; + + /** + * Default constructor. + */ + public FDFJavaScript() + { + js = new COSDictionary(); + } + + /** + * Constructor. + * + * @param javaScript The FDF java script. + */ + public FDFJavaScript( COSDictionary javaScript ) + { + js = javaScript; + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSBase getCOSObject() + { + return js; + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSDictionary getCOSDictionary() + { + return js; + } + + /** + * This will get the javascript that is executed before the import. + * + * @return Some javascript code. + */ + public PDTextStream getBefore() + { + return PDTextStream.createTextStream( js.getDictionaryObject( "Before" ) ); + } + + /** + * This will set the javascript code the will get execute before the import. + * + * @param before A reference to some javascript code. + */ + public void setBefore( PDTextStream before ) + { + js.setItem( "Before", before ); + } + + /** + * This will get the javascript that is executed after the import. + * + * @return Some javascript code. + */ + public PDTextStream getAfter() + { + return PDTextStream.createTextStream( js.getDictionaryObject( "After" ) ); + } + + /** + * This will set the javascript code the will get execute after the import. + * + * @param after A reference to some javascript code. + */ + public void setAfter( PDTextStream after ) + { + js.setItem( "After", after ); + } + + /** + * This will return a list of PDNamedTextStream objects. This is the "Doc" + * entry of the pdf document. These will be added to the PDF documents + * javascript name tree. This will not return null. + * + * @return A list of all named javascript entries. + */ + public List getNamedJavaScripts() + { + List retval = null; + COSArray array = (COSArray)js.getDictionaryObject( "Doc" ); + List namedStreams = new ArrayList(); + if( array == null ) + { + array = new COSArray(); + js.setItem( "Doc", array ); + } + for( int i=0; i + + + + + +The fdf package will handle all of the logic used for FDF objects inside of the PDF/FDF document. + + diff --git a/src/main/java/org/pdfbox/pdmodel/font/PDCIDFont.java b/src/main/java/org/pdfbox/pdmodel/font/PDCIDFont.java new file mode 100644 index 0000000..e13b821 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/font/PDCIDFont.java @@ -0,0 +1,248 @@ +/** + * Copyright (c) 2003-2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.font; + +import java.awt.Graphics; + +import java.io.IOException; + +import java.util.HashMap; +import java.util.Map; + +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSInteger; +import org.pdfbox.cos.COSName; +import org.pdfbox.cos.COSNumber; +import org.pdfbox.pdmodel.common.PDRectangle; + +import org.apache.log4j.Logger; + +/** + * This is implementation for the CIDFontType0/CIDFontType2 Fonts. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.7 $ + */ +public abstract class PDCIDFont extends PDFont +{ + private static Logger log = Logger.getLogger(PDCIDFont.class); + + + private Map widthCache = new HashMap(); + + /** + * Constructor. + */ + public PDCIDFont() + { + super(); + } + + /** + * Constructor. + * + * @param fontDictionary The font dictionary according to the PDF specification. + */ + public PDCIDFont( COSDictionary fontDictionary ) + { + super( fontDictionary ); + } + + /** + * @see PDFont#drawString( String, Graphics, float, float, float, float, float ) + */ + public void drawString( String string, Graphics g, float fontSize, + float xScale, float yScale, float x, float y ) + { + throw new RuntimeException( "Not yet implemented" ); + } + + /** + * This will get the fonts bouding box. + * + * @return The fonts bouding box. + * + * @throws IOException If there is an error getting the font bounding box. + */ + public PDRectangle getFontBoundingBox() throws IOException + { + throw new RuntimeException( "Not yet implemented" ); + } + + /** + * This will get the default width. The default value for the default width is 1000. + * + * @return The default width for the glyphs in this font. + */ + public long getDefaultWidth() + { + long dw = 1000; + COSNumber number = (COSNumber)font.getDictionaryObject( COSName.getPDFName( "DW" ) ); + if( number != null ) + { + dw = number.intValue(); + } + return dw; + } + + /** + * This will set the default width for the glyphs of this font. + * + * @param dw The default width. + */ + public void setDefaultWidth( long dw ) + { + font.setItem( COSName.getPDFName( "DW" ), new COSInteger( dw ) ); + } + + /** + * This will get the font width for a character. + * + * @param c The character code to get the width for. + * @param offset The offset into the array. + * @param length The length of the data. + * + * @return The width is in 1000 unit of text space, ie 333 or 777 + * + * @throws IOException If an error occurs while parsing. + */ + public float getFontWidth( byte[] c, int offset, int length ) throws IOException + { + + float retval = 0.0f; + int code = getCodeFromArray( c, offset, length ); + + Float widthFloat = (Float)widthCache.get( new Integer( code ) ); + if( widthFloat == null ) + { + COSArray widths = (COSArray)font.getDictionaryObject( COSName.getPDFName( "W" ) ); + + if( widths != null ) + { + boolean foundWidth = false; + for( int i=0; !foundWidth && i= firstCode.intValue() && + code < firstCode.intValue() + array.size() ) + { + COSNumber rangeWidth = + (COSNumber)array.get( code - firstCode.intValue() ); + retval = rangeWidth.floatValue(); + foundWidth = true; + } + } + else + { + COSNumber secondCode = (COSNumber)next; + i++; + COSNumber rangeWidth = (COSNumber)widths.getObject( i ); + if( code >= firstCode.intValue() && + code <= secondCode.intValue() ) + { + retval = rangeWidth.floatValue(); + foundWidth = true; + } + } + } + widthCache.put( new Integer( code ), new Float( retval ) ); + } + } + else + { + retval = widthFloat.floatValue(); + } + + if(log.isDebugEnabled() ) + { + log.debug( "PDCIDFontType0Font.getFontWidth( code=" + code +" ) retval=" +retval ); + } + return retval; + } + + /** + * This will get the average font width for all characters. + * + * @return The width is in 1000 unit of text space, ie 333 or 777 + * + * @throws IOException If an error occurs while parsing. + */ + public float getAverageFontWidth() throws IOException + { + float totalWidths = 0.0f; + float characterCount = 0.0f; + float defaultWidth = getDefaultWidth(); + COSArray widths = (COSArray)font.getDictionaryObject( COSName.getPDFName( "W" ) ); + + if( widths != null ) + { + for( int i=0; i 0 ) + { + totalWidths += rangeWidth.floatValue(); + characterCount += 1; + } + } + } + } + float average = totalWidths / characterCount; + if( average <= 0 ) + { + average = defaultWidth; + } + return average; + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/font/PDCIDFontType0Font.java b/src/main/java/org/pdfbox/pdmodel/font/PDCIDFontType0Font.java new file mode 100644 index 0000000..4c6589c --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/font/PDCIDFontType0Font.java @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.font; + +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSName; + +import org.apache.log4j.Logger; + +/** + * This is implementation of the CIDFontType0 Font. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.4 $ + */ +public class PDCIDFontType0Font extends PDCIDFont +{ + private static Logger log = Logger.getLogger(PDCIDFontType0Font.class); + + /** + * Constructor. + */ + public PDCIDFontType0Font() + { + super(); + font.setItem( COSName.SUBTYPE, COSName.getPDFName( "CIDFontType0" ) ); + } + + /** + * Constructor. + * + * @param fontDictionary The font dictionary according to the PDF specification. + */ + public PDCIDFontType0Font( COSDictionary fontDictionary ) + { + super( fontDictionary ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/font/PDCIDFontType2Font.java b/src/main/java/org/pdfbox/pdmodel/font/PDCIDFontType2Font.java new file mode 100644 index 0000000..bda6c4a --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/font/PDCIDFontType2Font.java @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.font; + +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSName; + +import org.apache.log4j.Logger; + +/** + * This is implementation of the CIDFontType2 Font. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.3 $ + */ +public class PDCIDFontType2Font extends PDCIDFont +{ + private static Logger log = Logger.getLogger(PDCIDFontType2Font.class); + + /** + * Constructor. + */ + public PDCIDFontType2Font() + { + super(); + font.setItem( COSName.SUBTYPE, COSName.getPDFName( "CIDFontType2" ) ); + } + + /** + * Constructor. + * + * @param fontDictionary The font dictionary according to the PDF specification. + */ + public PDCIDFontType2Font( COSDictionary fontDictionary ) + { + super( fontDictionary ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/font/PDFont.java b/src/main/java/org/pdfbox/pdmodel/font/PDFont.java new file mode 100644 index 0000000..593c8b0 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/font/PDFont.java @@ -0,0 +1,863 @@ +/** + * Copyright (c) 2003-2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.font; + +import org.pdfbox.afmparser.AFMParser; + +import org.pdfbox.afmtypes.FontMetric; + +import org.pdfbox.cmapparser.CMapParser; + +import org.pdfbox.cmaptypes.CMap; + +import org.pdfbox.encoding.AFMEncoding; +import org.pdfbox.encoding.DictionaryEncoding; +import org.pdfbox.encoding.Encoding; +import org.pdfbox.encoding.EncodingManager; + +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSFloat; +import org.pdfbox.cos.COSName; +import org.pdfbox.cos.COSNumber; +import org.pdfbox.cos.COSStream; + +import org.pdfbox.pdmodel.common.COSArrayList; +import org.pdfbox.pdmodel.common.COSObjectable; +import org.pdfbox.pdmodel.common.PDMatrix; +import org.pdfbox.pdmodel.common.PDRectangle; + +import org.pdfbox.util.ResourceLoader; + +import org.apache.log4j.Logger; + +import java.awt.Graphics; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.IOException; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.StringTokenizer; + +/** + * This is the base class for all PDF fonts. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.32 $ + */ +public abstract class PDFont implements COSObjectable +{ + private static Logger log = Logger.getLogger(PDFont.class); + + /** + * The cos dictionary for this font. + */ + protected COSDictionary font; + + /** + * This is only used if this is a font object and it has an encoding. + */ + private Encoding fontEncoding = null; + /** + * This is only used if this is a font object and it has an encoding and it is + * a type0 font with a cmap. + */ + private CMap cmap = null; + + private static Map afmResources = null; + private static Map cmapObjects = null; + private static Map afmObjects = null; + private static Map cmapSubstitutions = null; + + static + { + //these are read-only once they are created + afmResources = new HashMap(); + cmapSubstitutions = new HashMap(); + + //these are read-write + cmapObjects = Collections.synchronizedMap( new HashMap() ); + afmObjects = Collections.synchronizedMap( new HashMap() ); + + + afmResources.put( COSName.getPDFName( "Courier-Bold" ), "Resources/afm/Courier-Bold.afm" ); + afmResources.put( COSName.getPDFName( "Courier-BoldOblique" ), "Resources/afm/Courier-BoldOblique.afm" ); + afmResources.put( COSName.getPDFName( "Courier" ), "Resources/afm/Courier.afm" ); + afmResources.put( COSName.getPDFName( "Courier-Oblique" ), "Resources/afm/Courier-Oblique.afm" ); + afmResources.put( COSName.getPDFName( "Helvetica" ), "Resources/afm/Helvetica.afm" ); + afmResources.put( COSName.getPDFName( "Helvetica-Bold" ), "Resources/afm/Helvetica-Bold.afm" ); + afmResources.put( COSName.getPDFName( "Helvetica-BoldOblique" ), "Resources/afm/Helvetica-BoldOblique.afm" ); + afmResources.put( COSName.getPDFName( "Helvetica-Oblique" ), "Resources/afm/Helvetica-Oblique.afm" ); + afmResources.put( COSName.getPDFName( "Symbol" ), "Resources/afm/Symbol.afm" ); + afmResources.put( COSName.getPDFName( "Times-Bold" ), "Resources/afm/Times-Bold.afm" ); + afmResources.put( COSName.getPDFName( "Times-BoldItalic" ), "Resources/afm/Times-BoldItalic.afm" ); + afmResources.put( COSName.getPDFName( "Times-Italic" ), "Resources/afm/Times-Italic.afm" ); + afmResources.put( COSName.getPDFName( "Times-Roman" ), "Resources/afm/Times-Roman.afm" ); + afmResources.put( COSName.getPDFName( "ZapfDingbats" ), "Resources/afm/ZapfDingbats.afm" ); + + cmapSubstitutions.put( "ETenms-B5-H", "ETen-B5-H" ); + cmapSubstitutions.put( "ETenms-B5-V", "ETen-B5-V" ); + } + + /** + * This will clear AFM resources that are stored statically. + * This is usually not a problem unless you want to reclaim + * resources for a long running process. + * + * SPECIAL NOTE: The font calculations are currently in COSObject, which + * is where they will reside until PDFont is mature enough to take them over. + * PDFont is the appropriate place for them and not in COSObject but we need font + * calculations for text extractaion. THIS METHOD WILL BE MOVED OR REMOVED + * TO ANOTHER LOCATION IN A FUTURE VERSION OF PDFBOX. + */ + public static void clearResources() + { + afmObjects.clear(); + cmapObjects.clear(); + } + + /** + * Constructor. + */ + public PDFont() + { + font = new COSDictionary(); + font.setItem( COSName.TYPE, COSName.FONT ); + } + + /** + * Constructor. + * + * @param fontDictionary The font dictionary according to the PDF specification. + */ + public PDFont( COSDictionary fontDictionary ) + { + font = fontDictionary; + } + + /** + * @see COSObjectable#getCOSObject() + */ + public COSBase getCOSObject() + { + return font; + } + + /** + * This will get the font width for a character. + * + * @param c The character code to get the width for. + * @param offset The offset into the array. + * @param length The length of the data. + * + * @return The width is in 1000 unit of text space, ie 333 or 777 + * + * @throws IOException If an error occurs while parsing. + */ + public abstract float getFontWidth( byte[] c, int offset, int length ) throws IOException; + + /** + * This will get the width of this string for this font. + * + * @param string The string to get the width of. + * + * @return The width of the string in 1000 units of text space, ie 333 567... + * + * @throws IOException If there is an error getting the width information. + */ + public float getStringWidth( String string ) throws IOException + { + byte[] data = string.getBytes(); + float totalWidth = 0; + for( int i=0; i= first && code <= last && font.getDictionaryObject( COSName.WIDTHS ) != null ) + { + COSArray widthArray = (COSArray)font.getDictionaryObject( COSName.WIDTHS ); + COSNumber fontWidthObject = (COSNumber)widthArray.get( (int)(code - first) ); + fontWidth = fontWidthObject.floatValue(); + } + else + { + fontWidth = getFontWidthFromAFMFile( code ); + } + } + else + { + fontWidth = getFontWidthFromAFMFile( code ); + } + return fontWidth; + } + + /** + * This will get the average font width for all characters. + * + * @return The width is in 1000 unit of text space, ie 333 or 777 + * + * @throws IOException If an error occurs while parsing. + */ + public float getAverageFontWidth() throws IOException + { + float average = 0.0f; + float totalWidth = 0.0f; + float characterCount = 0.0f; + COSArray widths = (COSArray)font.getDictionaryObject( COSName.WIDTHS ); + if( widths != null ) + { + for( int i=0; i 0 ) + { + totalWidth += fontWidth.floatValue(); + characterCount += 1; + } + } + } + + if( totalWidth > 0 ) + { + average = totalWidth / characterCount; + } + else + { + average = getAverageFontWidthFromAFMFile(); + } + return average; + } + + /** + * This will get the font descriptor for this font. + * + * @return The font descriptor for this font. + * + * @throws IOException If there is an error parsing an AFM file, or unable to + * create a PDFontDescriptor object. + */ + public PDFontDescriptor getFontDescriptor() throws IOException + { + PDFontDescriptor retval = null; + COSDictionary fd = (COSDictionary)font.getDictionaryObject( COSName.getPDFName( "FontDescriptor" ) ); + if( fd == null ) + { + FontMetric afm = getAFM(); + if( afm == null ) + { + throw new IOException( "Error: Can't create font descriptor file" ); + } + retval = new PDFontDescriptorAFM( afm ); + } + else + { + retval = new PDFontDescriptorDictionary( fd ); + } + + return retval; + } + + /** + * This will set the font descriptor. + * + * @param fontDescriptor The font descriptor. + */ + public void setFontDescriptor( PDFontDescriptorDictionary fontDescriptor ) + { + COSDictionary dic = null; + if( fontDescriptor != null ) + { + dic = fontDescriptor.getCOSDictionary(); + } + font.setItem( COSName.getPDFName( "FontDescriptor" ), dic ); + } + + /** + * This will get the ToUnicode stream. + * + * @return The ToUnicode stream. + * @throws IOException If there is an error getting the stream. + */ + public PDStream getToUnicode() throws IOException + { + return PDStream.createFromCOS( font.getDictionaryObject( "ToUnicode" ) ); + } + + /** + * This will set the ToUnicode stream. + * + * @param unicode The unicode stream. + */ + public void setToUnicode( PDStream unicode ) + { + font.setItem( "ToUnicode", unicode ); + } + + /** + * This will get the fonts bounding box. + * + * @return The fonts bouding box. + * + * @throws IOException If there is an error getting the bounding box. + */ + public PDRectangle getFontBoundingBox() throws IOException + { + return getFontDescriptor().getFontBoundingBox(); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/font/PDTrueTypeFont.java b/src/main/java/org/pdfbox/pdmodel/font/PDTrueTypeFont.java new file mode 100644 index 0000000..d462255 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/font/PDTrueTypeFont.java @@ -0,0 +1,437 @@ +/** + * Copyright (c) 2003-2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.font; + +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSName; + +import org.pdfbox.pdmodel.PDDocument; + +import org.pdfbox.pdmodel.common.PDRectangle; +import org.pdfbox.pdmodel.common.PDStream; + +import org.pdfbox.encoding.WinAnsiEncoding; + +import org.pdfbox.ttf.CMAPEncodingEntry; +import org.pdfbox.ttf.CMAPTable; +import org.pdfbox.ttf.GlyphData; +import org.pdfbox.ttf.GlyphTable; +import org.pdfbox.ttf.HeaderTable; +import org.pdfbox.ttf.HorizontalHeaderTable; +import org.pdfbox.ttf.HorizontalMetricsTable; +import org.pdfbox.ttf.MemoryTTFDataStream; +import org.pdfbox.ttf.NamingTable; +import org.pdfbox.ttf.NameRecord; +import org.pdfbox.ttf.OS2WindowsMetricsTable; +import org.pdfbox.ttf.PostScriptTable; +import org.pdfbox.ttf.TTFParser; +import org.pdfbox.ttf.TrueTypeFont; +import org.pdfbox.util.ResourceLoader; + +import java.awt.Font; +import java.awt.FontFormatException; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.geom.AffineTransform; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * This is the TrueType implementation of fonts. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.14 $ + */ +public class PDTrueTypeFont extends PDSimpleFont +{ + /** + * This is the key to a property in the Resources/PDFBox_External_Fonts.properties file + * to load a Font when a mapping does not exist for the current font. + */ + public static final String UNKNOWN_FONT = "UNKNOWN_FONT"; + + private Font awtFont = null; + + private static Properties externalFonts = new Properties(); + private static Map loadedExternalFonts = new HashMap(); + + static + { + try + { + ResourceLoader.loadProperties( "Resources/PDFBox_External_Fonts.properties", externalFonts ); + } + catch( IOException io ) + { + io.printStackTrace(); + throw new RuntimeException( "Error loading font resources" ); + } + } + + + /** + * Constructor. + */ + public PDTrueTypeFont() + { + super(); + font.setItem( COSName.SUBTYPE, COSName.TRUE_TYPE ); + } + + /** + * Constructor. + * + * @param fontDictionary The font dictionary according to the PDF specification. + */ + public PDTrueTypeFont( COSDictionary fontDictionary ) + { + super( fontDictionary ); + } + + /** + * This will load a TTF font from a font file. + * + * @param doc The PDF document that will hold the embedded font. + * @param file The file on the filesystem that holds the font file. + * @return A true type font. + * @throws IOException If there is an error loading the file data. + */ + public static PDTrueTypeFont loadTTF( PDDocument doc, String file ) throws IOException + { + return loadTTF( doc, new File( file ) ); + } + + /** + * This will load a TTF to be embedding into a document. + * + * @param doc The PDF document that will hold the embedded font. + * @param file A TTF file stream. + * @return A PDF TTF. + * @throws IOException If there is an error loading the data. + */ + public static PDTrueTypeFont loadTTF( PDDocument doc, File file ) throws IOException + { + PDTrueTypeFont retval = new PDTrueTypeFont(); + PDFontDescriptorDictionary fd = new PDFontDescriptorDictionary(); + PDStream fontStream = new PDStream(doc, new FileInputStream( file ), false ); + fontStream.getStream().setInt( COSName.LENGTH1, (int)file.length() ); + fontStream.addCompression(); + fd.setFontFile2( fontStream ); + retval.setFontDescriptor( fd ); + //only support winansi encoding right now, should really + //just use Identity-H with unicode mapping + retval.setEncoding( new WinAnsiEncoding() ); + TrueTypeFont ttf = null; + try + { + TTFParser parser = new TTFParser(); + ttf = parser.parseTTF( file ); + NamingTable naming = ttf.getNaming(); + List records = naming.getNameRecords(); + for( int i=0; i 0 ); + fd.setItalicAngle( ps.getItalicAngle() ); + + String[] names = ps.getGlyphNames(); + if( names != null ) + { + for( int i=0; i= 0 && + widths.get( glyphToCCode[i]-firstChar) == zero ) + { + widths.set( glyphToCCode[i]-firstChar, + new Integer( (int)(widthValues[i]* 1000f)/header.getUnitsPerEm() ) ); + } + } + retval.setWidths( widths ); + + retval.setFirstChar( firstChar ); + retval.setLastChar( firstChar + widths.size()-1 ); + + } + finally + { + if( ttf != null ) + { + ttf.close(); + } + } + + return retval; + } + + /** + * @see PDFont#drawString( String, Graphics, float, float, float, float, float ) + */ + public void drawString( String string, Graphics g, float fontSize, + float xScale, float yScale, float x, float y ) throws IOException + { + PDFontDescriptorDictionary fd = (PDFontDescriptorDictionary)getFontDescriptor(); + if( awtFont == null ) + { + PDStream ttfStream = fd.getFontFile2(); + String fontName = fd.getFontName(); + awtFont = Font.getFont( fontName, null ); + if( ttfStream == null ) + { + //throw new IOException( "Error:TTF Stream is null"); + // Embedded true type programs are optional, + // if there is no stream, we must use an external + // file. + ttfStream = getExternalFontFile2( fd ); + } + if( ttfStream == null ) + { + //if we can't find a font then just fake it. + awtFont = new Font("Arial", Font.PLAIN, 1 ); + } + else + { + try + { + awtFont = Font.createFont( Font.TRUETYPE_FONT, ttfStream.createInputStream() ); + } + catch( FontFormatException e ) + { + throw new IOException( e.getMessage() ); + } + } + } + AffineTransform at = new AffineTransform(); + at.scale( xScale, yScale ); + Graphics2D g2d = (Graphics2D)g; + g2d.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON ); + g2d.setFont( awtFont.deriveFont( at ).deriveFont( fontSize ) ); + g2d.drawString( string, (int)x, (int)y ); + } + + /** + * Permit to load an external TTF Font program file + * + * Created by Pascal Allain + * Vertical7 Inc. + * + * @param fd The font descriptor currently used + * + * @return A PDStream with the Font File program, null if fd is null + * + * @throws IOException If the font is not found + */ + private PDStream getExternalFontFile2(PDFontDescriptorDictionary fd) + throws IOException + { + PDStream retval = null; + + if ( fd != null ) + { + String baseFont = getBaseFont(); + String fontResource = externalFonts.getProperty( UNKNOWN_FONT ); + if( (baseFont != null) && + (externalFonts.containsKey(baseFont)) ) + { + fontResource = externalFonts.getProperty(baseFont); + } + if( fontResource != null ) + { + TrueTypeFont extTTF = (TrueTypeFont)loadedExternalFonts.get( baseFont ); + if( extTTF == null ) + { + TTFParser ttfParser = new TTFParser(); + InputStream is = ResourceLoader.loadResource( fontResource ); + if( is == null ) + { + throw new IOException( "Error missing font resource '" + externalFonts.get(baseFont) + "'" ); + } + MemoryTTFDataStream stream = new MemoryTTFDataStream( is ); + extTTF = ttfParser.parseTTF( stream ); + loadedExternalFonts.put( baseFont, extTTF ); + } + retval = extTTF.getPDStream(); + } + } + + return retval; + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/font/PDType0Font.java b/src/main/java/org/pdfbox/pdmodel/font/PDType0Font.java new file mode 100644 index 0000000..010df33 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/font/PDType0Font.java @@ -0,0 +1,129 @@ +/** + * Copyright (c) 2003-2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.font; + +import java.awt.Graphics; + +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSName; +import org.pdfbox.pdmodel.common.PDRectangle; + +import java.io.IOException; + +/** + * This is implementation of the Type0 Font. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.7 $ + */ +public class PDType0Font extends PDFont +{ + /** + * Constructor. + */ + public PDType0Font() + { + super(); + font.setItem( COSName.SUBTYPE, COSName.getPDFName( "Type0" ) ); + } + + /** + * Constructor. + * + * @param fontDictionary The font dictionary according to the PDF specification. + */ + public PDType0Font( COSDictionary fontDictionary ) + { + super( fontDictionary ); + } + + /** + * @see PDFont#drawString( String, Graphics, float, float, float, float, float ) + */ + public void drawString( String string, Graphics g, float fontSize, + float xScale, float yScale, float x, float y ) + { + throw new RuntimeException( "Not yet implemented" ); + } + + /** + * This will get the fonts bouding box. + * + * @return The fonts bouding box. + * + * @throws IOException If there is an error getting the bounding box. + */ + public PDRectangle getFontBoundingBox() throws IOException + { + throw new RuntimeException( "Not yet implemented" ); + } + + /** + * This will get the font width for a character. + * + * @param c The character code to get the width for. + * @param offset The offset into the array. + * @param length The length of the data. + * + * @return The width is in 1000 unit of text space, ie 333 or 777 + * + * @throws IOException If an error occurs while parsing. + */ + public float getFontWidth( byte[] c, int offset, int length ) throws IOException + { + COSArray descendantFontArray = + (COSArray)font.getDictionaryObject( COSName.getPDFName( "DescendantFonts" ) ); + + COSDictionary descendantFontDictionary = (COSDictionary)descendantFontArray.getObject( 0 ); + PDFont descendentFont = PDFontFactory.createFont( descendantFontDictionary ); + + return descendentFont.getFontWidth( c, offset, length ); + } + + /** + * This will get the average font width for all characters. + * + * @return The width is in 1000 unit of text space, ie 333 or 777 + * + * @throws IOException If an error occurs while parsing. + */ + public float getAverageFontWidth() throws IOException + { + COSArray descendantFontArray = + (COSArray)font.getDictionaryObject( COSName.getPDFName( "DescendantFonts" ) ); + + COSDictionary descendantFontDictionary = (COSDictionary)descendantFontArray.getObject( 0 ); + PDFont descendentFont = PDFontFactory.createFont( descendantFontDictionary ); + + return descendentFont.getAverageFontWidth(); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/font/PDType1AfmPfbFont.java b/src/main/java/org/pdfbox/pdmodel/font/PDType1AfmPfbFont.java new file mode 100644 index 0000000..89fdc5e --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/font/PDType1AfmPfbFont.java @@ -0,0 +1,206 @@ +/** + * Copyright (c) 2004-2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ + +package org.pdfbox.pdmodel.font; + +import java.io.BufferedInputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.pdfbox.afmparser.AFMParser; +import org.pdfbox.afmtypes.CharMetric; +import org.pdfbox.afmtypes.FontMetric; +import org.pdfbox.encoding.AFMEncoding; +import org.pdfbox.pdmodel.PDDocument; +import org.pdfbox.pdmodel.common.PDRectangle; +import org.pdfbox.pdmodel.common.PDStream; +import org.pdfbox.pfb.PfbParser; + +/** + * This is implementation of the Type1 Font + * with a afm and a pfb file. + * + * @author Michael Niedermair + * @version $Revision: 1.3 $ + */ +public class PDType1AfmPfbFont extends PDType1Font +{ + /** + * the buffersize. + */ + private static final int BUFFERSIZE = 0xffff; + + /** + * The font descriptor. + */ + private PDFontDescriptorDictionary fd; + + /** + * the font metric. + */ + private FontMetric metric; + + /** + * Create a new object. + * @param doc The PDF document that will hold the embedded font. + * @param afmname The font filename. + * @throws IOException If there is an error loading the data. + */ + public PDType1AfmPfbFont(final PDDocument doc, final String afmname) + throws IOException + { + + super(); + + InputStream afmin = new BufferedInputStream( + new FileInputStream(afmname), BUFFERSIZE); + String pfbname = afmname.replaceAll(".AFM", "").replaceAll(".afm", "") + + ".pfb"; + InputStream pfbin = new BufferedInputStream( + new FileInputStream(pfbname), BUFFERSIZE); + + load(doc, afmin, pfbin); + } + + /** + * Create a new object. + * @param doc The PDF document that will hold the embedded font. + * @param afm The afm input. + * @param pfb The pfb input. + * @throws IOException If there is an error loading the data. + */ + public PDType1AfmPfbFont(final PDDocument doc, final InputStream afm, final InputStream pfb) + throws IOException + { + super(); + + load(doc, afm, pfb); + } + + /** + * This will load a afm and pfb to be embedding into a document. + * + * @param doc The PDF document that will hold the embedded font. + * @param afm The afm input. + * @param pfb The pfb input. + * @throws IOException If there is an error loading the data. + */ + private void load(final PDDocument doc, final InputStream afm, + final InputStream pfb) throws IOException + { + + fd = new PDFontDescriptorDictionary(); + setFontDescriptor(fd); + + // read the pfb + PfbParser pfbparser = new PfbParser(pfb); + pfb.close(); + + PDStream fontStream = new PDStream(doc, pfbparser.getInputStream(), + false); + fontStream.getStream().setInt("Length", pfbparser.size()); + for (int i = 0; i < pfbparser.getLengths().length; i++) + { + fontStream.getStream().setInt("Length" + (i + 1), + pfbparser.getLengths()[i]); + } + fontStream.addCompression(); + fd.setFontFile(fontStream); + + // read the afm + AFMParser parser = new AFMParser(afm); + parser.parse(); + metric = parser.getResult(); + setEncoding(new AFMEncoding(metric)); + + // set the values + setBaseFont(metric.getFontName()); + fd.setFontName(metric.getFontName()); + fd.setFontFamily(metric.getFamilyName()); + fd.setNonSymbolic(true); + fd.setFontBoundingBox(new PDRectangle(metric.getFontBBox())); + fd.setItalicAngle(metric.getItalicAngle()); + fd.setAscent(metric.getAscender()); + fd.setDescent(metric.getDescender()); + fd.setCapHeight(metric.getCapHeight()); + fd.setXHeight(metric.getXHeight()); + fd.setAverageWidth(metric.getAverageCharacterWidth()); + fd.setCharacterSet(metric.getCharacterSet()); + + // get firstchar, lastchar + int firstchar = 255; + int lastchar = 0; + + // widths + List listmetric = metric.getCharMetrics(); + + int maxWidths = 256; + List widths = new ArrayList(maxWidths); + Integer zero = new Integer(0); + Iterator iter = listmetric.iterator(); + while (iter.hasNext()) + { + CharMetric m = (CharMetric) iter.next(); + int n = m.getCharacterCode(); + if (n > 0) + { + firstchar = Math.min(firstchar, n); + lastchar = Math.max(lastchar, n); + if (m.getWx() > 0) + { + float width = m.getWx(); + widths.add(new Float(width)); + } + else + { + widths.add(zero); + } + } + } + setFirstChar(firstchar); + setLastChar(lastchar); + setWidths(widths); + + } + + /** + * @see org.pdfbox.pdmodel.font.PDSimpleFont#getFontDescriptor() + */ + public PDFontDescriptor getFontDescriptor() throws IOException + { + return fd; + } + +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/font/PDType1Font.java b/src/main/java/org/pdfbox/pdmodel/font/PDType1Font.java new file mode 100644 index 0000000..891f7c9 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/font/PDType1Font.java @@ -0,0 +1,267 @@ +/** + * Copyright (c) 2004-2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.font; + +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.geom.AffineTransform; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSName; + +/** + * This is implementation of the Type1 Font. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.10 $ + */ +public class PDType1Font extends PDSimpleFont +{ + /** + * Standard Base 14 Font. + */ + public static final PDType1Font TIMES_ROMAN = new PDType1Font( "Times-Roman" ); + /** + * Standard Base 14 Font. + */ + public static final PDType1Font TIMES_BOLD = new PDType1Font( "Times-Bold" ); + /** + * Standard Base 14 Font. + */ + public static final PDType1Font TIMES_ITALIC = new PDType1Font( "Times-Italic" ); + /** + * Standard Base 14 Font. + */ + public static final PDType1Font TIMES_BOLD_ITALIC = new PDType1Font( "Times-BoldItalic" ); + /** + * Standard Base 14 Font. + */ + public static final PDType1Font HELVETICA = new PDType1Font( "Helvetica" ); + /** + * Standard Base 14 Font. + */ + public static final PDType1Font HELVETICA_BOLD = new PDType1Font( "Helvetica-Bold" ); + /** + * Standard Base 14 Font. + */ + public static final PDType1Font HELVETICA_OBLIQUE = new PDType1Font( "Helvetica-Oblique" ); + /** + * Standard Base 14 Font. + */ + public static final PDType1Font HELVETICA_BOLD_OBLIQUE = new PDType1Font( "Helvetica-BoldOblique" ); + /** + * Standard Base 14 Font. + */ + public static final PDType1Font COURIER = new PDType1Font( "Courier" ); + /** + * Standard Base 14 Font. + */ + public static final PDType1Font COURIER_BOLD = new PDType1Font( "Courier-Bold" ); + /** + * Standard Base 14 Font. + */ + public static final PDType1Font COURIER_OBLIQUE = new PDType1Font( "Courier-Oblique" ); + /** + * Standard Base 14 Font. + */ + public static final PDType1Font COURIER_BOLD_OBLIQUE = new PDType1Font( "Courier-BoldOblique" ); + /** + * Standard Base 14 Font. + */ + public static final PDType1Font SYMBOL = new PDType1Font( "Symbol" ); + /** + * Standard Base 14 Font. + */ + public static final PDType1Font ZAPF_DINGBATS = new PDType1Font( "ZapfDingbats" ); + + + private static final Map STANDARD_14 = new HashMap(); + static + { + STANDARD_14.put( TIMES_ROMAN.getBaseFont(), TIMES_ROMAN ); + STANDARD_14.put( TIMES_BOLD.getBaseFont(), TIMES_BOLD ); + STANDARD_14.put( TIMES_ITALIC.getBaseFont(), TIMES_ITALIC ); + STANDARD_14.put( TIMES_BOLD_ITALIC.getBaseFont(), TIMES_BOLD_ITALIC ); + STANDARD_14.put( HELVETICA.getBaseFont(), HELVETICA ); + STANDARD_14.put( HELVETICA_BOLD.getBaseFont(), HELVETICA_BOLD ); + STANDARD_14.put( HELVETICA_OBLIQUE.getBaseFont(), HELVETICA_OBLIQUE ); + STANDARD_14.put( HELVETICA_BOLD_OBLIQUE.getBaseFont(), HELVETICA_BOLD_OBLIQUE ); + STANDARD_14.put( COURIER.getBaseFont(), COURIER ); + STANDARD_14.put( COURIER_BOLD.getBaseFont(), COURIER_BOLD ); + STANDARD_14.put( COURIER_OBLIQUE.getBaseFont(), COURIER_OBLIQUE ); + STANDARD_14.put( COURIER_BOLD_OBLIQUE.getBaseFont(), COURIER_BOLD_OBLIQUE ); + STANDARD_14.put( SYMBOL.getBaseFont(), SYMBOL ); + STANDARD_14.put( ZAPF_DINGBATS.getBaseFont(), ZAPF_DINGBATS ); + } + + private Font awtFont = null; + + /** + * Constructor. + */ + public PDType1Font() + { + super(); + font.setItem( COSName.SUBTYPE, COSName.getPDFName( "Type1" ) ); + } + + /** + * Constructor. + * + * @param fontDictionary The font dictionary according to the PDF specification. + */ + public PDType1Font( COSDictionary fontDictionary ) + { + super( fontDictionary ); + } + + /** + * Constructor. + * + * @param baseFont The base font for this font. + */ + public PDType1Font( String baseFont ) + { + this(); + setBaseFont( baseFont ); + } + + /** + * A convenience method to get one of the standard 14 font from name. + * + * @param name The name of the font to get. + * + * @return The font that matches the name or null if it does not exist. + */ + public static PDType1Font getStandardFont( String name ) + { + return (PDType1Font)STANDARD_14.get( name ); + } + + /** + * This will get the names of the standard 14 fonts. + * + * @return An array of the names of the standard 14 fonts. + */ + public static String[] getStandard14Names() + { + return (String[])STANDARD_14.keySet().toArray( new String[14] ); + } + + /** + * @see PDFont#drawString( String, Graphics, float, float, float, float, float ) + */ + public void drawString( String string, Graphics g, float fontSize, + float xScale, float yScale, float x, float y ) throws IOException + { + if( awtFont == null ) + { + String baseFont = this.getBaseFont(); + if( baseFont.equals( TIMES_ROMAN.getBaseFont() ) ) + { + awtFont = new Font( "Times New Roman", Font.PLAIN, 1 ); + } + else if( baseFont.equals( TIMES_ITALIC.getBaseFont() ) ) + { + awtFont = new Font( "Times New Roman", Font.ITALIC, 1 ); + } + else if( baseFont.equals( TIMES_BOLD.getBaseFont() ) ) + { + awtFont = new Font( "Times New Roman", Font.BOLD, 1 ); + } + else if( baseFont.equals( TIMES_BOLD_ITALIC.getBaseFont() ) ) + { + awtFont = new Font( "Times New Roman", Font.BOLD | Font.ITALIC, 1 ); + } + else if( baseFont.equals( HELVETICA.getBaseFont() ) ) + { + awtFont = new Font( "Helvetica", Font.PLAIN, 1 ); + } + else if( baseFont.equals( HELVETICA_BOLD.getBaseFont() ) ) + { + awtFont = new Font( "Helvetica", Font.BOLD, 1 ); + } + else if( baseFont.equals( HELVETICA_BOLD_OBLIQUE.getBaseFont() ) ) + { + awtFont = new Font( "Helvetica", Font.BOLD | Font.ITALIC, 1 ); + } + else if( baseFont.equals( HELVETICA_OBLIQUE.getBaseFont() ) ) + { + awtFont = new Font( "Helvetica", Font.ITALIC, 1 ); + } + else if( baseFont.equals( COURIER.getBaseFont() ) ) + { + awtFont = new Font( "Courier", Font.PLAIN, 1 ); + } + else if( baseFont.equals( COURIER_BOLD.getBaseFont() ) ) + { + awtFont = new Font( "Courier", Font.BOLD, 1 ); + } + else if( baseFont.equals( COURIER_BOLD_OBLIQUE.getBaseFont() ) ) + { + awtFont = new Font( "Courier", Font.BOLD | Font.ITALIC, 1 ); + } + else if( baseFont.equals( COURIER_OBLIQUE.getBaseFont() ) ) + { + awtFont = new Font( "Courier", Font.ITALIC, 1 ); + } + else if( baseFont.equals( SYMBOL.getBaseFont() ) ) + { + awtFont = new Font( "Symbol", Font.PLAIN, 1 ); + } + else if( baseFont.equals( ZAPF_DINGBATS.getBaseFont() ) ) + { + awtFont = new Font( "ZapfDingbats", Font.PLAIN, 1 ); + } + else + { + awtFont = new Font( "Arial", Font.PLAIN, 1 ); + //throw new IOException( "Not yet implemented:" + getClass().getName() + " " + + //this.getBaseFont() + + //" " + this + " " + TIMES_ROMAN ); + } + } + AffineTransform at = new AffineTransform(); + at.scale( xScale, yScale ); + + Graphics2D g2d = (Graphics2D)g; + g2d.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON ); + g2d.setFont( awtFont.deriveFont( at ).deriveFont( fontSize ) ); + //g2d.getFontRenderContext().getTransform().scale( xScale, yScale ); + + g2d.drawString( string, (int)x, (int)y ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/font/PDType3Font.java b/src/main/java/org/pdfbox/pdmodel/font/PDType3Font.java new file mode 100644 index 0000000..5f9c363 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/font/PDType3Font.java @@ -0,0 +1,152 @@ +/** + * Copyright (c) 2003-2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.font; + +import org.apache.log4j.Logger; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSName; +import org.pdfbox.cos.COSStream; +import org.pdfbox.pdmodel.common.PDMatrix; + +import java.awt.Graphics; +import java.awt.Image; + +import java.io.IOException; + +import java.util.HashMap; +import java.util.Map; + +/** + * This is implementation of the Type3 Font. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.6 $ + */ +public class PDType3Font extends PDSimpleFont +{ + private static Logger log = Logger.getLogger( PDType3Font.class ); + + //A map of character code to java.awt.Image for the glyph + private Map images = new HashMap(); + + /** + * Constructor. + */ + public PDType3Font() + { + super(); + font.setItem( COSName.SUBTYPE, COSName.getPDFName( "Type3" ) ); + } + + /** + * Constructor. + * + * @param fontDictionary The font dictionary according to the PDF specification. + */ + public PDType3Font( COSDictionary fontDictionary ) + { + super( fontDictionary ); + } + + /** + * Type3 fonts have their glyphs defined as a content stream. This + * will create the image that represents that character + * + * @throws IOException If there is an error creating the image. + */ + private Image createImageIfNecessary( char character ) throws IOException + { + Character c = new Character( character ); + Image retval = (Image)images.get( c ); + if( retval == null ) + { + COSDictionary charProcs = (COSDictionary)font.getDictionaryObject( COSName.getPDFName( "CharProcs" ) ); + COSStream stream = (COSStream)charProcs.getDictionaryObject( COSName.getPDFName( "" + character ) ); + if( stream != null ) + { + Type3StreamParser parser = new Type3StreamParser(); + retval = parser.createImage( stream ); + images.put( c, retval ); + } + else + { + log.warn( "Error font type 3 image stream is null" ); + } + } + return retval; + + } + + /** + * This will draw a string on a canvas using the font. + * + * @param string The string to draw. + * @param g The graphics to draw onto. + * @param fontSize The size of the font to draw. + * @param x The x coordinate to draw at. + * @param y The y coordinate to draw at. + * + * @throws IOException If there is an error drawing the image on the screen. + */ + public void drawString( String string, Graphics g, float fontSize, float x, float y ) throws IOException + { + //if( string.equals( "V" )|| string.equals( "o" ) ) + { + for(int i=0; i 0 && newHeight > 0 ) + { + image = image.getScaledInstance( newWidth, newHeight, Image.SCALE_SMOOTH ); + g.drawImage( image, (int)x, (int)y, null ); + x+=newWidth; + } + } + } + } + } + + /** + * Set the font matrix for this type3 font. + * + * @param matrix The font matrix for this type3 font. + */ + public void setFontMatrix( PDMatrix matrix ) + { + font.setItem( "FontMatrix", matrix ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/font/Type3StreamParser.java b/src/main/java/org/pdfbox/pdmodel/font/Type3StreamParser.java new file mode 100644 index 0000000..a2adc1f --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/font/Type3StreamParser.java @@ -0,0 +1,607 @@ +/** + * Copyright (c) 2003-2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.font; + +import java.awt.Image; + +import java.io.IOException; + +import java.util.List; + +import org.pdfbox.cos.COSNumber; +import org.pdfbox.cos.COSStream; + +import org.pdfbox.pdmodel.graphics.xobject.PDInlinedImage; + +import org.pdfbox.util.BoundingBox; +import org.pdfbox.util.ImageParameters; +import org.pdfbox.util.PDFOperator; +import org.pdfbox.util.PDFStreamEngine; + +/** + * This class will handle creating an image for a type 3 glyph. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.8 $ + */ +public class Type3StreamParser extends PDFStreamEngine +{ + private PDInlinedImage image = null; + private BoundingBox box = null; + + + /** + * This will parse a type3 stream and create an image from it. + * + * @param type3Stream The stream containing the operators to draw the image. + * + * @return The image that was created. + * + * @throws IOException If there is an error processing the stream. + */ + public Image createImage( COSStream type3Stream ) throws IOException + { + processStream( null, null, type3Stream ); + return image.createImage(); + } + + /** + * This is used to handle an operation. + * + * @param operator The operation to perform. + * @param arguments The list of arguments. + * + * @throws IOException If there is an error processing the operation. + */ + protected void processOperator( PDFOperator operator, List arguments ) throws IOException + { + super.processOperator( operator, arguments ); + String operation = operator.getOperation(); + /** + if( operation.equals( "b" ) ) + { + //Close, fill, and stroke path using nonzero winding number rule + } + else if( operation.equals( "B" ) ) + { + //Fill and stroke path using nonzero winding number rule + } + else if( operation.equals( "b*" ) ) + { + //Close, fill, and stroke path using even-odd rule + } + else if( operation.equals( "B*" ) ) + { + //Fill and stroke path using even-odd rule + } + else if( operation.equals( "BDC" ) ) + { + //(PDF 1.2) Begin marked-content sequence with property list + } + else **/if( operation.equals( "BI" ) ) + { + ImageParameters params = operator.getImageParameters(); + image = new PDInlinedImage(); + image.setImageParameters( params ); + image.setImageData( operator.getImageData() ); + //begin inline image object + }/** + else if( operation.equals( "BMC" ) ) + { + //(PDF 1.2) Begin marked-content sequence + } + else if( operation.equals( "BT" ) ) + { + log.debug( "" ); + textMatrix = new Matrix(); + textLineMatrix = new Matrix(); + } + else if( operation.equals( "BX" ) ) + { + //(PDF 1.1) Begin compatibility section + } + else if( operation.equals( "c" ) ) + { + //Append curved segment to path (three control points) + } + else if( operation.equals( "cm" ) ) + { + } + else if( operation.equals( "cs" ) ) + { + } + else if( operation.equals( "CS" ) ) + { + } + else if( operation.equals( "d" ) ) + { + //Set the line dash pattern in the graphics state + } + else */if( operation.equals( "d0" ) ) + { + //set glyph with for a type3 font + //COSNumber horizontalWidth = (COSNumber)arguments.get( 0 ); + //COSNumber verticalWidth = (COSNumber)arguments.get( 1 ); + //width = horizontalWidth.intValue(); + //height = verticalWidth.intValue(); + } + else if( operation.equals( "d1" ) ) + { + //set glyph with and bounding box for type 3 font + //COSNumber horizontalWidth = (COSNumber)arguments.get( 0 ); + //COSNumber verticalWidth = (COSNumber)arguments.get( 1 ); + COSNumber llx = (COSNumber)arguments.get( 2 ); + COSNumber lly = (COSNumber)arguments.get( 3 ); + COSNumber urx = (COSNumber)arguments.get( 4 ); + COSNumber ury = (COSNumber)arguments.get( 5 ); + + //width = horizontalWidth.intValue(); + //height = verticalWidth.intValue(); + box = new BoundingBox(); + box.setLowerLeftX( llx.floatValue() ); + box.setLowerLeftY( lly.floatValue() ); + box.setUpperRightX( urx.floatValue() ); + box.setUpperRightY( ury.floatValue() ); + }/* + else if( operation.equals( "Do" ) ) + { + //invoke named object. + } + else if( operation.equals( "DP" ) ) + { + //(PDF 1.2) De.ne marked-content point with property list + } + else if( operation.equals( "EI" ) ) + { + //end inline image object + } + else if( operation.equals( "EMC" ) ) + { + //End inline image object + } + else if( operation.equals( "ET" ) ) + { + log.debug( "" ); + textMatrix = null; + textLineMatrix = null; + } + else if( operation.equals( "EX" ) ) + { + //(PDF 1.1) End compatibility section + } + else if( operation.equals( "f" ) ) + { + //Fill the path, using the nonzero winding number rule to determine the region to .ll + } + else if( operation.equals( "F" ) ) + { + } + else if( operation.equals( "f*" ) ) + { + //Fill path using even-odd rule + } + else if( operation.equals( "g" ) ) + { + } + else if( operation.equals( "G" ) ) + { + } + else if( operation.equals( "gs" ) ) + { + } + else if( operation.equals( "h" ) ) + { + //close subpath + } + else if( operation.equals( "i" ) ) + { + //set flatness tolerance, not sure what this does + } + else if( operation.equals( "ID" ) ) + { + //begin inline image data + } + else if( operation.equals( "j" ) ) + { + //Set the line join style in the graphics state + //System.out.println( "" ); + } + else if( operation.equals( "J" ) ) + { + //Set the line cap style in the graphics state + //System.out.println( "" ); + } + else if( operation.equals( "k" ) ) + { + //Set CMYK color for nonstroking operations + } + else if( operation.equals( "K" ) ) + { + //Set CMYK color for stroking operations + } + else if( operation.equals( "l" ) ) + { + //append straight line segment from the current point to the point. + COSNumber x = (COSNumber)arguments.get( 0 ); + COSNumber y = (COSNumber)arguments.get( 1 ); + linePath.lineTo( x.floatValue(), pageSize.getHeight()-y.floatValue() ); + } + else if( operation.equals( "m" ) ) + { + COSNumber x = (COSNumber)arguments.get( 0 ); + COSNumber y = (COSNumber)arguments.get( 1 ); + linePath.reset(); + linePath.moveTo( x.floatValue(), pageSize.getHeight()-y.floatValue() ); + //System.out.println( "" ); + } + else if( operation.equals( "M" ) ) + { + //System.out.println( "" ); + } + else if( operation.equals( "MP" ) ) + { + //(PDF 1.2) Define marked-content point + } + else if( operation.equals( "n" ) ) + { + //End path without .lling or stroking + //System.out.println( "" ); + } + else if( operation.equals( "q" ) ) + { + //save graphics state + if( log.isDebugEnabled() ) + { + log.debug( "<" + operation + "> - save state" ); + } + graphicsStack.push(graphicsState.clone()); + } + else if( operation.equals( "Q" ) ) + { + //restore graphics state + if( log.isDebugEnabled() ) + { + log.debug( "<" + operation + "> - restore state" ); + } + graphicsState = (PDGraphicsState)graphicsStack.pop(); + } + else if( operation.equals( "re" ) ) + { + } + else if( operation.equals( "rg" ) ) + { + //Set RGB color for nonstroking operations + } + else if( operation.equals( "RG" ) ) + { + //Set RGB color for stroking operations + } + else if( operation.equals( "ri" ) ) + { + //Set color rendering intent + } + else if( operation.equals( "s" ) ) + { + //Close and stroke path + } + else if( operation.equals( "S" ) ) + { + graphics.draw( linePath ); + } + else if( operation.equals( "sc" ) ) + { + //set color for nonstroking operations + //System.out.println( "" ); + } + else if( operation.equals( "SC" ) ) + { + //set color for stroking operations + //System.out.println( "" ); + } + else if( operation.equals( "scn" ) ) + { + //set color for nonstroking operations special + } + else if( operation.equals( "SCN" ) ) + { + //set color for stroking operations special + } + else if( operation.equals( "sh" ) ) + { + //(PDF 1.3) Paint area de.ned by shading pattern + } + else if( operation.equals( "T*" ) ) + { + if (log.isDebugEnabled()) + { + log.debug(""); + } + //move to start of next text line + if( graphicsState.getTextState().getLeading() == 0 ) + { + graphicsState.getTextState().setLeading( -.01f ); + } + Matrix td = new Matrix(); + td.setValue( 2, 1, -1 * graphicsState.getTextState().getLeading() * textMatrix.getValue(1,1)); + textLineMatrix = textLineMatrix.multiply( td ); + textMatrix = textLineMatrix.copy(); + } + else if( operation.equals( "Tc" ) ) + { + //set character spacing + COSNumber characterSpacing = (COSNumber)arguments.get( 0 ); + if (log.isDebugEnabled()) + { + log.debug(""); + } + graphicsState.getTextState().setCharacterSpacing( characterSpacing.floatValue() ); + } + else if( operation.equals( "Td" ) ) + { + COSNumber x = (COSNumber)arguments.get( 0 ); + COSNumber y = (COSNumber)arguments.get( 1 ); + if (log.isDebugEnabled()) + { + log.debug(""); + } + Matrix td = new Matrix(); + td.setValue( 2, 0, x.floatValue() * textMatrix.getValue(0,0) ); + td.setValue( 2, 1, y.floatValue() * textMatrix.getValue(1,1) ); + //log.debug( "textLineMatrix before " + textLineMatrix ); + textLineMatrix = textLineMatrix.multiply( td ); + //log.debug( "textLineMatrix after " + textLineMatrix ); + textMatrix = textLineMatrix.copy(); + } + else if( operation.equals( "TD" ) ) + { + //move text position and set leading + COSNumber x = (COSNumber)arguments.get( 0 ); + COSNumber y = (COSNumber)arguments.get( 1 ); + if (log.isDebugEnabled()) + { + log.debug(""); + } + graphicsState.getTextState().setLeading( -1 * y.floatValue() ); + Matrix td = new Matrix(); + td.setValue( 2, 0, x.floatValue() * textMatrix.getValue(0,0) ); + td.setValue( 2, 1, y.floatValue() * textMatrix.getValue(1,1) ); + //log.debug( "textLineMatrix before " + textLineMatrix ); + textLineMatrix = textLineMatrix.multiply( td ); + //log.debug( "textLineMatrix after " + textLineMatrix ); + textMatrix = textLineMatrix.copy(); + } + else if( operation.equals( "Tf" ) ) + { + //set font and size + COSName fontName = (COSName)arguments.get( 0 ); + graphicsState.getTextState().setFontSize( ((COSNumber)arguments.get( 1 ) ).floatValue() ); + + if (log.isDebugEnabled()) + { + log.debug(""); + } + + //old way + //graphicsState.getTextState().getFont() = (COSObject)stream.getDictionaryObject( fontName ); + //if( graphicsState.getTextState().getFont() == null ) + //{ + // graphicsState.getTextState().getFont() = (COSObject)graphicsState.getTextState().getFont() + // Dictionary.getItem( fontName ); + //} + graphicsState.getTextState().setFont( (PDFont)fonts.get( fontName.getName() ) ); + if( graphicsState.getTextState().getFont() == null ) + { + throw new IOException( "Error: Could not find font(" + fontName + ") in map=" + fonts ); + } + //log.debug( "Font Resource=" + fontResource ); + //log.debug( "Current Font=" + graphicsState.getTextState().getFont() ); + //log.debug( "graphicsState.getTextState().getFontSize()=" + graphicsState.getTextState().getFontSize() ); + } + else if( operation.equals( "Tj" ) ) + { + COSString string = (COSString)arguments.get( 0 ); + TextPosition pos = showString( string.getBytes() ); + if (log.isDebugEnabled()) + { + log.debug(""); + } + } + else if( operation.equals( "TJ" ) ) + { + Matrix td = new Matrix(); + + COSArray array = (COSArray)arguments.get( 0 ); + for( int i=0; i" ); + } + td.setValue( 2, 0, value ); + textMatrix = textMatrix.multiply( td ); + } + else if( next instanceof COSString ) + { + TextPosition pos = showString( ((COSString)next).getBytes() ); + if (log.isDebugEnabled()) + { + log.debug(""); + } + } + else + { + throw new IOException( "Unknown type in array for TJ operation:" + next ); + } + } + } + else if( operation.equals( "TL" ) ) + { + COSNumber leading = (COSNumber)arguments.get( 0 ); + graphicsState.getTextState().setLeading( leading.floatValue() ); + if (log.isDebugEnabled()) + { + log.debug(""); + } + } + else if( operation.equals( "Tm" ) ) + { + //Set text matrix and text line matrix + COSNumber a = (COSNumber)arguments.get( 0 ); + COSNumber b = (COSNumber)arguments.get( 1 ); + COSNumber c = (COSNumber)arguments.get( 2 ); + COSNumber d = (COSNumber)arguments.get( 3 ); + COSNumber e = (COSNumber)arguments.get( 4 ); + COSNumber f = (COSNumber)arguments.get( 5 ); + + if (log.isDebugEnabled()) + { + log.debug(""); + } + + textMatrix = new Matrix(); + textMatrix.setValue( 0, 0, a.floatValue() ); + textMatrix.setValue( 0, 1, b.floatValue() ); + textMatrix.setValue( 1, 0, c.floatValue() ); + textMatrix.setValue( 1, 1, d.floatValue() ); + textMatrix.setValue( 2, 0, e.floatValue() ); + textMatrix.setValue( 2, 1, f.floatValue() ); + textLineMatrix = textMatrix.copy(); + } + else if( operation.equals( "Tr" ) ) + { + //Set text rendering mode + //System.out.println( "" ); + } + else if( operation.equals( "Ts" ) ) + { + //Set text rise + //System.out.println( "" ); + } + else if( operation.equals( "Tw" ) ) + { + //set word spacing + COSNumber wordSpacing = (COSNumber)arguments.get( 0 ); + if (log.isDebugEnabled()) + { + log.debug(""); + } + graphicsState.getTextState().setWordSpacing( wordSpacing.floatValue() ); + } + else if( operation.equals( "Tz" ) ) + { + //Set horizontal text scaling + } + else if( operation.equals( "v" ) ) + { + //Append curved segment to path (initial point replicated) + } + else if( operation.equals( "w" ) ) + { + //Set the line width in the graphics state + //System.out.println( "" ); + } + else if( operation.equals( "W" ) ) + { + //Set clipping path using nonzero winding number rule + //System.out.println( "" ); + } + else if( operation.equals( "W*" ) ) + { + //Set clipping path using even-odd rule + } + else if( operation.equals( "y" ) ) + { + //Append curved segment to path (final point replicated) + } + else if( operation.equals( "'" ) ) + { + // Move to start of next text line, and show text + // + COSString string = (COSString)arguments.get( 0 ); + if (log.isDebugEnabled()) + { + log.debug("<' string=\"" + string.getString() + "\">"); + } + + Matrix td = new Matrix(); + td.setValue( 2, 1, -1 * graphicsState.getTextState().getLeading() * textMatrix.getValue(1,1)); + textLineMatrix = textLineMatrix.multiply( td ); + textMatrix = textLineMatrix.copy(); + + showString( string.getBytes() ); + } + else if( operation.equals( "\"" ) ) + { + //Set word and character spacing, move to next line, and show text + // + COSNumber wordSpacing = (COSNumber)arguments.get( 0 ); + COSNumber characterSpacing = (COSNumber)arguments.get( 1 ); + COSString string = (COSString)arguments.get( 2 ); + + if (log.isDebugEnabled()) + { + log.debug("<\" wordSpacing=\"" + wordSpacing + + "\", characterSpacing=\"" + characterSpacing + + "\", string=\"" + string.getString() + "\">"); + } + + graphicsState.getTextState().setCharacterSpacing( characterSpacing.floatValue() ); + graphicsState.getTextState().setWordSpacing( wordSpacing.floatValue() ); + + Matrix td = new Matrix(); + td.setValue( 2, 1, -1 * graphicsState.getTextState().getLeading() * textMatrix.getValue(1,1)); + textLineMatrix = textLineMatrix.multiply( td ); + textMatrix = textLineMatrix.copy(); + + showString( string.getBytes() ); + }*/ + } + + +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/font/package.html b/src/main/java/org/pdfbox/pdmodel/font/package.html new file mode 100644 index 0000000..4e8d27e --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/font/package.html @@ -0,0 +1,9 @@ + + + + + + +Classes to deal with font functionality in a PDF Document. + + diff --git a/src/main/java/org/pdfbox/pdmodel/graphics/PDExtendedGraphicsState.java b/src/main/java/org/pdfbox/pdmodel/graphics/PDExtendedGraphicsState.java new file mode 100644 index 0000000..3fe9c40 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/graphics/PDExtendedGraphicsState.java @@ -0,0 +1,724 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.graphics; + +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSBoolean; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSFloat; +import org.pdfbox.cos.COSInteger; +import org.pdfbox.cos.COSName; +import org.pdfbox.cos.COSNumber; + +import org.pdfbox.pdmodel.common.COSObjectable; + +import java.io.IOException; + +import java.util.Iterator; + +/** + * This class represents the graphics state dictionary that is stored in the PDF document. + * The PDGraphicsStateValue holds the current runtime values as a stream is being executed. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.4 $ + */ +public class PDExtendedGraphicsState implements COSObjectable +{ + private static final COSName LW = COSName.getPDFName( "LW" ); + private static final COSName LC = COSName.getPDFName( "LC" ); + private static final COSName LJ = COSName.getPDFName( "LJ" ); + private static final COSName ML = COSName.getPDFName( "ML" ); + private static final COSName D = COSName.getPDFName( "D" ); + private static final COSName RI = COSName.getPDFName( "RI" ); + private static final COSName OP = COSName.getPDFName( "OP" ); + private static final COSName OP_NS = COSName.getPDFName( "op" ); + private static final COSName OPM = COSName.getPDFName( "OPM" ); + private static final COSName FONT = COSName.getPDFName( "Font" ); + private static final COSName FL = COSName.getPDFName( "FL" ); + private static final COSName SM = COSName.getPDFName( "SM" ); + private static final COSName SA = COSName.getPDFName( "SA" ); + private static final COSName CA = COSName.getPDFName( "CA" ); + private static final COSName CA_NS = COSName.getPDFName( "ca" ); + private static final COSName AIS = COSName.getPDFName( "AIS" ); + private static final COSName TK = COSName.getPDFName( "TK" ); + + /** + * Rendering intent constants, see PDF Reference 1.5 Section 4.5.4 Rendering Intents. + */ + public static final String RENDERING_INTENT_ABSOLUTE_COLORIMETRIC = "AbsoluteColorimetric"; + /** + * Rendering intent constants, see PDF Reference 1.5 Section 4.5.4 Rendering Intents. + */ + public static final String RENDERING_INTENT_RELATIVE_COLORIMETRIC = "RelativeColorimetric"; + /** + * Rendering intent constants, see PDF Reference 1.5 Section 4.5.4 Rendering Intents. + */ + public static final String RENDERING_INTENT_SATURATION = "Saturation"; + /** + * Rendering intent constants, see PDF Reference 1.5 Section 4.5.4 Rendering Intents. + */ + public static final String RENDERING_INTENT_PERCEPTUAL = "Perceptual"; + + + private COSDictionary graphicsState; + + /** + * Default constructor, creates blank graphics state. + */ + public PDExtendedGraphicsState() + { + graphicsState = new COSDictionary(); + graphicsState.setItem( COSName.TYPE, COSName.getPDFName( "ExtGState" ) ); + } + + /** + * Create a graphics state from an existing dictionary. + * + * @param dictionary The existing graphics state. + */ + public PDExtendedGraphicsState( COSDictionary dictionary ) + { + graphicsState = dictionary; + } + + /** + * This will implement the gs operator. + * + * @param gs The state to copy this dictionaries values into. + * + * @throws IOException If there is an error copying font information. + */ + public void copyIntoGraphicsState( PDGraphicsState gs ) throws IOException + { + Iterator keys = graphicsState.keyList().iterator(); + while( keys.hasNext() ) + { + COSName key = (COSName)keys.next(); + if( key.equals( LW ) ) + { + gs.setLineWidth( getLineWidth().doubleValue() ); + } + else if( key.equals( LC ) ) + { + gs.setLineCap( getLineCapStyle().intValue() ); + } + else if( key.equals( LJ ) ) + { + gs.setLineJoin( getLineJoinStyle().intValue() ); + } + else if( key.equals( ML ) ) + { + gs.setMiterLimit( getMiterLimit().doubleValue() ); + } + else if( key.equals( D ) ) + { + gs.setLineDashPattern( getLineDashPattern() ); + } + else if( key.equals( RI ) ) + { + gs.setRenderingIntent( getRenderingIntent() ); + } + else if( key.equals( OPM ) ) + { + gs.setOverprintMode( getOverprintMode().doubleValue() ); + } + else if( key.equals( FONT ) ) + { + PDFontSetting setting = getFontSetting(); + gs.getTextState().setFont( setting.getFont() ); + gs.getTextState().setFontSize( setting.getFontSize() ); + } + else if( key.equals( FL ) ) + { + gs.setFlatness( getFlatnessTolerance().floatValue() ); + } + else if( key.equals( SM ) ) + { + gs.setSmoothness( getSmoothnessTolerance().floatValue() ); + } + else if( key.equals( SA ) ) + { + gs.setStrokeAdjustment( getAutomaticStrokeAdjustment().booleanValue() ); + } + else if( key.equals( CA ) ) + { + gs.setAlphaConstants( getStrokingAlpaConstant().floatValue() ); + }/** + else if( key.equals( CA_NS ) ) + { + }**/ + else if( key.equals( AIS ) ) + { + gs.setAlphaSource( getAlpaSourceFlag().booleanValue() ); + } + else if( key.equals( TK ) ) + { + gs.getTextState().setKnockoutFlag( getTextKnockoutFlag().booleanValue() ); + } + } + } + + /** + * This will get the underlying dictionary that this class acts on. + * + * @return The underlying dictionary for this class. + */ + public COSDictionary getCOSDictionary() + { + return graphicsState; + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSBase getCOSObject() + { + return graphicsState; + } + + /** + * This will get the line width. This will return null if there is no line width + * + * @return null or the LW value of the dictionary. + */ + public Float getLineWidth() + { + return getFloatItem( LW ); + } + + /** + * This will set the line width. + * + * @param width The line width for the object. + */ + public void setLineWidth( Float width ) + { + setFloatItem( LW, width ); + } + + /** + * This will get the line cap style. + * + * @return null or the LC value of the dictionary. + */ + public Long getLineCapStyle() + { + return getLongItem( LC ); + } + + /** + * This will set the line cap style for the graphics state. + * + * @param style The new line cap style to set. + */ + public void setLineCapStyle( Long style ) + { + setLongItem( LC, style ); + } + + /** + * This will get the line join style. + * + * @return null or the LJ value in the dictionary. + */ + public Long getLineJoinStyle() + { + return getLongItem( LJ ); + } + + /** + * This will set the line join style. + * + * @param style The new line join style. + */ + public void setLineJoinStyle( Long style ) + { + setLongItem( LJ, style ); + } + + + /** + * This will get the miter limit. + * + * @return null or the ML value in the dictionary. + */ + public Float getMiterLimit() + { + return getFloatItem( ML ); + } + + /** + * This will set the miter limit for the graphics state. + * + * @param miterLimit The new miter limit value + */ + public void setMiterLimit( Float miterLimit ) + { + setFloatItem( ML, miterLimit ); + } + + /** + * This will get the dash pattern. + * + * @return null or the D value in the dictionary. + */ + public PDLineDashPattern getLineDashPattern() + { + PDLineDashPattern retval = null; + COSArray dp = (COSArray)graphicsState.getDictionaryObject( D ); + if( dp != null ) + { + retval = new PDLineDashPattern( dp ); + } + return retval; + } + + /** + * This will set the dash pattern for the graphics state. + * + * @param dashPattern The dash pattern + */ + public void setLineDashPattern( PDLineDashPattern dashPattern ) + { + graphicsState.setItem( D, dashPattern.getCOSObject() ); + } + + /** + * This will get the rendering intent. + * + * @return null or the RI value in the dictionary. + */ + public String getRenderingIntent() + { + String retval = null; + COSName ri = (COSName)graphicsState.getDictionaryObject( RI ); + if( ri != null ) + { + retval = ((COSName)ri).getName(); + } + return retval; + } + + /** + * This will set the rendering intent for the graphics state. + * + * @param ri The new rendering intent + */ + public void setRenderingIntent( String ri ) + { + COSName intent = null; + if( ri != null ) + { + intent = COSName.getPDFName( ri ); + } + graphicsState.setItem( RI, intent ); + } + + /** + * This will get the overprint control. + * + * @return The overprint control or null if one has not been set. + */ + public Boolean getStrokingOverprintControl() + { + return getBooleanItem( OP ); + } + + /** + * This will get the overprint control(OP). + * + * @param op The overprint control. + */ + public void setStrokingOverprintControl( Boolean op ) + { + setBooleanItem( OP, op ); + } + + /** + * This will get the overprint control for non stroking operations. If this + * value is null then the regular overprint control value will be returned. + * + * @return The overprint control or null if one has not been set. + */ + public Boolean getNonStrokingOverprintControl() + { + Boolean retval = getBooleanItem( OP_NS ); + if( retval == null ) + { + retval = getStrokingOverprintControl(); + } + return retval; + } + + /** + * This will get the overprint control(OP). + * + * @param op The overprint control. + */ + public void setNonStrokingOverprintControl( Boolean op ) + { + setBooleanItem( OP_NS, op ); + } + + /** + * This will get the overprint control mode. + * + * @return The overprint control mode or null if one has not been set. + */ + public Float getOverprintMode() + { + return getFloatItem( OPM ); + } + + /** + * This will get the overprint mode(OPM). + * + * @param overprintMode The overprint mode + */ + public void setOverprintMode( Float overprintMode ) + { + setFloatItem( OPM, overprintMode ); + } + + /** + * This will get the font setting of the graphics state. + * + * @return The font setting. + */ + public PDFontSetting getFontSetting() + { + PDFontSetting setting = null; + COSArray font = (COSArray)graphicsState.getDictionaryObject( FONT ); + if( font != null ) + { + setting = new PDFontSetting( font ); + } + return setting; + } + + /** + * This will set the font setting for this graphics state. + * + * @param fs The new font setting. + */ + public void setFontSetting( PDFontSetting fs ) + { + graphicsState.setItem( FONT, fs ); + } + + /** + * This will get the flatness tolerance. + * + * @return The flatness tolerance or null if one has not been set. + */ + public Float getFlatnessTolerance() + { + return getFloatItem( FL ); + } + + /** + * This will get the flatness tolerance. + * + * @param flatness The new flatness tolerance + */ + public void setFlatnessTolerance( Float flatness ) + { + setFloatItem( FL, flatness ); + } + + /** + * This will get the smothness tolerance. + * + * @return The smothness tolerance or null if one has not been set. + */ + public Float getSmoothnessTolerance() + { + return getFloatItem( SM ); + } + + /** + * This will get the smoothness tolerance. + * + * @param smoothness The new smoothness tolerance + */ + public void setSmoothnessTolerance( Float smoothness ) + { + setFloatItem( SM, smoothness ); + } + + /** + * This will get the automatic stroke adjustment flag. + * + * @return The automatic stroke adjustment flag or null if one has not been set. + */ + public Boolean getAutomaticStrokeAdjustment() + { + return getBooleanItem( SA ); + } + + /** + * This will get the automatic stroke adjustment flag. + * + * @param sa The new automatic stroke adjustment flag. + */ + public void setAutomaticStrokeAdjustment( Boolean sa ) + { + setBooleanItem( SA, sa ); + } + + /** + * This will get the stroking alpha constant. + * + * @return The stroking alpha constant or null if one has not been set. + */ + public Float getStrokingAlpaConstant() + { + return getFloatItem( CA ); + } + + /** + * This will get the stroking alpha constant. + * + * @param alpha The new stroking alpha constant. + */ + public void setStrokingAlphaConstant( Float alpha ) + { + setFloatItem( CA, alpha ); + } + + /** + * This will get the non stroking alpha constant. + * + * @return The non stroking alpha constant or null if one has not been set. + */ + public Float getNonStrokingAlpaConstant() + { + return getFloatItem( CA_NS ); + } + + /** + * This will get the non stroking alpha constant. + * + * @param alpha The new non stroking alpha constant. + */ + public void setNonStrokingAlphaConstant( Float alpha ) + { + setFloatItem( CA_NS, alpha ); + } + + /** + * This will get the alpha source flag. + * + * @return The alpha source flag. + */ + public Boolean getAlpaSourceFlag() + { + return getBooleanItem( AIS ); + } + + /** + * This will get the alpha source flag. + * + * @param alpha The alpha source flag. + */ + public void setAlphaSourceFlag( Boolean alpha ) + { + setBooleanItem( AIS, alpha ); + } + + /** + * This will get the text knockout flag. + * + * @return The text knockout flag. + */ + public Boolean getTextKnockoutFlag() + { + return getBooleanItem( TK ); + } + + /** + * This will get the text knockout flag. + * + * @param tk The text knockout flag. + */ + public void setTextKnockoutFlag( Boolean tk ) + { + setBooleanItem( TK, tk ); + } + + /** + * This will get a float item from the dictionary. + * + * @param key The key to the item. + * + * @return The value for that item. + */ + private Float getFloatItem( COSName key ) + { + Float retval = null; + COSNumber value = (COSNumber)graphicsState.getDictionaryObject( key ); + if( value != null ) + { + retval = new Float( value.floatValue() ); + } + return retval; + } + + /** + * This will set a float object. + * + * @param key The key to the data that we are setting. + * @param value The value that we are setting. + */ + private void setFloatItem( COSName key, Float value ) + { + if( value == null ) + { + graphicsState.removeItem( key ); + } + else + { + graphicsState.setItem( key, new COSFloat( value.floatValue() ) ); + } + } + + /** + * This will get a integer item from the dictionary. + * + * @param key The key to the item. + * + * @return The value for that item. + */ + private Integer getIntegerItem( COSName key ) + { + Integer retval = null; + COSNumber value = (COSNumber)graphicsState.getDictionaryObject( key ); + if( value != null ) + { + retval = new Integer( value.intValue() ); + } + return retval; + } + + /** + * This will set a integer object. + * + * @param key The key to the data that we are setting. + * @param value The value that we are setting. + */ + private void setIntegerItem( COSName key, Integer value ) + { + if( value == null ) + { + graphicsState.removeItem( key ); + } + else + { + graphicsState.setItem( key, new COSInteger( value.intValue() ) ); + } + } + + /** + * This will get an int item from the dictionary. + * + * @param key The key to the item. + * + * @return The value for that item. + */ + private Long getLongItem( COSName key ) + { + Long retval = null; + COSNumber value = (COSNumber)graphicsState.getDictionaryObject( key ); + if( value != null ) + { + retval = new Long( value.intValue() ); + } + return retval; + } + + /** + * This will set an integer object. + * + * @param key The key to the data that we are setting. + * @param value The value that we are setting. + */ + private void setLongItem( COSName key, Long value ) + { + if( value == null ) + { + graphicsState.removeItem( key ); + } + else + { + graphicsState.setItem( key, new COSInteger( value.longValue() ) ); + } + } + + /** + * This will get a boolean item from the dictionary. + * + * @param key The key to the item. + * + * @return The value for that item. + */ + private Boolean getBooleanItem( COSName key ) + { + Boolean retval = null; + COSBoolean value = (COSBoolean)graphicsState.getDictionaryObject( key ); + if( value != null ) + { + retval = value.getValueAsObject(); + } + return retval; + } + + /** + * This will set an boolean object. + * + * @param key The key to the data that we are setting. + * @param value The value that we are setting. + */ + private void setBooleanItem( COSName key, Boolean value ) + { + if( value == null ) + { + graphicsState.removeItem( key ); + } + else + { + graphicsState.setItem( key, COSBoolean.getBoolean( value ) ); + } + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/graphics/PDFontSetting.java b/src/main/java/org/pdfbox/pdmodel/graphics/PDFontSetting.java new file mode 100644 index 0000000..039609f --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/graphics/PDFontSetting.java @@ -0,0 +1,133 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.graphics; + +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSFloat; +import org.pdfbox.cos.COSNumber; + +import org.pdfbox.pdmodel.common.COSObjectable; + +import org.pdfbox.pdmodel.font.PDFont; +import org.pdfbox.pdmodel.font.PDFontFactory; + +import java.io.IOException; + +/** + * This class represents a font setting used for the graphics state. A font setting is a font and a + * font size. Maybe there is a better name for this? + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.3 $ + */ +public class PDFontSetting implements COSObjectable +{ + private COSArray fontSetting = null; + + /** + * Creates a blank font setting, font will be null, size will be 1. + */ + public PDFontSetting() + { + fontSetting = new COSArray(); + fontSetting.add( null ); + fontSetting.add( new COSFloat( 1 ) ); + } + + /** + * Constructs a font setting from an existing array. + * + * @param fs The new font setting value. + */ + public PDFontSetting( COSArray fs ) + { + fontSetting = fs; + } + + /** + * @see COSObjectable#getCOSObject() + */ + public COSBase getCOSObject() + { + return fontSetting; + } + + /** + * This will get the font for this font setting. + * + * @return The font for this setting of null if one was not found. + * + * @throws IOException If there is an error getting the font. + */ + public PDFont getFont() throws IOException + { + PDFont retval = null; + COSBase font = fontSetting.get( 0 ); + if( font instanceof COSDictionary ) + { + retval = PDFontFactory.createFont( (COSDictionary)font ); + } + return retval; + } + + /** + * This will set the font for this font setting. + * + * @param font The new font. + */ + public void setFont( PDFont font ) + { + fontSetting.set( 0, font ); + } + + /** + * This will get the size of the font. + * + * @return The size of the font. + */ + public float getFontSize() + { + COSNumber size = (COSNumber)fontSetting.get( 1 ); + return size.floatValue(); + } + + /** + * This will set the size of the font. + * + * @param size The new size of the font. + */ + public void setFontSize( float size ) + { + fontSetting.set( 1, new COSFloat( size ) ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/graphics/PDGraphicsState.java b/src/main/java/org/pdfbox/pdmodel/graphics/PDGraphicsState.java new file mode 100644 index 0000000..4115198 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/graphics/PDGraphicsState.java @@ -0,0 +1,438 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.graphics; + +import org.pdfbox.util.Matrix; + +import org.pdfbox.pdmodel.text.PDTextState; + +import org.pdfbox.pdmodel.graphics.color.PDColorSpaceInstance; + +/** + * This class will hold the current state of the graphics parameters when executing a + * content stream. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.3 $ + */ +public class PDGraphicsState implements Cloneable +{ + private Matrix currentTransformationMatrix = new Matrix(); + + //Here are some attributes of the Graphics state, but have not been created yet. + // + //clippingPath + private PDColorSpaceInstance strokingColorSpace = new PDColorSpaceInstance(); + private PDColorSpaceInstance nonStrokingColorSpace = new PDColorSpaceInstance(); + private PDTextState textState = new PDTextState(); + private double lineWidth = 0; + private int lineCap = 0; + private int lineJoin = 0; + private double miterLimit = 0; + private PDLineDashPattern lineDashPattern; + private String renderingIntent; + private boolean strokeAdjustment = false; + //blend mode + //soft mask + private double alphaConstants = 0; + private boolean alphaSource = false; + + //DEVICE DEPENDENT parameters + private boolean overprint = false; + private double overprintMode = 0; + //black generation + //undercolor removal + //transfer + //halftone + private double flatness = 1.0; + private double smoothness = 0; + + /** + * Get the value of the CTM. + * + * @return The current transformation matrix. + */ + public Matrix getCurrentTransformationMatrix() + { + return currentTransformationMatrix; + } + + /** + * Set the value of the CTM. + * + * @param value The current transformation matrix. + */ + public void setCurrentTransformationMatrix(Matrix value) + { + currentTransformationMatrix = value; + } + + /** + * Get the value of the line width. + * + * @return The current line width. + */ + public double getLineWidth() + { + return lineWidth; + } + + /** + * set the value of the line width. + * + * @param value The current line width. + */ + public void setLineWidth(double value) + { + lineWidth = value; + } + + /** + * Get the value of the line cap. + * + * @return The current line cap. + */ + public int getLineCap() + { + return lineCap; + } + + /** + * set the value of the line cap. + * + * @param value The current line cap. + */ + public void setLineCap(int value) + { + lineCap = value; + } + + /** + * Get the value of the line join. + * + * @return The current line join value. + */ + public int getLineJoin() + { + return lineJoin; + } + + /** + * Get the value of the line join. + * + * @param value The current line join + */ + public void setLineJoin(int value) + { + lineJoin = value; + } + + /** + * Get the value of the miter limit. + * + * @return The current miter limit. + */ + public double getMiterLimit() + { + return miterLimit; + } + + /** + * set the value of the miter limit. + * + * @param value The current miter limit. + */ + public void setMiterLimit(double value) + { + miterLimit = value; + } + + /** + * Get the value of the stroke adjustment parameter. + * + * @return The current stroke adjustment. + */ + public boolean isStrokeAdjustment() + { + return strokeAdjustment; + } + + /** + * set the value of the stroke adjustment. + * + * @param value The value of the stroke adjustment parameter. + */ + public void setStrokeAdjustment(boolean value) + { + strokeAdjustment = value; + } + + /** + * Get the value of the alpha constants property. + * + * @return The value of the alpha constants parameter. + */ + public double getAlphaConstants() + { + return alphaConstants; + } + + /** + * set the value of the alpha constants property. + * + * @param value The value of the alpha constants parameter. + */ + public void setAlphaConstants(double value) + { + alphaConstants = value; + } + + /** + * get the value of the alpha source property. + * + * @return The value of the alpha source parameter. + */ + public boolean isAlphaSource() + { + return alphaSource; + } + + /** + * set the value of the alpha source property. + * + * @param value The value of the alpha source parameter. + */ + public void setAlphaSource(boolean value) + { + alphaSource = value; + } + + /** + * get the value of the overprint property. + * + * @return The value of the overprint parameter. + */ + public boolean isOverprint() + { + return overprint; + } + + /** + * set the value of the overprint property. + * + * @param value The value of the overprint parameter. + */ + public void setOverprint(boolean value) + { + overprint = value; + } + + /** + * get the value of the overprint mode property. + * + * @return The value of the overprint mode parameter. + */ + public double getOverprintMode() + { + return overprintMode; + } + + /** + * set the value of the overprint mode property. + * + * @param value The value of the overprint mode parameter. + */ + public void setOverprintMode(double value) + { + overprintMode = value; + } + + /** + * get the value of the flatness property. + * + * @return The value of the flatness parameter. + */ + public double getFlatness() + { + return flatness; + } + + /** + * set the value of the flatness property. + * + * @param value The value of the flatness parameter. + */ + public void setFlatness(double value) + { + flatness = value; + } + + /** + * get the value of the smoothness property. + * + * @return The value of the smoothness parameter. + */ + public double getSmoothness() + { + return smoothness; + } + + /** + * set the value of the smoothness property. + * + * @param value The value of the smoothness parameter. + */ + public void setSmoothness(double value) + { + smoothness = value; + } + + /** + * This will get the graphics text state. + * + * @return The graphics text state. + */ + public PDTextState getTextState() + { + return textState; + } + + /** + * This will set the graphics text state. + * + * @param value The graphics text state. + */ + public void setTextState(PDTextState value) + { + textState = value; + } + + /** + * This will get the current line dash pattern. + * + * @return The line dash pattern. + */ + public PDLineDashPattern getLineDashPattern() + { + return lineDashPattern; + } + + /** + * This will set the current line dash pattern. + * + * @param value The new line dash pattern. + */ + public void setLineDashPattern(PDLineDashPattern value) + { + lineDashPattern = value; + } + + /** + * This will get the rendering intent. + * + * @see PDExtendedGraphicsState + * + * @return The rendering intent + */ + public String getRenderingIntent() + { + return renderingIntent; + } + + /** + * This will set the rendering intent. + * + * @param value The new rendering intent. + */ + public void setRenderingIntent(String value) + { + renderingIntent = value; + } + + /** + * @see Object#clone() + */ + public Object clone() + { + PDGraphicsState clone = null; + try + { + clone = (PDGraphicsState)super.clone(); + clone.setTextState( (PDTextState)textState.clone() ); + clone.setCurrentTransformationMatrix( currentTransformationMatrix.copy() ); + } + catch( CloneNotSupportedException e ) + { + e.printStackTrace(); + } + return clone; + } + + /** + * This will get the current stroking colorspace. + * + * @return The current stroking colorspace. + */ + public PDColorSpaceInstance getStrokingColorSpace() + { + return strokingColorSpace; + } + + /** + * This will set the current stroking colorspace. + * + * @param value The new stroking colorspace instance. + */ + public void setStrokingColorSpace(PDColorSpaceInstance value) + { + strokingColorSpace = value; + } + + /** + * This will get the nonstroking color space instance. + * + * @return The colorspace instance. + */ + public PDColorSpaceInstance getNonStrokingColorSpace() + { + return nonStrokingColorSpace; + } + + /** + * This will set the non-stroking colorspace instance. + * + * @param value The non-stroking colorspace instance. + */ + public void setNonStrokingColorSpace(PDColorSpaceInstance value) + { + nonStrokingColorSpace = value; + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/graphics/PDLineDashPattern.java b/src/main/java/org/pdfbox/pdmodel/graphics/PDLineDashPattern.java new file mode 100644 index 0000000..a67d5e4 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/graphics/PDLineDashPattern.java @@ -0,0 +1,135 @@ +/** + * Copyright (c) 2003-2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.graphics; + +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSInteger; +import org.pdfbox.cos.COSNumber; + +import org.pdfbox.pdmodel.common.COSArrayList; +import org.pdfbox.pdmodel.common.COSObjectable; + +import java.util.List; + +/** + * This class represents the line dash pattern for a graphics state. See PDF + * Reference 1.5 section 4.3.2 + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.4 $ + */ +public class PDLineDashPattern implements COSObjectable +{ + private COSArray lineDashPattern = null; + + /** + * Creates a blank line dash pattern. With no dashes and a phase of 0. + */ + public PDLineDashPattern() + { + lineDashPattern = new COSArray(); + lineDashPattern.add( new COSArray() ); + lineDashPattern.add( new COSInteger( 0 ) ); + } + + /** + * Constructs a line dash pattern from an existing array. + * + * @param ldp The existing line dash pattern. + */ + public PDLineDashPattern( COSArray ldp ) + { + lineDashPattern = ldp; + } + + /** + * @see COSObjectable#getCOSObject() + */ + public COSBase getCOSObject() + { + return lineDashPattern; + } + + /** + * This will get the line dash pattern phase. The dash phase specifies the + * distance into the dash pattern at which to start the dash. + * + * @return The line dash pattern phase. + */ + public int getPhaseStart() + { + COSNumber phase = (COSNumber)lineDashPattern.get( 1 ); + return phase.intValue(); + } + + /** + * This will set the line dash pattern phase. + * + * @param phase The new line dash patter phase. + */ + public void setPhaseStart( int phase ) + { + lineDashPattern.set( 1, new COSInteger( phase ) ); + } + + /** + * This will return a list of java.lang.Integer objects that represent the line + * dash pattern appearance. + * + * @return The line dash pattern. + */ + public List getDashPattern() + { + COSArray dashPatterns = (COSArray)lineDashPattern.get( 0 ); + return COSArrayList.convertIntegerCOSArrayToList( dashPatterns ); + } + + /** + * Get the line dash pattern as a COS object. + * + * @return The cos array line dash pattern. + */ + public COSArray getCOSDashPattern() + { + return (COSArray)lineDashPattern.get( 0 ); + } + + /** + * This will replace the existing line dash pattern. + * + * @param dashPattern A list of java.lang.Integer objects. + */ + public void setDashPattern( List dashPattern ) + { + lineDashPattern.set( 0, COSArrayList.converterToCOSArray( dashPattern ) ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/graphics/color/PDCalGray.java b/src/main/java/org/pdfbox/pdmodel/graphics/color/PDCalGray.java new file mode 100644 index 0000000..fc6f84e --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/graphics/color/PDCalGray.java @@ -0,0 +1,240 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.graphics.color; + +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSFloat; +import org.pdfbox.cos.COSName; +import org.pdfbox.cos.COSNumber; + +import java.awt.color.ColorSpace; +import java.awt.image.ColorModel; + +import java.io.IOException; + +/** + * This class represents a Cal Gray color space. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.4 $ + */ +public class PDCalGray extends PDColorSpace +{ + /** + * The name of this color space. + */ + public static final String NAME = "CalGray"; + + private COSArray array; + private COSDictionary dictionary; + + /** + * Constructor. + */ + public PDCalGray() + { + array = new COSArray(); + dictionary = new COSDictionary(); + array.add( COSName.getPDFName( NAME ) ); + array.add( dictionary ); + } + + /** + * Constructor with array. + * + * @param gray The underlying color space. + */ + public PDCalGray( COSArray gray ) + { + array = gray; + dictionary = (COSDictionary)array.getObject( 1 ); + } + + /** + * This will get the number of components that this color space is made up of. + * + * @return The number of components in this color space. + * + * @throws IOException If there is an error getting the number of color components. + */ + public int getNumberOfComponents() throws IOException + { + return 1; + } + + /** + * This will return the name of the color space. + * + * @return The name of the color space. + */ + public String getName() + { + return NAME; + } + + /** + * Create a Java colorspace for this colorspace. + * + * @return A color space that can be used for Java AWT operations. + * + * @throws IOException If there is an error creating the color space. + */ + public ColorSpace createColorSpace() throws IOException + { + throw new IOException( "Not implemented" ); + } + + /** + * Create a Java color model for this colorspace. + * + * @param bpc The number of bits per component. + * + * @return A color model that can be used for Java AWT operations. + * + * @throws IOException If there is an error creating the color model. + */ + public ColorModel createColorModel( int bpc ) throws IOException + { + throw new IOException( "Not implemented" ); + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSBase getCOSObject() + { + return array; + } + + /** + * This will get the gamma value. If none is present then the default of 1 + * will be returned. + * + * @return The gamma value. + */ + public float getGamma() + { + float retval = 1.0f; + COSNumber gamma = (COSNumber)dictionary.getDictionaryObject( COSName.getPDFName( "Gamma" ) ); + if( gamma != null ) + { + retval = gamma.floatValue(); + } + return retval; + } + + /** + * Set the gamma value. + * + * @param value The new gamma value. + */ + public void setGamma( float value ) + { + dictionary.setItem( COSName.getPDFName( "Gamma" ), new COSFloat( value ) ); + } + + /** + * This will return the whitepoint tristimulus. As this is a required field + * this will never return null. A default of 1,1,1 will be returned if the + * pdf does not have any values yet. + * + * @return The whitepoint tristimulus. + */ + public PDTristimulus getWhitepoint() + { + PDTristimulus retval = null; + COSArray wp = (COSArray)dictionary.getDictionaryObject( COSName.getPDFName( "WhitePoint" ) ); + if( wp == null ) + { + wp.add( new COSFloat( 1.0f ) ); + wp.add( new COSFloat( 1.0f ) ); + wp.add( new COSFloat( 1.0f ) ); + dictionary.setItem( COSName.getPDFName( "WhitePoint" ), wp ); + } + return new PDTristimulus( wp ); + } + + /** + * This will set the whitepoint tristimulus. As this is a required field + * this null should not be passed into this function. + * + * @param wp The whitepoint tristimulus. + */ + public void setWhitepoint( PDTristimulus wp ) + { + COSBase wpArray = wp.getCOSObject(); + if( wpArray != null ) + { + dictionary.setItem( COSName.getPDFName( "WhitePoint" ), wpArray ); + } + } + + /** + * This will return the BlackPoint tristimulus. This is an optional field but + * has defaults so this will never return null. + * A default of 0,0,0 will be returned if the pdf does not have any values yet. + * + * @return The blackpoint tristimulus. + */ + public PDTristimulus getBlackPoint() + { + PDTristimulus retval = null; + COSArray bp = (COSArray)dictionary.getDictionaryObject( COSName.getPDFName( "BlackPoint" ) ); + if( bp == null ) + { + bp.add( new COSFloat( 0.0f ) ); + bp.add( new COSFloat( 0.0f ) ); + bp.add( new COSFloat( 0.0f ) ); + dictionary.setItem( COSName.getPDFName( "BlackPoint" ), bp ); + } + return new PDTristimulus( bp ); + } + + /** + * This will set the BlackPoint tristimulus. As this is a required field + * this null should not be passed into this function. + * + * @param bp The BlackPoint tristimulus. + */ + public void setBlackPoint( PDTristimulus bp ) + { + COSBase bpArray = null; + if( bp != null ) + { + bpArray = bp.getCOSObject(); + } + dictionary.setItem( COSName.getPDFName( "BlackPoint" ), bpArray ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/graphics/color/PDCalRGB.java b/src/main/java/org/pdfbox/pdmodel/graphics/color/PDCalRGB.java new file mode 100644 index 0000000..6aa4eb1 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/graphics/color/PDCalRGB.java @@ -0,0 +1,289 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.graphics.color; + +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSFloat; +import org.pdfbox.cos.COSName; + +import org.pdfbox.pdmodel.common.PDMatrix; + +import java.awt.color.ColorSpace; +import java.awt.image.ColorModel; + +import java.io.IOException; + +/** + * This class represents a Cal RGB color space. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.2 $ + */ +public class PDCalRGB extends PDColorSpace +{ + /** + * The name of this color space. + */ + public static final String NAME = "CalRGB"; + + private COSArray array; + private COSDictionary dictionary; + + /** + * Constructor. + */ + public PDCalRGB() + { + array = new COSArray(); + dictionary = new COSDictionary(); + array.add( COSName.getPDFName( NAME ) ); + array.add( dictionary ); + } + + /** + * Constructor with array. + * + * @param rgb The underlying color space. + */ + public PDCalRGB( COSArray rgb ) + { + array = rgb; + dictionary = (COSDictionary)array.getObject( 1 ); + } + + /** + * This will get the number of components that this color space is made up of. + * + * @return The number of components in this color space. + * + * @throws IOException If there is an error getting the number of color components. + */ + public int getNumberOfComponents() throws IOException + { + return 3; + } + + /** + * This will return the name of the color space. + * + * @return The name of the color space. + */ + public String getName() + { + return NAME; + } + + /** + * Create a Java colorspace for this colorspace. + * + * @return A color space that can be used for Java AWT operations. + * + * @throws IOException If there is an error creating the color space. + */ + public ColorSpace createColorSpace() throws IOException + { + throw new IOException( "Not implemented" ); + } + + /** + * Create a Java color model for this colorspace. + * + * @param bpc The number of bits per component. + * + * @return A color model that can be used for Java AWT operations. + * + * @throws IOException If there is an error creating the color model. + */ + public ColorModel createColorModel( int bpc ) throws IOException + { + throw new IOException( "Not implemented" ); + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSBase getCOSObject() + { + return array; + } + + /** + * This will return the whitepoint tristimulus. As this is a required field + * this will never return null. A default of 1,1,1 will be returned if the + * pdf does not have any values yet. + * + * @return The whitepoint tristimulus. + */ + public PDTristimulus getWhitepoint() + { + PDTristimulus retval = null; + COSArray wp = (COSArray)dictionary.getDictionaryObject( COSName.getPDFName( "WhitePoint" ) ); + if( wp == null ) + { + wp.add( new COSFloat( 1.0f ) ); + wp.add( new COSFloat( 1.0f ) ); + wp.add( new COSFloat( 1.0f ) ); + dictionary.setItem( COSName.getPDFName( "WhitePoint" ), wp ); + } + return new PDTristimulus( wp ); + } + + /** + * This will set the whitepoint tristimulus. As this is a required field + * this null should not be passed into this function. + * + * @param wp The whitepoint tristimulus. + */ + public void setWhitepoint( PDTristimulus wp ) + { + COSBase wpArray = wp.getCOSObject(); + if( wpArray != null ) + { + dictionary.setItem( COSName.getPDFName( "WhitePoint" ), wpArray ); + } + } + + /** + * This will return the BlackPoint tristimulus. This is an optional field but + * has defaults so this will never return null. + * A default of 0,0,0 will be returned if the pdf does not have any values yet. + * + * @return The blackpoint tristimulus. + */ + public PDTristimulus getBlackPoint() + { + PDTristimulus retval = null; + COSArray bp = (COSArray)dictionary.getDictionaryObject( COSName.getPDFName( "BlackPoint" ) ); + if( bp == null ) + { + bp.add( new COSFloat( 0.0f ) ); + bp.add( new COSFloat( 0.0f ) ); + bp.add( new COSFloat( 0.0f ) ); + dictionary.setItem( COSName.getPDFName( "BlackPoint" ), bp ); + } + return new PDTristimulus( bp ); + } + + /** + * This will set the BlackPoint tristimulus. As this is a required field + * this null should not be passed into this function. + * + * @param bp The BlackPoint tristimulus. + */ + public void setBlackPoint( PDTristimulus bp ) + { + + COSBase bpArray = null; + if( bp != null ) + { + bpArray = bp.getCOSObject(); + } + dictionary.setItem( COSName.getPDFName( "BlackPoint" ), bpArray ); + } + + /** + * This will get the gamma value. If none is present then the default of 1,1,1 + * will be returned. + * + * @return The gamma value. + */ + public PDGamma getGamma() + { + COSArray gamma = (COSArray)dictionary.getDictionaryObject( COSName.getPDFName( "Gamma" ) ); + if( gamma == null ) + { + gamma = new COSArray(); + gamma.add( new COSFloat( 1.0f ) ); + gamma.add( new COSFloat( 1.0f ) ); + gamma.add( new COSFloat( 1.0f ) ); + dictionary.setItem( COSName.getPDFName( "Gamma" ), gamma ); + } + return new PDGamma( gamma ); + } + + /** + * Set the gamma value. + * + * @param value The new gamma value. + */ + public void setGamma( PDGamma value ) + { + COSArray gamma = null; + if( value != null ) + { + gamma = (COSArray)value.getCOSArray(); + } + dictionary.setItem( COSName.getPDFName( "Gamma" ), gamma ); + } + + /** + * This will get the linear interpretation array. This is guaranteed to not + * return null. If the underlying dictionary contains null then the identity + * matrix will be returned. + * + * @return The linear interpretation matrix. + */ + public PDMatrix getLinearInterpretation() + { + PDMatrix retval = null; + COSArray matrix = (COSArray)dictionary.getDictionaryObject( COSName.getPDFName( "Matrix" ) ); + if( matrix == null ) + { + retval = new PDMatrix(); + setLinearInterpretation( retval ); + } + else + { + retval = new PDMatrix( matrix ); + } + return retval; + } + + /** + * This will set the linear interpretation matrix. Passing in null will + * clear the matrix. + * + * @param matrix The new linear interpretation matrix. + */ + public void setLinearInterpretation( PDMatrix matrix ) + { + COSArray matrixArray = null; + if( matrix != null ) + { + matrixArray = matrix.getCOSArray(); + } + dictionary.setItem( COSName.getPDFName( "Matrix" ), matrixArray ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/graphics/color/PDColorSpace.java b/src/main/java/org/pdfbox/pdmodel/graphics/color/PDColorSpace.java new file mode 100644 index 0000000..33ac0a1 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/graphics/color/PDColorSpace.java @@ -0,0 +1,97 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.graphics.color; + +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSName; + +import org.pdfbox.pdmodel.common.COSObjectable; + +import java.io.IOException; + +import java.awt.color.ColorSpace; +import java.awt.image.ColorModel; + + +/** + * This class represents a color space in a pdf document. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.4 $ + */ +public abstract class PDColorSpace implements COSObjectable +{ + /** + * This will return the name of the color space. + * + * @return The name of the color space. + */ + public abstract String getName(); + + /** + * This will get the number of components that this color space is made up of. + * + * @return The number of components in this color space. + * + * @throws IOException If there is an error getting the number of color components. + */ + public abstract int getNumberOfComponents() throws IOException; + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSBase getCOSObject() + { + return COSName.getPDFName( getName() ); + } + + /** + * Create a Java colorspace for this colorspace. + * + * @return A color space that can be used for Java AWT operations. + * + * @throws IOException If there is an error creating the color space. + */ + public abstract ColorSpace createColorSpace() throws IOException; + + /** + * Create a Java color model for this colorspace. + * + * @param bpc The number of bits per component. + * + * @return A color model that can be used for Java AWT operations. + * + * @throws IOException If there is an error creating the color model. + */ + public abstract ColorModel createColorModel( int bpc ) throws IOException; +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/graphics/color/PDColorSpaceFactory.java b/src/main/java/org/pdfbox/pdmodel/graphics/color/PDColorSpaceFactory.java new file mode 100644 index 0000000..8c9aad5 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/graphics/color/PDColorSpaceFactory.java @@ -0,0 +1,218 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.graphics.color; + +import java.awt.color.ColorSpace; +import java.awt.color.ICC_ColorSpace; +import java.io.IOException; +import java.io.OutputStream; + +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSFloat; +import org.pdfbox.cos.COSName; +import org.pdfbox.pdmodel.PDDocument; +import org.pdfbox.pdmodel.common.PDStream; + +/** + * This class represents a color space in a pdf document. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.10 $ + */ +public final class PDColorSpaceFactory +{ + /** + * Private constructor for utility classes. + */ + private PDColorSpaceFactory() + { + //utility class should not be implemented + } + + /** + * This will create the correct color space given the name. + * + * @param colorSpace The color space object. + * + * @return The color space. + * + * @throws IOException If the color space name is unknown. + */ + public static PDColorSpace createColorSpace( COSBase colorSpace ) throws IOException + { + PDColorSpace retval = null; + if( colorSpace instanceof COSName ) + { + retval = createColorSpace( ((COSName)colorSpace).getName() ); + } + else if( colorSpace instanceof COSArray ) + { + COSArray array = (COSArray)colorSpace; + COSName type = (COSName)array.getObject( 0 ); + if( type.getName().equals( PDCalGray.NAME ) ) + { + retval = new PDCalGray( array ); + } + else if( type.getName().equals( PDCalRGB.NAME ) ) + { + retval = new PDCalRGB( array ); + } + else if( type.getName().equals( PDDeviceN.NAME ) ) + { + retval = new PDDeviceN( array ); + } + else if( type.getName().equals( PDIndexed.NAME ) || + type.getName().equals( PDIndexed.ABBREVIATED_NAME )) + { + retval = new PDIndexed( array ); + } + else if( type.getName().equals( PDLab.NAME ) ) + { + retval = new PDLab( array ); + } + else if( type.getName().equals( PDSeparation.NAME ) ) + { + retval = new PDSeparation( array ); + } + else if( type.getName().equals( PDICCBased.NAME ) ) + { + retval = new PDICCBased( array ); + } + else if( type.getName().equals( PDPattern.NAME ) ) + { + retval = new PDPattern( array ); + } + else + { + throw new IOException( "Unknown colorspace array type:" + type ); + } + } + else + { + throw new IOException( "Unknown colorspace type:" + colorSpace ); + } + return retval; + } + + /** + * This will create the correct color space given the name. + * + * @param colorSpaceName The name of the colorspace. + * + * @return The color space. + * + * @throws IOException If the color space name is unknown. + */ + public static PDColorSpace createColorSpace( String colorSpaceName ) throws IOException + { + PDColorSpace cs = null; + if( colorSpaceName.equals( PDDeviceCMYK.NAME ) || + colorSpaceName.equals( PDDeviceCMYK.ABBREVIATED_NAME ) ) + { + cs = PDDeviceCMYK.INSTANCE; + } + else if( colorSpaceName.equals( PDDeviceRGB.NAME ) || + colorSpaceName.equals( PDDeviceRGB.ABBREVIATED_NAME ) ) + { + cs = PDDeviceRGB.INSTANCE; + } + else if( colorSpaceName.equals( PDDeviceGray.NAME ) || + colorSpaceName.equals( PDDeviceGray.ABBREVIATED_NAME )) + { + cs = new PDDeviceGray(); + } + else if( colorSpaceName.equals( PDLab.NAME ) ) + { + cs = new PDLab(); + } + else if( colorSpaceName.equals( PDPattern.NAME ) ) + { + cs = new PDPattern(); + } + else + { + throw new IOException( "Error: Unknown colorspace '" + colorSpaceName + "'" ); + } + return cs; + } + + /** + * This will create the correct color space from a java colorspace. + * + * @param doc The doc to potentiall write information to. + * @param cs The awt colorspace. + * + * @return The color space. + * + * @throws IOException If the color space name is unknown. + */ + public static PDColorSpace createColorSpace( PDDocument doc, ColorSpace cs ) throws IOException + { + PDColorSpace retval = null; + if( cs.isCS_sRGB() ) + { + retval = PDDeviceRGB.INSTANCE; + } + else if( cs instanceof ICC_ColorSpace ) + { + ICC_ColorSpace ics = (ICC_ColorSpace)cs; + PDICCBased pdCS = new PDICCBased( doc ); + retval = pdCS; + COSArray ranges = new COSArray(); + for( int i=0; i + + + + + +This package deals with colors that are stored in a PDF document. + + \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/graphics/package.html b/src/main/java/org/pdfbox/pdmodel/graphics/package.html new file mode 100644 index 0000000..3c1f7ca --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/graphics/package.html @@ -0,0 +1,9 @@ + + + + + + +The PDModel graphics package deals with graphics states, operations, and parameters within the PDF document. + + diff --git a/src/main/java/org/pdfbox/pdmodel/graphics/predictor/Average.java b/src/main/java/org/pdfbox/pdmodel/graphics/predictor/Average.java new file mode 100644 index 0000000..46e65dc --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/graphics/predictor/Average.java @@ -0,0 +1,81 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.graphics.predictor; + +/** + * We can use raw on the right hand side of + * the decoding formula because it is already decoded. + * + * average(i,j) = raw(i,j) + (raw(i-1,j)+raw(i,j-1)/2 + * + * decoding + * + * raw(i,j) = avarage(i,j) - (raw(i-1,j)+raw(i,j-1)/2 + * + * @author xylifyx@yahoo.co.uk + * @version $Revision: 1.2 $ + */ +public class Average extends PredictorAlgorithm +{ + /** + * Not an optimal version, but close to the def. + * + * @see org.pdfbox.pdmodel.graphics.predictor.PredictorAlgorithm#encodeLine(byte[], byte[], + * int, int, int, int) + */ + public void encodeLine(byte[] src, byte[] dest, int srcDy, int srcOffset, + int destDy, int destOffset) + { + int bpl = getWidth() * getBpp(); + for (int x = 0; x < bpl; x++) + { + dest[x + destOffset] = (byte) (src[x + srcOffset] - ((leftPixel( + src, srcOffset, srcDy, x) + abovePixel(src, srcOffset, + srcDy, x)) >>> 2)); + } + } + + /** + * @see org.pdfbox.pdmodel.graphics.predictor.PredictorAlgorithm#decodeLine(byte[], byte[], + * int, int, int, int) + */ + public void decodeLine(byte[] src, byte[] dest, int srcDy, int srcOffset, + int destDy, int destOffset) + { + int bpl = getWidth() * getBpp(); + for (int x = 0; x < bpl; x++) + { + dest[x + destOffset] = (byte) (src[x + srcOffset] + ((leftPixel( + dest, destOffset, destDy, x) + abovePixel(dest, + destOffset, destDy, x)) >>> 2)); + } + } +} diff --git a/src/main/java/org/pdfbox/pdmodel/graphics/predictor/None.java b/src/main/java/org/pdfbox/pdmodel/graphics/predictor/None.java new file mode 100644 index 0000000..20ec815 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/graphics/predictor/None.java @@ -0,0 +1,104 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.graphics.predictor; + +/** + * The none algorithm. + * + * None(i,j) = Raw(i,j) + * + * Raw(i,j) = None(i,j) + * + * @author xylifyx@yahoo.co.uk + * @version $Revision: 1.2 $ + */ +public class None extends PredictorAlgorithm +{ + /** + * encode a byte array full of image data using the filter that this object + * implements. + * + * @param src + * buffer + * @param dest + * buffer + */ + public void encode(byte[] src, byte[] dest) + { + checkBufsiz(dest, src); + System.arraycopy(src,0,dest,0,src.length); + } + + /** + * decode a byte array full of image data using the filter that this object + * implements. + * + * @param src + * buffer + * @param dest + * buffer + */ + public void decode(byte[] src, byte[] dest) + { + System.arraycopy(src,0,dest,0,src.length); + } + + + + /** + * @see org.pdfbox.pdmodel.graphics.predictor.PredictorAlgorithm#encodeLine(byte[], byte[], + * int, int, int, int) + */ + public void encodeLine(byte[] src, byte[] dest, int srcDy, int srcOffset, + int destDy, int destOffset) + { + int bpl = getWidth() * getBpp(); + for (int x = 0; x < bpl; x++) + { + dest[destOffset + x] = src[srcOffset + x]; + } + } + + /** + * @see org.pdfbox.pdmodel.graphics.predictor.PredictorAlgorithm#decodeLine(byte[], byte[], + * int, int, int, int) + */ + public void decodeLine(byte[] src, byte[] dest, int srcDy, int srcOffset, + int destDy, int destOffset) + { + int bpl = getWidth() * getBpp(); + for (int x = 0; x < bpl; x++) + { + dest[destOffset + x] = src[srcOffset + x]; + } + } + +} diff --git a/src/main/java/org/pdfbox/pdmodel/graphics/predictor/Paeth.java b/src/main/java/org/pdfbox/pdmodel/graphics/predictor/Paeth.java new file mode 100644 index 0000000..1fddef0 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/graphics/predictor/Paeth.java @@ -0,0 +1,121 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + */ +package org.pdfbox.pdmodel.graphics.predictor; + +/** + * From http://www.w3.org/TR/PNG-Filters.html: The Paeth filter computes a + * simple linear function of the three neighboring pixels (left, above, upper + * left), then chooses as predictor the neighboring pixel closest to the + * computed value. This technique is due to Alan W. Paeth [PAETH]. + * + * To compute the Paeth filter, apply the following formula to each byte of the + * scanline: + * + * Paeth(i,j) = Raw(i,j) - PaethPredictor(Raw(i-1,j), Raw(i,j-1), Raw(i-1,j-1)) + * + * To decode the Paeth filter + * + * Raw(i,j) = Paeth(i,j) - PaethPredictor(Raw(i-1,j), Raw(i,j-1), Raw(i-1,j-1)) + * + * @author xylifyx@yahoo.co.uk + * @version $Revision: 1.2 $ + */ +public class Paeth extends PredictorAlgorithm +{ + /** + * The paeth predictor function. + * + * This function is taken almost directly from the PNG definition on + * http://www.w3.org/TR/PNG-Filters.html + * + * @param a + * left + * @param b + * above + * @param c + * upper left + * @return The result of the paeth predictor. + */ + public int paethPredictor(int a, int b, int c) + { + int p = a + b - c; // initial estimate + int pa = Math.abs(p - a); // distances to a, b, c + int pb = Math.abs(p - b); + int pc = Math.abs(p - c); + // return nearest of a,b,c, + // breaking ties in order a,b,c. + if (pa <= pb && pa <= pc) + { + return a; + } + else if (pb <= pc) + { + return b; + } + else + { + return c; + } + } + + /** + * @see org.pdfbox.pdmodel.graphics.predictor.PredictorAlgorithm#encodeLine(byte[], byte[], + * int, int, int, int) + */ + public void encodeLine(byte[] src, byte[] dest, int srcDy, int srcOffset, + int destDy, int destOffset) + { + int bpl = getWidth() * getBpp(); + for (int x = 0; x < bpl; x++) + { + dest[x + destOffset] = (byte) (src[x + srcOffset] - paethPredictor( + leftPixel(src, srcOffset, srcDy, x), abovePixel(src, + srcOffset, srcDy, x), aboveLeftPixel(src, + srcOffset, srcDy, x))); + } + } + + /** + * @see org.pdfbox.pdmodel.graphics.predictor.PredictorAlgorithm#decodeLine(byte[], byte[], + * int, int, int, int) + */ + public void decodeLine(byte[] src, byte[] dest, int srcDy, int srcOffset, + int destDy, int destOffset) + { + int bpl = getWidth() * getBpp(); + for (int x = 0; x < bpl; x++) + { + dest[x + destOffset] = (byte) (src[x + srcOffset] + paethPredictor( + leftPixel(dest, destOffset, destDy, x), abovePixel(dest, + destOffset, destDy, x), aboveLeftPixel(dest, + destOffset, destDy, x))); + } + } +} diff --git a/src/main/java/org/pdfbox/pdmodel/graphics/predictor/PredictorAlgorithm.java b/src/main/java/org/pdfbox/pdmodel/graphics/predictor/PredictorAlgorithm.java new file mode 100644 index 0000000..11f60f9 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/graphics/predictor/PredictorAlgorithm.java @@ -0,0 +1,336 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.graphics.predictor; + +import java.util.Random; + +/** + * Implements different PNG predictor algorithms that is used in PDF files. + * + * @author xylifyx@yahoo.co.uk + * @version $Revision: 1.2 $ + * @see http://www.w3.org/TR/PNG-Filters.html + */ +public abstract class PredictorAlgorithm +{ + private int width; + + private int height; + + private int bpp; + + /** + * check that buffer sizes matches width,height,bpp. This implementation is + * used by most of the filters, but not Uptimum. + * + * @param src The source buffer. + * @param dest The destination buffer. + */ + public void checkBufsiz(byte[] src, byte[] dest) + { + if (src.length != dest.length) + { + throw new IllegalArgumentException("src.length != dest.length"); + } + if (src.length != getWidth() * getHeight() * getBpp()) + { + throw new IllegalArgumentException( + "src.length != width * height * bpp"); + } + } + + /** + * encode line of pixel data in src from srcOffset and width*bpp bytes + * forward, put the decoded bytes into dest. + * + * @param src + * raw image data + * @param dest + * encoded data + * @param srcDy + * byte offset between lines + * @param srcOffset + * beginning of line data + * @param destDy + * byte offset between lines + * @param destOffset + * beginning of line data + */ + public abstract void encodeLine(byte[] src, byte[] dest, int srcDy, + int srcOffset, int destDy, int destOffset); + + /** + * decode line of pixel data in src from src_offset and width*bpp bytes + * forward, put the decoded bytes into dest. + * + * @param src + * encoded image data + * @param dest + * raw data + * @param srcDy + * byte offset between lines + * @param srcOffset + * beginning of line data + * @param destDy + * byte offset between lines + * @param destOffset + * beginning of line data + */ + public abstract void decodeLine(byte[] src, byte[] dest, int srcDy, + int srcOffset, int destDy, int destOffset); + + /** + * Simple command line program to test the algorithm. + * + * @param args The command line arguments. + */ + public static void main(String[] args) + { + Random rnd = new Random(); + int width = 5; + int height = 5; + int bpp = 3; + byte[] raw = new byte[width * height * bpp]; + rnd.nextBytes(raw); + System.out.println("raw: "); + dump(raw); + for (int i = 10; i < 15; i++) + { + byte[] decoded = new byte[width * height * bpp]; + byte[] encoded = new byte[width * height * bpp]; + + PredictorAlgorithm filter = PredictorAlgorithm.getFilter(i); + filter.setWidth(width); + filter.setHeight(height); + filter.setBpp(bpp); + filter.encode(raw, encoded); + filter.decode(encoded, decoded); + System.out.println(filter.getClass().getName()); + dump(decoded); + } + } + + /** + * Get the left pixel from the buffer. + * + * @param buf The buffer. + * @param offset The offset into the buffer. + * @param dy The dy value. + * @param x The x value. + * + * @return The left pixel. + */ + public int leftPixel(byte[] buf, int offset, int dy, int x) + { + return x >= getBpp() ? buf[offset + x - getBpp()] : 0; + } + + /** + * Get the above pixel from the buffer. + * + * @param buf The buffer. + * @param offset The offset into the buffer. + * @param dy The dy value. + * @param x The x value. + * + * @return The above pixel. + */ + public int abovePixel(byte[] buf, int offset, int dy, int x) + { + return offset >= dy ? buf[offset + x - dy] : 0; + } + + /** + * Get the above-left pixel from the buffer. + * + * @param buf The buffer. + * @param offset The offset into the buffer. + * @param dy The dy value. + * @param x The x value. + * + * @return The above-left pixel. + */ + public int aboveLeftPixel(byte[] buf, int offset, int dy, int x) + { + return offset >= dy && x >= getBpp() ? buf[offset + x - dy - getBpp()] + : 0; + } + + /** + * Simple helper to print out a buffer. + * + * @param raw The bytes to print out. + */ + private static void dump(byte[] raw) + { + for (int i = 0; i < raw.length; i++) + { + System.out.print(raw[i] + " "); + } + System.out.println(); + } + + /** + * @return Returns the bpp. + */ + public int getBpp() + { + return bpp; + } + + /** + * @param newBpp + * The bpp to set. + */ + public void setBpp(int newBpp) + { + bpp = newBpp; + } + + /** + * @return Returns the height. + */ + public int getHeight() + { + return height; + } + + /** + * @param newHeight + * The height to set. + */ + public void setHeight(int newHeight) + { + height = newHeight; + } + + /** + * @return Returns the width. + */ + public int getWidth() + { + return width; + } + + /** + * @param newWidth + * The width to set. + */ + public void setWidth(int newWidth) + { + this.width = newWidth; + } + + + /** + * encode a byte array full of image data using the filter that this object + * implements. + * + * @param src + * buffer + * @param dest + * buffer + */ + public void encode(byte[] src, byte[] dest) + { + checkBufsiz(dest, src); + int dy = getWidth()*getBpp(); + for (int y = 0; y < height; y++) + { + int yoffset = y * dy; + encodeLine(src, dest, dy, yoffset, dy, yoffset); + } + } + + /** + * decode a byte array full of image data using the filter that this object + * implements. + * + * @param src + * buffer + * @param dest + * buffer + */ + public void decode(byte[] src, byte[] dest) + { + checkBufsiz(src, dest); + int dy = width * bpp; + for (int y = 0; y < height; y++) + { + int yoffset = y * dy; + decodeLine(src, dest, dy, yoffset, dy, yoffset); + } + } + + /** + * @param predictor + *
    + *
  • 1 No prediction (the default value) + *
  • 2 TIFF Predictor 2 + *
  • 10 PNG prediction (on encoding, PNG None on all rows) + *
  • 11 PNG prediction (on encoding, PNG Sub on all rows) + *
  • 12 PNG prediction (on encoding, PNG Up on all rows) + *
  • 13 PNG prediction (on encoding, PNG Average on all rows) + *
  • 14 PNG prediction (on encoding, PNG Paeth on all rows) + *
  • 15 PNG prediction (on encoding, PNG optimum) + *
+ * + * @return The predictor class based on the predictor code. + */ + public static PredictorAlgorithm getFilter(int predictor) + { + PredictorAlgorithm filter; + switch (predictor) + { + case 10: + filter = new None(); + break; + case 11: + filter = new Sub(); + break; + case 12: + filter = new Up(); + break; + case 13: + filter = new Average(); + break; + case 14: + filter = new Paeth(); + break; + case 15: + filter = new Uptimum(); + break; + default: + filter = new None(); + } + return filter; + } +} diff --git a/src/main/java/org/pdfbox/pdmodel/graphics/predictor/Sub.java b/src/main/java/org/pdfbox/pdmodel/graphics/predictor/Sub.java new file mode 100644 index 0000000..3959dbe --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/graphics/predictor/Sub.java @@ -0,0 +1,86 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.graphics.predictor; + +/** + * The sub algorithm. + * + * Sub(i,j) = Raw(i,j) - Raw(i-1,j) + * + * Raw(i,j) = Sub(i,j) + Raw(i-1,j) + * + * @author xylifyx@yahoo.co.uk + * @version $Revision: 1.2 $ + */ +public class Sub extends PredictorAlgorithm +{ + /** + * @see org.pdfbox.pdmodel.graphics.predictor.PredictorAlgorithm#encodeLine(byte[], byte[], int, int, int, int) + */ + public void encodeLine(byte[] src, byte[] dest, int srcDy, int srcOffset, + int destDy, int destOffset) + { + int bpl = getWidth()*getBpp(); + int bpp = getBpp(); + // case: x < bpp + for (int x = 0; x < bpl && x < bpp; x++) + { + dest[x + destOffset] = src[x + srcOffset]; + } + // otherwise + for (int x = getBpp(); x < bpl; x++) + { + dest[x + destOffset] = (byte) (src[x + srcOffset] - src[x + + srcOffset - bpp]); + } + } + + /** + * @see org.pdfbox.pdmodel.graphics.predictor.PredictorAlgorithm#decodeLine(byte[], byte[], int, int, int, int) + */ + public void decodeLine(byte[] src, byte[] dest, int srcDy, int srcOffset, + int destDy, int destOffset) + { + int bpl = getWidth()*getBpp(); + int bpp = getBpp(); + // case: x < bpp + for (int x = 0; x < bpl && x < bpp; x++) + { + dest[x + destOffset] = src[x + srcOffset]; + } + // otherwise + for (int x = getBpp(); x < bpl; x++) + { + dest[x + destOffset] = (byte) (src[x + srcOffset] + dest[x + + destOffset - bpp]); + } + } +} diff --git a/src/main/java/org/pdfbox/pdmodel/graphics/predictor/Up.java b/src/main/java/org/pdfbox/pdmodel/graphics/predictor/Up.java new file mode 100644 index 0000000..f1932b4 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/graphics/predictor/Up.java @@ -0,0 +1,100 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.graphics.predictor; + +/** + * The up algorithm. + * + * Up(i,j) = Raw(i,j) - Raw(i,j-1) + * + * Raw(i,j) = Up(i,j) + Raw(i,j-1) + * + * @author xylifyx@yahoo.co.uk + * @version $Revision: 1.2 $ + */ +public class Up extends PredictorAlgorithm +{ + /** + * @see org.pdfbox.pdmodel.graphics.predictor.PredictorAlgorithm#encodeLine(byte[], byte[], int, int, int, int) + */ + public void encodeLine(byte[] src, byte[] dest, int srcDy, int srcOffset, + int destDy, int destOffset) + { + int bpl = getWidth()*getBpp(); + // case: y = 0; + if (srcOffset - srcDy < 0) + { + if (0 < getHeight()) + { + for (int x = 0; x < bpl; x++) + { + dest[destOffset + x] = src[srcOffset + x]; + } + } + } + else + { + for (int x = 0; x < bpl; x++) + { + dest[destOffset + x] = (byte) (src[srcOffset + x] - src[srcOffset + + x - srcDy]); + } + } + } + + /** + * @see org.pdfbox.pdmodel.graphics.predictor.PredictorAlgorithm#decodeLine(byte[], byte[], int, int, int, int) + */ + public void decodeLine(byte[] src, byte[] dest, int srcDy, int srcOffset, + int destDy, int destOffset) + { + // case: y = 0; + int bpl = getWidth()*getBpp(); + if (destOffset - destDy < 0) + { + if (0 < getHeight()) + { + for (int x = 0; x < bpl; x++) + { + dest[destOffset + x] = src[srcOffset + x]; + } + } + } + else + { + for (int x = 0; x < bpl; x++) + { + dest[destOffset + x] = (byte) (src[srcOffset + x] + dest[destOffset + + x - destDy]); + } + } + } +} diff --git a/src/main/java/org/pdfbox/pdmodel/graphics/predictor/Uptimum.java b/src/main/java/org/pdfbox/pdmodel/graphics/predictor/Uptimum.java new file mode 100644 index 0000000..ac03162 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/graphics/predictor/Uptimum.java @@ -0,0 +1,153 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.graphics.predictor; + +/** + * + * + * In an Uptimum encoded image, each line takes up width*bpp+1 bytes. The first + * byte holds a number that signifies which algorithm encoded the line. + * + * @author xylifyx@yahoo.co.uk + * @version $Revision: 1.2 $ + */ +public class Uptimum extends PredictorAlgorithm +{ + /** + * @see PredictorAlgorithm#checkBufsiz(byte[], byte[]) + */ + public void checkBufsiz(byte[] filtered, byte[] raw) + { + if (filtered.length != (getWidth() * getBpp() + 1) * getHeight()) + { + + throw new IllegalArgumentException( + "filtered.length != (width*bpp + 1) * height, " + + filtered.length + " " + + (getWidth() * getBpp() + 1) * getHeight() + + "w,h,bpp=" + getWidth() + "," + getHeight() + "," + + getBpp()); + } + if (raw.length != getWidth() * getHeight() * getBpp()) + { + throw new IllegalArgumentException( + "raw.length != width * height * bpp, raw.length=" + + raw.length + " w,h,bpp=" + getWidth() + "," + + getHeight() + "," + getBpp()); + } + } + + /** + * @see org.pdfbox.pdmodel.graphics.predictor.PredictorAlgorithm#encodeLine(byte[], byte[], + * int, int, int, int) + */ + public void encodeLine(byte[] src, byte[] dest, int srcDy, int srcOffset, + int destDy, int destOffset) + { + throw new UnsupportedOperationException("encodeLine"); + } + + /** + * @see org.pdfbox.pdmodel.graphics.predictor.PredictorAlgorithm#decodeLine(byte[], byte[], + * int, int, int, int) + */ + public void decodeLine(byte[] src, byte[] dest, int srcDy, int srcOffset, + int destDy, int destOffset) + { + throw new UnsupportedOperationException("decodeLine"); + } + + /** + * @see PredictorAlgorithm#encode(byte[], byte[]) + */ + public void encode(byte[] src, byte[] dest) + { + checkBufsiz(dest, src); + throw new UnsupportedOperationException("encode"); + } + + /** + * filter indexed by byte code. + */ + PredictorAlgorithm[] filter = { new None(), new Sub(), new Up(), new Average(), + new Paeth() }; + + /** + * @see org.pdfbox.pdmodel.graphics.predictor.PredictorAlgorithm#setBpp(int) + */ + public void setBpp(int bpp) + { + super.setBpp(bpp); + for (int i = 0; i < filter.length; i++) + { + filter[i].setBpp(bpp); + } + } + /** + * @see org.pdfbox.pdmodel.graphics.predictor.PredictorAlgorithm#setHeight(int) + */ + public void setHeight(int height) + { + super.setHeight(height); + for (int i = 0; i < filter.length; i++) + { + filter[i].setHeight(height); + } + } + + /** + * @see org.pdfbox.pdmodel.graphics.predictor.PredictorAlgorithm#setWidth(int) + */ + public void setWidth(int width) + { + super.setWidth(width); + for (int i = 0; i < filter.length; i++) + { + filter[i].setWidth(width); + } + } + + /** + * @see PredictorAlgorithm#decode(byte[], byte[]) + */ + public void decode(byte[] src, byte[] dest) + { + checkBufsiz(src, dest); + int bpl = getWidth() * getBpp(); + int srcDy = bpl + 1; + for (int y = 0; y < getHeight(); y++) + { + PredictorAlgorithm f = filter[src[y * srcDy]]; + int srcOffset = y * srcDy + 1; + f.decodeLine(src, dest, srcDy, srcOffset, bpl, y * bpl); + } + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/graphics/predictor/package.html b/src/main/java/org/pdfbox/pdmodel/graphics/predictor/package.html new file mode 100644 index 0000000..127d2e0 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/graphics/predictor/package.html @@ -0,0 +1,10 @@ + + + + + + +The predictor package contains code for different PNG predictor algorithms that +are present in PDF documents. These classes are used internally by PDFBox. + + diff --git a/src/main/java/org/pdfbox/pdmodel/graphics/xobject/PDCcitt.java b/src/main/java/org/pdfbox/pdmodel/graphics/xobject/PDCcitt.java new file mode 100644 index 0000000..59387a0 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/graphics/xobject/PDCcitt.java @@ -0,0 +1,598 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.graphics.xobject; + +import java.awt.image.BufferedImage; +import java.io.InputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.RandomAccessFile; + +import java.util.ArrayList; +import java.util.List; + +import javax.imageio.ImageIO; + +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSName; + +import org.pdfbox.pdmodel.PDDocument; +import org.pdfbox.pdmodel.common.PDStream; +import org.pdfbox.pdmodel.graphics.color.PDDeviceGray; + +/** + * An image class for CCITT Fax. + * + * @author paul king + * @version $Revision: 1.2 $ + */ +public class PDCcitt extends PDXObjectImage +{ + private static final List FAX_FILTERS = new ArrayList(); + + static + { + FAX_FILTERS.add( COSName.CCITTFAX_DECODE.getName() ); + FAX_FILTERS.add( COSName.CCITTFAX_DECODE_ABBREVIATION.getName() ); + } + + /** + * Standard constructor. + * + * @param ccitt The PDStream that already contains all ccitt information. + */ + public PDCcitt(PDStream ccitt) + { + super(ccitt, "tiff"); + + } + + /** + * Construct from a tiff file. + * + * @param doc The document to create the image as part of. + * @param raf The random access TIFF file which contains a suitable CCITT compressed image + * @throws IOException If there is an error reading the tiff data. + */ + + public PDCcitt( PDDocument doc, java.io.RandomAccessFile raf ) throws IOException + { + super( new PDStream(doc),"tiff"); + // super( new PDStream( doc, null, true ), "tiff" ); + + COSDictionary decodeParms = new COSDictionary(); + + COSDictionary dic = getCOSStream(); + + extractFromTiff(raf, getCOSStream().createFilteredStream(),decodeParms); + + dic.setItem( COSName.FILTER, COSName.CCITTFAX_DECODE); + dic.setItem( COSName.SUBTYPE, COSName.IMAGE); + dic.setItem( COSName.TYPE, COSName.getPDFName( "XObject" ) ); + dic.setItem( "DecodeParms", decodeParms); + + setBitsPerComponent( 1 ); + setColorSpace( new PDDeviceGray() ); + setWidth( decodeParms.getInt("Columns") ); + setHeight( decodeParms.getInt("Rows") ); + + } + + /** + * Returns an image of the CCITT Fax, or null if TIFFs are not supported. (Requires additional JAI Image filters ) + * @see org.pdfbox.pdmodel.graphics.xobject.PDXObjectImage#getRGBImage() + */ + public BufferedImage getRGBImage() throws IOException + { + // ImageIO.scanForPlugins(); + return ImageIO.read(new TiffWrapper(getPDStream().getPartiallyFilteredStream( FAX_FILTERS ),getCOSStream())); + } + + /** + * This writes a tiff to out. + * @see org.pdfbox.pdmodel.graphics.xobject.PDXObjectImage#write2OutputStream(java.io.OutputStream) + */ + public void write2OutputStream(OutputStream out) throws IOException + { + InputStream data = new TiffWrapper(getPDStream().getPartiallyFilteredStream( FAX_FILTERS ),getCOSStream()); + byte[] buf = new byte[1024]; + int amountRead = -1; + while( (amountRead = data.read( buf )) != -1 ) + { + out.write( buf, 0, amountRead ); + } + } + + /** + * Extract the ccitt stream from the tiff file. + * + * @param raf - TIFF File + * @param os - Stream to write raw ccitt data two + * @param parms - COSDictionary which the encoding parameters are added to + * @throws IOException If there is an error reading/writing to/from the stream + */ + private void extractFromTiff(RandomAccessFile raf, OutputStream os, COSDictionary parms) throws IOException + { + try + { + + // First check the basic tiff header + raf.seek(0); + char endianess = (char) raf.read(); + if ((char) raf.read() != endianess) + { + throw new IOException("Not a valid tiff file"); + } + //ensure that endianess is either M or I + if (endianess != 'M' && endianess != 'I') + { + throw new IOException("Not a valid tiff file"); + } + int magicNumber = readshort(endianess, raf); + if( magicNumber != 42) + { + throw new IOException("Not a valid tiff file"); + } + + // Relocate to the first set of tags + raf.seek(readlong(endianess, raf)); + + int numtags = readshort(endianess, raf); + + // The number 50 is somewhat arbitary, it just stops us load up junk from somewhere and tramping on + if (numtags > 50) + { + throw new IOException("Not a valid tiff file"); + } + + // Loop through the tags, some will convert to items in the parms dictionary + // Other point us to where to find the data stream + // The only parm which might change as a result of other options is K, so + // We'll deal with that as a special; + + int k=-1000; // Default Non CCITT compression + int dataoffset=0; + int datalength=0; + + for (int i=0; i < numtags; i++) + { + int tag = readshort(endianess, raf); + int type = readshort(endianess, raf); + int count = readlong(endianess, raf); + int val = readlong(endianess, raf); // See note + + // Note, we treated that value as a long. The value always occupies 4 bytes + // But it might only use the first byte or two. Depending on endianess we might need to correct + // Note we ignore all other types, they are of little interest for PDFs/CCITT Fax + if (endianess == 'M') + { + switch (type) + { + case 1: + { + val = val >> 24; + break; // byte value + } + case 3: + { + val = val >> 16; + break; // short value + } + case 4: + { + break; // long value + } + default: + { + //do nothing + } + } + } + switch (tag) + { + case 256: + { + parms.setInt("Columns",val); + break; + } + case 257: + { + parms.setInt("Rows",val); + break; + } + case 259: + { + if (val == 4) + { + k=-1; + } + if (val == 3) + { + k=0; + } + break; // T6/T4 Compression + } + case 262: + { + if (val == 1) + { + parms.setBoolean("BlackIs1", true); + } + break; + } + case 273: + { + if (count == 1) + { + dataoffset=val; + } + break; + } + case 279: + { + if (count == 1) + { + datalength=val; + } + break; + } + case 292: + { + if (val == 1) + { + k=50; // T4 2D - arbitary K value + } + break; + } + case 324: + { + if (count == 1) + { + dataoffset=val; + } + break; + } + case 325: + { + if (count == 1) + { + datalength=val; + } + break; + } + default: + { + //do nothing + } + } + } + + if (k == -1000) + { + throw new IOException("First image in tiff is not CCITT T4 or T6 compressed"); + } + if (dataoffset == 0) + { + throw new IOException("First image in tiff is not a single tile/strip"); + } + + parms.setInt("K",k); + + raf.seek(dataoffset); + + byte[] buf = new byte[8192]; + int amountRead = -1; + while( (amountRead = raf.read( buf,0, Math.min(8192,datalength) )) > 0 ) + { + datalength -= amountRead; + os.write( buf, 0, amountRead ); + } + + } + finally + { + os.close(); + } + } + + private int readshort(char endianess, RandomAccessFile raf) throws IOException + { + if (endianess == 'I') + { + return raf.read() | (raf.read() << 8); + } + return (raf.read() << 8) | raf.read(); + } + + private int readlong(char endianess, RandomAccessFile raf) throws IOException + { + if (endianess == 'I') + { + return raf.read() | (raf.read() << 8) | (raf.read() << 16) | (raf.read() << 24); + } + return (raf.read() << 24) | (raf.read() << 16) | (raf.read() << 8) | raf.read(); + } + + + /** + * Extends InputStream to wrap the data from the CCITT Fax with a suitable TIFF Header. + * For details see www.tiff.org, which contains useful information including pointers to the + * TIFF 6.0 Specification + * + */ + private class TiffWrapper extends InputStream + { + + private int currentOffset; // When reading, where in the tiffheader are we. + private byte[] tiffheader; // Byte array to store tiff header data + private InputStream datastream; // Original InputStream + + public TiffWrapper(InputStream rawstream, COSDictionary options) + { + buildHeader(options); + currentOffset=0; + datastream = rawstream; + } + + // Implement basic methods from InputStream + + public boolean markSupported() + { + return false; + } + + public void reset() throws IOException + { + throw new IOException("reset not supported"); + } + + // For simple read, take a byte from the tiffheader array or pass through. + public int read() throws IOException + { + if (currentOffset < tiffheader.length) + { + return tiffheader[currentOffset++]; + } + return datastream.read(); + } + + // For read methods only return as many bytes as we have left in the header + // if we've exhausted the header, pass through to the InputStream of the raw CCITT data + public int read(byte[] data) throws IOException + { + if (currentOffset < tiffheader.length) + { + int length = java.lang.Math.min(tiffheader.length - currentOffset, data.length); + if (length > 0) + { + System.arraycopy(tiffheader, currentOffset, data, 0, length); + } + currentOffset += length; + return length; + } + else + { + return datastream.read(data); + } + } + + // For read methods only return as many bytes as we have left in the header + // if we've exhausted the header, pass through to the InputStream of the raw CCITT data + public int read(byte[] data, int off, int len) throws IOException + { + if (currentOffset < tiffheader.length) + { + int length = java.lang.Math.min(tiffheader.length - currentOffset, len); + if (length > 0) + { + System.arraycopy(tiffheader, currentOffset, data, off, length); + } + currentOffset += length; + return length; + } + else + { + return datastream.read(data,off,len); + } + } + + // When skipping if any header data not yet read, only allow to skip what we've in the buffer + // Otherwise just pass through. + public long skip(long n) throws IOException + { + if (currentOffset < tiffheader.length) + { + long length = Math.min(tiffheader.length - currentOffset, n); + currentOffset += length; + return length; + } + else + { + return datastream.skip(n); + } + } + + // Static data for the beginning of the TIFF header + private final byte[] basicHeader = { + 'I','I',42,0,8,0,0,0, // File introducer and pointer to first IFD + 0,0}; // Number of tags start with two + + + private int additionalOffset; // Offset in header to additional data + + // Builds up the tiffheader based on the options passed through. + private void buildHeader(COSDictionary options) + { + + final int numOfTags = 10; // The maximum tags we'll fill + final int maxAdditionalData = 24; // The maximum amount of additional data + // outside the IFDs. (bytes) + + // The length of the header will be the length of the basic header (10) + // plus 12 bytes for each IFD, 4 bytes as a pointer to the next IFD (will be 0) + // plus the length of the additional data + + tiffheader = new byte[10 + (12 * numOfTags ) + 4 + maxAdditionalData]; + java.util.Arrays.fill(tiffheader,(byte)0); + System.arraycopy(basicHeader,0,tiffheader,0,basicHeader.length); + + // Additional data outside the IFD starts after the IFD's and pointer to the next IFD (0) + additionalOffset = 10 + (12 * numOfTags ) + 4; + + // Now work out the variable values from TIFF defaults, + // PDF Defaults and the Dictionary for this XObject + short cols = 1728; + short rows = 0; + short blackis1 = 0; + short comptype = 3; // T4 compression + long t4options = 0; // Will set if 1d or 2d T4 + + COSDictionary decodeParms = (COSDictionary) options.getDictionaryObject("DecodeParms"); + + if (decodeParms != null) + { + cols = (short) decodeParms.getInt("Columns", cols); + rows = (short) decodeParms.getInt("Rows", rows); + if (decodeParms.getBoolean("BlackIs1", false)) + { + blackis1 = 1; + } + int k = decodeParms.getInt("K"); // Mandatory parm + if (k < 0) + { + //T6 + comptype = 4; + } + if (k > 0) + { + //T4 2D + comptype = 3; + t4options = 1; + } + // else k = 0, leave as default T4 1D compression + } + + // If we couldn't get the number of rows, use the main item from XObject + if (rows == 0) + { + rows = (short) options.getInt("Height", rows); + } + + // Now put the tags into the tiffheader + // These musn't exceed the maximum set above, and by TIFF spec should be sorted into + // Numeric sequence. + + addTag(256, cols); // Columns + addTag(257, rows); // Rows + addTag(259, comptype); // T6 + addTag(262, blackis1); // Photometric Interpretation + addTag(273, (long) tiffheader.length); // Offset to start of image data - updated below + addTag(279, (long) options.getInt("Length")); // Length of image data + addTag(282, 300, 1); // X Resolution 300 (default unit Inches) This is arbitary + addTag(283, 300, 1); // Y Resolution 300 (default unit Inches) This is arbitary + if (comptype == 3) + { + addTag(292, t4options); + } + addTag(305, "PDFBOX"); // Software generating image + } + + /* Tiff types 1 = byte, 2=ascii, 3=short, 4=ulong 5=rational */ + + private void addTag(int tag,long value) + { + // Adds a tag of type 4 (ulong) + int count = ++tiffheader[8]; + int offset = (count-1)*12 + 10; + tiffheader[offset]=(byte)(tag & 0xff); + tiffheader[offset+1]=(byte)((tag>>8) & 0xff); + tiffheader[offset+2]=4; // Type Long + tiffheader[offset+4]=1; // One Value + tiffheader[offset+8]=(byte)(value & 0xff); + tiffheader[offset+9]=(byte)((value>>8) & 0xff); + tiffheader[offset+10]=(byte)((value>>16) & 0xff); + tiffheader[offset+11]=(byte)((value>>24) & 0xff); + } + + private void addTag(int tag, short value) + { + // Adds a tag of type 3 (short) + int count = ++tiffheader[8]; + int offset = (count-1)*12 + 10; + tiffheader[offset]=(byte)(tag & 0xff); + tiffheader[offset+1]=(byte)((tag>>8) & 0xff); + tiffheader[offset+2]=3; // Type Short + tiffheader[offset+4]=1; // One Value + tiffheader[offset+8]=(byte)(value & 0xff); + tiffheader[offset+9]=(byte)((value>>8) & 0xff); + } + + private void addTag(int tag, String value) + { + // Adds a tag of type 2 (ascii) + int count = ++tiffheader[8]; + int offset = (count-1)*12 + 10; + tiffheader[offset]=(byte)(tag & 0xff); + tiffheader[offset+1]=(byte)((tag>>8) & 0xff); + tiffheader[offset+2]=2; // Type Ascii + tiffheader[offset+4]=1; // One Value + tiffheader[offset+8]=(byte)(additionalOffset & 0xff); + tiffheader[offset+9]=(byte)((additionalOffset>>8) & 0xff); + tiffheader[offset+10]=(byte)((additionalOffset>>16) & 0xff); + tiffheader[offset+11]=(byte)((additionalOffset>>24) & 0xff); + System.arraycopy(value.getBytes(), 0, tiffheader, additionalOffset, value.length()); + additionalOffset += value.length() + 1; + } + + private void addTag(int tag, long numerator, long denominator) + { + // Adds a tag of type 5 (rational) + int count = ++tiffheader[8]; + int offset = (count-1)*12 + 10; + tiffheader[offset]=(byte)(tag & 0xff); + tiffheader[offset+1]=(byte)((tag>>8) & 0xff); + tiffheader[offset+2]=5; // Type Rational + tiffheader[offset+4]=1; // One Value + tiffheader[offset+8]=(byte)(additionalOffset & 0xff); + tiffheader[offset+9]=(byte)((additionalOffset>>8) & 0xff); + tiffheader[offset+10]=(byte)((additionalOffset>>16) & 0xff); + tiffheader[offset+11]=(byte)((additionalOffset>>24) & 0xff); + tiffheader[additionalOffset++]=(byte) ((numerator) & 0xFF); + tiffheader[additionalOffset++]=(byte) ((numerator>>8) & 0xFF); + tiffheader[additionalOffset++]=(byte) ((numerator>>16) & 0xFF); + tiffheader[additionalOffset++]=(byte) ((numerator>>24) & 0xFF); + tiffheader[additionalOffset++]=(byte) ((denominator) & 0xFF); + tiffheader[additionalOffset++]=(byte) ((denominator>>8) & 0xFF); + tiffheader[additionalOffset++]=(byte) ((denominator>>16) & 0xFF); + tiffheader[additionalOffset++]=(byte) ((denominator>>24) & 0xFF); + } + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/graphics/xobject/PDInlinedImage.java b/src/main/java/org/pdfbox/pdmodel/graphics/xobject/PDInlinedImage.java new file mode 100644 index 0000000..009743f --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/graphics/xobject/PDInlinedImage.java @@ -0,0 +1,201 @@ +/** + * Copyright (c) 2003-2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.graphics.xobject; + +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; +import java.awt.image.DataBuffer; +import java.awt.image.DataBufferByte; +import java.awt.image.DataBufferInt; +import java.awt.image.IndexColorModel; +import java.awt.image.WritableRaster; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.List; + +import org.pdfbox.filter.Filter; +import org.pdfbox.filter.FilterManager; +import org.pdfbox.pdmodel.graphics.color.PDColorSpace; +import org.pdfbox.util.ImageParameters; + +/** + * This class represents an inlined image. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.4 $ + */ +public class PDInlinedImage +{ + private ImageParameters params; + private byte[] imageData; + + /** + * This will get the image parameters. + * + * @return The image parameters. + */ + public ImageParameters getImageParameters() + { + return params; + } + + /** + * This will set the image parameters for this image. + * + * @param imageParams The imageParams. + */ + public void setImageParameters( ImageParameters imageParams ) + { + params = imageParams; + } + + /** + * Get the bytes for the image. + * + * @return The image data. + */ + public byte[] getImageData() + { + return imageData; + } + + /** + * Set the bytes that make up the image. + * + * @param value The image data. + */ + public void setImageData(byte[] value) + { + imageData = value; + } + + /** + * This will take the inlined image information and create a java.awt.Image from + * it. + * + * @return The image that this object represents. + * + * @throws IOException If there is an error creating the image. + */ + public BufferedImage createImage() throws IOException + { + /* + * This was the previous implementation, not sure which is better right now. + * byte[] transparentColors = new byte[]{(byte)0xFF,(byte)0xFF}; + byte[] colors=new byte[]{0, (byte)0xFF}; + IndexColorModel colorModel = new IndexColorModel( 1, 2, colors, colors, colors, transparentColors ); + BufferedImage image = new BufferedImage( + params.getWidth(), + params.getHeight(), + BufferedImage.TYPE_BYTE_BINARY, + colorModel ); + DataBufferByte buffer = new DataBufferByte( getImageData(), 1 ); + WritableRaster raster = + Raster.createPackedRaster( + buffer, + params.getWidth(), + params.getHeight(), + params.getBitsPerComponent(), + new Point(0,0) ); + image.setData( raster ); + return image; + */ + + + //verify again pci32.pdf before changing below + PDColorSpace pcs = params.getColorSpace(); + ColorModel colorModel = null; + if(pcs != null) + { + colorModel = + params.getColorSpace().createColorModel( + params.getBitsPerComponent() ); + } + else + { + byte[] transparentColors = new + byte[]{(byte)0xFF,(byte)0xFF}; + byte[] colors=new byte[]{0, (byte)0xFF}; + colorModel = new IndexColorModel( 1, 2, + colors, colors, colors, transparentColors ); + } + List filters = params.getFilters(); + byte[] finalData = null; + if( filters == null ) + { + finalData = getImageData(); + } + else + { + ByteArrayInputStream in = new ByteArrayInputStream( getImageData() ); + ByteArrayOutputStream out = new ByteArrayOutputStream(getImageData().length); + FilterManager filterManager = new FilterManager(); + for( int i=0; filters != null && i + *
  • 1 No prediction (the default value) + *
  • 2 TIFF Predictor 2 + *
  • 10 PNG prediction (on encoding, PNG None on all rows) + *
  • 11 PNG prediction (on encoding, PNG Sub on all rows) + *
  • 12 PNG prediction (on encoding, PNG Up on all rows) + *
  • 13 PNG prediction (on encoding, PNG Average on all rows) + *
  • 14 PNG prediction (on encoding, PNG Paeth on all rows) + *
  • 15 PNG prediction (on encoding, PNG optimum) + * + * + * Default value: 1. + * + * @return predictor algorithm code + */ + public int getPredictor() + { + COSDictionary decodeParms = getDecodeParams(); + if (decodeParms != null) + { + int i = decodeParms.getInt("Predictor"); + if (i != -1) + { + return i; + } + } + return 1; + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/graphics/xobject/PDXObject.java b/src/main/java/org/pdfbox/pdmodel/graphics/xobject/PDXObject.java new file mode 100644 index 0000000..99ac8a5 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/graphics/xobject/PDXObject.java @@ -0,0 +1,207 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.graphics.xobject; + +import java.io.IOException; +import java.util.List; + +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSName; +import org.pdfbox.cos.COSStream; + +import org.pdfbox.pdmodel.PDDocument; +import org.pdfbox.pdmodel.common.COSObjectable; +import org.pdfbox.pdmodel.common.PDMetadata; +import org.pdfbox.pdmodel.common.PDStream; + +/** + * The base class for all XObjects in the PDF document. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @author mathiak + * @author Marcel Kammer + * @version $Revision: 1.12 $ + */ +public abstract class PDXObject implements COSObjectable +{ + private PDStream xobject; + + /** + * Standard constuctor. + * + * @param xobj The XObject dictionary. + */ + public PDXObject(COSStream xobj) + { + xobject = new PDStream( xobj ); + } + + /** + * Standard constuctor. + * + * @param xobj The XObject dictionary. + */ + public PDXObject(PDStream xobj) + { + xobject = xobj; + } + + /** + * Standard constuctor. + * + * @param doc The doc to store the object contents. + */ + public PDXObject(PDDocument doc) + { + xobject = new PDStream(doc); + xobject.getStream().setName( COSName.TYPE, "XObject" ); + } + + /** + * Returns the stream. + * @see org.pdfbox.pdmodel.common.COSObjectable#getCOSObject() + */ + public COSBase getCOSObject() + { + return xobject.getCOSObject(); + } + + /** + * Returns the stream. + * @return The stream for this object. + */ + public COSStream getCOSStream() + { + return xobject.getStream(); + } + + /** + * Returns the stream. + * @return The stream for this object. + */ + public PDStream getPDStream() + { + return xobject; + } + + /** + * Create the correct xobject from the cos base. + * + * @param xobject The cos level xobject to create. + * + * @return a pdmodel xobject + * @throws IOException If there is an error creating the xobject. + */ + public static PDXObject createXObject( COSBase xobject ) throws IOException + { + PDXObject retval = null; + if( xobject == null ) + { + retval = null; + } + else if( xobject instanceof COSStream ) + { + COSStream xstream = (COSStream)xobject; + String subtype = xstream.getNameAsString( "Subtype" ); + if( subtype.equals( PDXObjectImage.SUB_TYPE ) ) + { + PDStream image = new PDStream( xstream ); + // See if filters are DCT or JPX otherwise treat as Bitmap-like + // There might be a problem with several filters, but that's ToDo until + // I find an example + List filters = image.getFilters(); + if( filters != null && filters.contains( COSName.DCT_DECODE.getName() ) ) + { + return new PDJpeg(image); + } + else if ( filters != null && filters.contains( COSName.CCITTFAX_DECODE.getName() ) ) + { + return new PDCcitt(image); + } + else if( filters != null && filters.contains(COSName.JPX_DECODE.getName())) + { + //throw new IOException( "JPXDecode has not been implemented for images" ); + //JPX Decode is not really supported right now, but if we are just doing + //text extraction then we don't want to throw an exception, so for now + //just return a PDPixelMap, which will break later on if it is + //actually used, but for text extraction it is not used. + return new PDPixelMap( image ); + + } + else + { + retval = new PDPixelMap(image); + } + } + else if( subtype.equals( PDXObjectForm.SUB_TYPE ) ) + { + retval = new PDXObjectForm( xstream ); + } + else + { + throw new IOException( "Unknown xobject subtype '" + subtype + "'" ); + } + } + else + { + throw new IOException( "Unknown xobject type:" + xobject.getClass().getName() ); + } + + return retval; + } + + /** + * Get the metadata that is part of the document catalog. This will + * return null if there is no meta data for this object. + * + * @return The metadata for this object. + */ + public PDMetadata getMetadata() + { + PDMetadata retval = null; + COSStream mdStream = (COSStream)xobject.getStream().getDictionaryObject( "Metadata" ); + if( mdStream != null ) + { + retval = new PDMetadata( mdStream ); + } + return retval; + } + + /** + * Set the metadata for this object. This can be null. + * + * @param meta The meta data for this object. + */ + public void setMetadata( PDMetadata meta ) + { + xobject.getStream().setItem( "Metadata", meta ); + } +} diff --git a/src/main/java/org/pdfbox/pdmodel/graphics/xobject/PDXObjectForm.java b/src/main/java/org/pdfbox/pdmodel/graphics/xobject/PDXObjectForm.java new file mode 100644 index 0000000..08858ea --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/graphics/xobject/PDXObjectForm.java @@ -0,0 +1,120 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.graphics.xobject; + +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSName; +import org.pdfbox.cos.COSStream; + +import org.pdfbox.pdmodel.PDResources; +import org.pdfbox.pdmodel.common.PDStream; + +/** + * A form xobject. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.4 $ + */ +public class PDXObjectForm extends PDXObject +{ + /** + * The XObject subtype. + */ + public static final String SUB_TYPE = "Form"; + + /** + * Standard constuctor. + * + * @param formStream The XObject is passed as a COSStream. + */ + public PDXObjectForm(PDStream formStream) + { + super( formStream ); + } + + /** + * Standard constuctor. + * + * @param formStream The XObject is passed as a COSStream. + */ + public PDXObjectForm(COSStream formStream) + { + super( formStream ); + } + + /** + * This will get the form type, currently 1 is the only form type. + * + * @return The form type. + */ + public int getFormType() + { + return getCOSStream().getInt( "FormType",1 ); + } + + /** + * Set the form type. + * + * @param formType The new form type. + */ + public void setFormType( int formType ) + { + getCOSStream().setInt( "FormType", formType ); + } + + /** + * This will get the resources at this page and not look up the hierarchy. + * This attribute is inheritable, and findResources() should probably used. + * This will return null if no resources are available at this level. + * + * @return The resources at this level in the hierarchy. + */ + public PDResources getResources() + { + PDResources retval = null; + COSDictionary resources = (COSDictionary)getCOSStream().getDictionaryObject( COSName.RESOURCES ); + if( resources != null ) + { + retval = new PDResources( resources ); + } + return retval; + } + + /** + * This will set the resources for this page. + * + * @param resources The new resources for this page. + */ + public void setResources( PDResources resources ) + { + getCOSStream().setItem( COSName.RESOURCES, resources ); + } +} diff --git a/src/main/java/org/pdfbox/pdmodel/graphics/xobject/PDXObjectImage.java b/src/main/java/org/pdfbox/pdmodel/graphics/xobject/PDXObjectImage.java new file mode 100644 index 0000000..6257113 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/graphics/xobject/PDXObjectImage.java @@ -0,0 +1,244 @@ +/** + * Copyright (c) 2004-2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.graphics.xobject; + +import java.awt.image.BufferedImage; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSName; +import org.pdfbox.pdmodel.PDDocument; +import org.pdfbox.pdmodel.common.PDStream; +import org.pdfbox.pdmodel.graphics.color.PDColorSpace; +import org.pdfbox.pdmodel.graphics.color.PDColorSpaceFactory; +import org.pdfbox.pdmodel.graphics.color.PDDeviceGray; + +/** + * The prototype for all PDImages. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @author mathiak + * @version $Revision: 1.8 $ + */ +public abstract class PDXObjectImage extends PDXObject +{ + /** + * The XObject subtype. + */ + public static final String SUB_TYPE = "Image"; + + /** + * This contains the suffix used when writing to file. + */ + private String suffix; + + /** + * Standard constuctor. + * + * @param imageStream The XObject is passed as a COSStream. + * @param fileSuffix The file suffix, jpg/png. + */ + public PDXObjectImage(PDStream imageStream, String fileSuffix) + { + super( imageStream ); + suffix = fileSuffix; + } + + /** + * Standard constuctor. + * + * @param doc The document to store the stream in. + * @param fileSuffix The file suffix, jpg/png. + */ + public PDXObjectImage(PDDocument doc, String fileSuffix) + { + super( doc ); + getCOSStream().setName( COSName.SUBTYPE, SUB_TYPE ); + suffix = fileSuffix; + } + + /** + * Returns an java.awt.Image, that can be used for display etc. + * + * @return This PDF object as an AWT image. + * + * @throws IOException If there is an error creating the image. + */ + public abstract BufferedImage getRGBImage() throws IOException; + + /** + * Writes the Image to out. + * @param out the OutputStream that the Image is written to. + * @throws IOException when somethings wrong with out + */ + public abstract void write2OutputStream(OutputStream out) throws IOException; + + /** + * Writes the image to a file with the filename + an appropriate suffix, like "Image.jpg". + * The suffix is automatically set by the + * @param filename the filename + * @throws IOException When somethings wrong with the corresponding file. + */ + public void write2file(String filename) throws IOException + { + FileOutputStream out = null; + try + { + out = new FileOutputStream(filename + "." + suffix); + write2OutputStream(out); + out.flush(); + } + finally + { + if( out != null ) + { + out.close(); + } + } + } + + /** + * Get the height of the image. + * + * @return The height of the image. + */ + public int getHeight() + { + return getCOSStream().getInt( "Height", -1 ); + } + + /** + * Set the height of the image. + * + * @param height The height of the image. + */ + public void setHeight( int height ) + { + getCOSStream().setInt( "Height", height ); + } + + /** + * Get the width of the image. + * + * @return The width of the image. + */ + public int getWidth() + { + return getCOSStream().getInt( "Width", -1 ); + } + + /** + * Set the width of the image. + * + * @param width The width of the image. + */ + public void setWidth( int width ) + { + getCOSStream().setInt( "Width", width ); + } + + /** + * The bits per component of this image. This will return -1 if one has not + * been set. + * + * @return The number of bits per component. + */ + public int getBitsPerComponent() + { + return getCOSStream().getInt( new String[] { "BPC", "BitsPerComponent"}, -1 ); + } + + /** + * Set the number of bits per component. + * + * @param bpc The number of bits per component. + */ + public void setBitsPerComponent( int bpc ) + { + getCOSStream().setInt( "BitsPerComponent", bpc ); + } + + /** + * This will get the color space or null if none exists. + * + * @return The color space for this image. + * + * @throws IOException If there is an error getting the colorspace. + */ + public PDColorSpace getColorSpace() throws IOException + { + COSBase cs = getCOSStream().getDictionaryObject( new String[]{ "CS", "ColorSpace" } ); + PDColorSpace retval = null; + if( cs != null ) + { + retval = PDColorSpaceFactory.createColorSpace( cs ); + } + else + { + //there are some cases where the 'required' CS value is not present + //but we know that it will be grayscale for a CCITT filter. + COSBase filter = getCOSStream().getDictionaryObject( "Filter" ); + if( COSName.CCITTFAX_DECODE.equals( filter ) || + COSName.CCITTFAX_DECODE_ABBREVIATION.equals( filter ) ) + { + retval = new PDDeviceGray(); + } + } + return retval; + } + + /** + * This will set the color space for this image. + * + * @param cs The color space for this image. + */ + public void setColorSpace( PDColorSpace cs ) + { + COSBase base = null; + if( cs != null ) + { + base = cs.getCOSObject(); + } + getCOSStream().setItem( COSName.getPDFName( "ColorSpace" ), base ); + } + + /** + * This will get the suffix for this image type, jpg/png. + * + * @return The image suffix. + */ + public String getSuffix() + { + return suffix; + } +} diff --git a/src/main/java/org/pdfbox/pdmodel/graphics/xobject/package.html b/src/main/java/org/pdfbox/pdmodel/graphics/xobject/package.html new file mode 100644 index 0000000..60d3324 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/graphics/xobject/package.html @@ -0,0 +1,9 @@ + + + + + + +This package deals with images that are stored in a PDF document. + + diff --git a/src/main/java/org/pdfbox/pdmodel/interactive/action/PDActionFactory.java b/src/main/java/org/pdfbox/pdmodel/interactive/action/PDActionFactory.java new file mode 100644 index 0000000..bf0c156 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/interactive/action/PDActionFactory.java @@ -0,0 +1,96 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.interactive.action; + +import org.pdfbox.cos.COSDictionary; + +import org.pdfbox.pdmodel.interactive.action.type.PDAction; +import org.pdfbox.pdmodel.interactive.action.type.PDActionGoTo; +import org.pdfbox.pdmodel.interactive.action.type.PDActionJavaScript; +import org.pdfbox.pdmodel.interactive.action.type.PDActionLaunch; +import org.pdfbox.pdmodel.interactive.action.type.PDActionRemoteGoTo; +import org.pdfbox.pdmodel.interactive.action.type.PDActionURI; + +/** + * This class will take a dictionary and determine which type of action to create. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.4 $ + */ +public class PDActionFactory +{ + /** + * Utility Class. + */ + private PDActionFactory() + { + //utility class + } + + /** + * This will create the correct type of action based on the type specified + * in the dictionary. + * + * @param action An action dictionary. + * + * @return An action of the correct type. + */ + public static PDAction createAction( COSDictionary action ) + { + PDAction retval = null; + if( action != null ) + { + String type = action.getNameAsString( "S" ); + if( PDActionJavaScript.SUB_TYPE.equals( type ) ) + { + retval = new PDActionJavaScript( action ); + } + else if( PDActionGoTo.SUB_TYPE.equals( type ) ) + { + retval = new PDActionGoTo( action ); + } + else if( PDActionLaunch.SUB_TYPE.equals( type ) ) + { + retval = new PDActionLaunch( action ); + } + else if( PDActionRemoteGoTo.SUB_TYPE.equals( type ) ) + { + retval = new PDActionRemoteGoTo( action ); + } + else if( PDActionURI.SUB_TYPE.equals( type ) ) + { + retval = new PDActionURI( action ); + } + } + return retval; + } + +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/interactive/action/PDAdditionalActions.java b/src/main/java/org/pdfbox/pdmodel/interactive/action/PDAdditionalActions.java new file mode 100644 index 0000000..fc2f79b --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/interactive/action/PDAdditionalActions.java @@ -0,0 +1,106 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.interactive.action; + +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSDictionary; + +import org.pdfbox.pdmodel.common.COSObjectable; +import org.pdfbox.pdmodel.interactive.action.type.PDAction; + +/** + * This represents a dictionary of actions that occur due to events. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.3 $ + */ +public class PDAdditionalActions implements COSObjectable +{ + private COSDictionary actions; + + /** + * Default constructor. + */ + public PDAdditionalActions() + { + actions = new COSDictionary(); + } + + /** + * Constructor. + * + * @param a The action dictionary. + */ + public PDAdditionalActions( COSDictionary a ) + { + actions = a; + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSBase getCOSObject() + { + return actions; + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSDictionary getCOSDictionary() + { + return actions; + } + + /** + * Get the F action. + * + * @return The F action. + */ + public PDAction getF() + { + return PDActionFactory.createAction( (COSDictionary)actions.getDictionaryObject("F" ) ); + } + + /** + * Set the F action. + * + * @param action Get the F action. + */ + public void setF( PDAction action ) + { + actions.setItem( "F", action ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/interactive/action/PDAnnotationAdditionalActions.java b/src/main/java/org/pdfbox/pdmodel/interactive/action/PDAnnotationAdditionalActions.java new file mode 100644 index 0000000..9b9232e --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/interactive/action/PDAnnotationAdditionalActions.java @@ -0,0 +1,380 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.interactive.action; + +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSDictionary; + +import org.pdfbox.pdmodel.common.COSObjectable; +import org.pdfbox.pdmodel.interactive.action.type.PDAction; + +/** + * This class represents an annotation's dictionary of actions + * that occur due to events. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @author Panagiotis Toumasis (ptoumasis@mail.gr) + * @version $Revision: 1.1 $ + */ +public class PDAnnotationAdditionalActions implements COSObjectable +{ + private COSDictionary actions; + + /** + * Default constructor. + */ + public PDAnnotationAdditionalActions() + { + actions = new COSDictionary(); + } + + /** + * Constructor. + * + * @param a The action dictionary. + */ + public PDAnnotationAdditionalActions( COSDictionary a ) + { + actions = a; + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSBase getCOSObject() + { + return actions; + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSDictionary getCOSDictionary() + { + return actions; + } + + /** + * This will get an action to be performed when the cursor + * enters the annotation's active area. + * + * @return The E entry of annotation's additional actions dictionary. + */ + public PDAction getE() + { + COSDictionary e = (COSDictionary)actions.getDictionaryObject( "E" ); + PDAction retval = null; + if( e != null ) + { + retval = PDActionFactory.createAction( e ); + } + return retval; + } + + /** + * This will set an action to be performed when the cursor + * enters the annotation's active area. + * + * @param e The action to be performed. + */ + public void setE( PDAction e ) + { + actions.setItem( "E", e ); + } + + /** + * This will get an action to be performed when the cursor + * exits the annotation's active area. + * + * @return The X entry of annotation's additional actions dictionary. + */ + public PDAction getX() + { + COSDictionary x = (COSDictionary)actions.getDictionaryObject( "X" ); + PDAction retval = null; + if( x != null ) + { + retval = PDActionFactory.createAction( x ); + } + return retval; + } + + /** + * This will set an action to be performed when the cursor + * exits the annotation's active area. + * + * @param x The action to be performed. + */ + public void setX( PDAction x ) + { + actions.setItem( "X", x ); + } + + /** + * This will get an action to be performed when the mouse button + * is pressed inside the annotation's active area. + * The name D stands for "down". + * + * @return The d entry of annotation's additional actions dictionary. + */ + public PDAction getD() + { + COSDictionary d = (COSDictionary)actions.getDictionaryObject( "D" ); + PDAction retval = null; + if( d != null ) + { + retval = PDActionFactory.createAction( d ); + } + return retval; + } + + /** + * This will set an action to be performed when the mouse button + * is pressed inside the annotation's active area. + * The name D stands for "down". + * + * @param d The action to be performed. + */ + public void setD( PDAction d ) + { + actions.setItem( "D", d ); + } + + /** + * This will get an action to be performed when the mouse button + * is released inside the annotation's active area. + * The name U stands for "up". + * + * @return The U entry of annotation's additional actions dictionary. + */ + public PDAction getU() + { + COSDictionary u = (COSDictionary)actions.getDictionaryObject( "U" ); + PDAction retval = null; + if( u != null ) + { + retval = PDActionFactory.createAction( u ); + } + return retval; + } + + /** + * This will set an action to be performed when the mouse button + * is released inside the annotation's active area. + * The name U stands for "up". + * + * @param u The action to be performed. + */ + public void setU( PDAction u ) + { + actions.setItem( "U", u ); + } + + /** + * This will get an action to be performed when the annotation + * receives the input focus. + * + * @return The Fo entry of annotation's additional actions dictionary. + */ + public PDAction getFo() + { + COSDictionary fo = (COSDictionary)actions.getDictionaryObject( "Fo" ); + PDAction retval = null; + if( fo != null ) + { + retval = PDActionFactory.createAction( fo ); + } + return retval; + } + + /** + * This will set an action to be performed when the annotation + * receives the input focus. + * + * @param fo The action to be performed. + */ + public void setFo( PDAction fo ) + { + actions.setItem( "Fo", fo ); + } + + /** + * This will get an action to be performed when the annotation + * loses the input focus. + * The name Bl stands for "blurred". + * + * @return The Bl entry of annotation's additional actions dictionary. + */ + public PDAction getBl() + { + COSDictionary bl = (COSDictionary)actions.getDictionaryObject( "Bl" ); + PDAction retval = null; + if( bl != null ) + { + retval = PDActionFactory.createAction( bl ); + } + return retval; + } + + /** + * This will set an action to be performed when the annotation + * loses the input focus. + * The name Bl stands for "blurred". + * + * @param bl The action to be performed. + */ + public void setBl( PDAction bl ) + { + actions.setItem( "Bl", bl ); + } + + /** + * This will get an action to be performed when the page containing + * the annotation is opened. The action is executed after the O action + * in the page's additional actions dictionary and the OpenAction entry + * in the document catalog, if such actions are present. + * + * @return The PO entry of annotation's additional actions dictionary. + */ + public PDAction getPO() + { + COSDictionary po = (COSDictionary)actions.getDictionaryObject( "PO" ); + PDAction retval = null; + if( po != null ) + { + retval = PDActionFactory.createAction( po ); + } + return retval; + } + + /** + * This will set an action to be performed when the page containing + * the annotation is opened. The action is executed after the O action + * in the page's additional actions dictionary and the OpenAction entry + * in the document catalog, if such actions are present. + * + * @param po The action to be performed. + */ + public void setPO( PDAction po ) + { + actions.setItem( "PO", po ); + } + + /** + * This will get an action to be performed when the page containing + * the annotation is closed. The action is executed before the C action + * in the page's additional actions dictionary, if present. + * + * @return The PC entry of annotation's additional actions dictionary. + */ + public PDAction getPC() + { + COSDictionary pc = (COSDictionary)actions.getDictionaryObject( "PC" ); + PDAction retval = null; + if( pc != null ) + { + retval = PDActionFactory.createAction( pc ); + } + return retval; + } + + /** + * This will set an action to be performed when the page containing + * the annotation is closed. The action is executed before the C action + * in the page's additional actions dictionary, if present. + * + * @param pc The action to be performed. + */ + public void setPC( PDAction pc ) + { + actions.setItem( "PC", pc ); + } + + /** + * This will get an action to be performed when the page containing + * the annotation becomes visible in the viewer application's user interface. + * + * @return The PV entry of annotation's additional actions dictionary. + */ + public PDAction getPV() + { + COSDictionary pv = (COSDictionary)actions.getDictionaryObject( "PV" ); + PDAction retval = null; + if( pv != null ) + { + retval = PDActionFactory.createAction( pv ); + } + return retval; + } + + /** + * This will set an action to be performed when the page containing + * the annotation becomes visible in the viewer application's user interface. + * + * @param pv The action to be performed. + */ + public void setPV( PDAction pv ) + { + actions.setItem( "PV", pv ); + } + + /** + * This will get an action to be performed when the page containing the annotation + * is no longer visible in the viewer application's user interface. + * + * @return The PI entry of annotation's additional actions dictionary. + */ + public PDAction getPI() + { + COSDictionary pi = (COSDictionary)actions.getDictionaryObject( "PI" ); + PDAction retval = null; + if( pi != null ) + { + retval = PDActionFactory.createAction( pi ); + } + return retval; + } + + /** + * This will set an action to be performed when the page containing the annotation + * is no longer visible in the viewer application's user interface. + * + * @param pi The action to be performed. + */ + public void setPI( PDAction pi ) + { + actions.setItem( "PI", pi ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/interactive/action/PDDocumentCatalogAdditionalActions.java b/src/main/java/org/pdfbox/pdmodel/interactive/action/PDDocumentCatalogAdditionalActions.java new file mode 100644 index 0000000..6164de1 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/interactive/action/PDDocumentCatalogAdditionalActions.java @@ -0,0 +1,238 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.interactive.action; + +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSDictionary; + +import org.pdfbox.pdmodel.common.COSObjectable; +import org.pdfbox.pdmodel.interactive.action.type.PDAction; + +/** + * This class represents a document catalog's dictionary of actions + * that occur due to events. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @author Panagiotis Toumasis (ptoumasis@mail.gr) + * @version $Revision: 1.1 $ + */ +public class PDDocumentCatalogAdditionalActions implements COSObjectable +{ + private COSDictionary actions; + + /** + * Default constructor. + */ + public PDDocumentCatalogAdditionalActions() + { + actions = new COSDictionary(); + } + + /** + * Constructor. + * + * @param a The action dictionary. + */ + public PDDocumentCatalogAdditionalActions( COSDictionary a ) + { + actions = a; + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSBase getCOSObject() + { + return actions; + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSDictionary getCOSDictionary() + { + return actions; + } + + /** + * This will get a JavaScript action to be performed + * before closing a document. + * The name WC stands for "will close". + * + * @return The WC entry of document catalog's additional actions dictionary. + */ + public PDAction getWC() + { + COSDictionary wc = (COSDictionary)actions.getDictionaryObject( "WC" ); + PDAction retval = null; + if( wc != null ) + { + retval = PDActionFactory.createAction( wc ); + } + return retval; + } + + /** + * This will set a JavaScript action to be performed + * before closing a document. + * The name WC stands for "will close". + * + * @param wc The action to be performed. + */ + public void setWC( PDAction wc ) + { + actions.setItem( "WC", wc ); + } + + /** + * This will get a JavaScript action to be performed + * before saving a document. + * The name WS stands for "will save". + * + * @return The WS entry of document catalog's additional actions dictionary. + */ + public PDAction getWS() + { + COSDictionary ws = (COSDictionary)actions.getDictionaryObject( "WS" ); + PDAction retval = null; + if( ws != null ) + { + retval = PDActionFactory.createAction( ws ); + } + return retval; + } + + /** + * This will set a JavaScript action to be performed + * before saving a document. + * The name WS stands for "will save". + * + * @param ws The action to be performed. + */ + public void setWS( PDAction ws ) + { + actions.setItem( "WS", ws ); + } + + /** + * This will get a JavaScript action to be performed + * after saving a document. + * The name DS stands for "did save". + * + * @return The DS entry of document catalog's additional actions dictionary. + */ + public PDAction getDS() + { + COSDictionary ds = (COSDictionary)actions.getDictionaryObject( "DS" ); + PDAction retval = null; + if( ds != null ) + { + retval = PDActionFactory.createAction( ds ); + } + return retval; + } + + /** + * This will set a JavaScript action to be performed + * after saving a document. + * The name DS stands for "did save". + * + * @param ds The action to be performed. + */ + public void setDS( PDAction ds ) + { + actions.setItem( "DS", ds ); + } + + /** + * This will get a JavaScript action to be performed + * before printing a document. + * The name WP stands for "will print". + * + * @return The WP entry of document catalog's additional actions dictionary. + */ + public PDAction getWP() + { + COSDictionary wp = (COSDictionary)actions.getDictionaryObject( "WP" ); + PDAction retval = null; + if( wp != null ) + { + retval = PDActionFactory.createAction( wp ); + } + return retval; + } + + /** + * This will set a JavaScript action to be performed + * before printing a document. + * The name WP stands for "will print". + * + * @param wp The action to be performed. + */ + public void setWP( PDAction wp ) + { + actions.setItem( "WP", wp ); + } + + /** + * This will get a JavaScript action to be performed + * after printing a document. + * The name DP stands for "did print". + * + * @return The DP entry of document catalog's additional actions dictionary. + */ + public PDAction getDP() + { + COSDictionary dp = (COSDictionary)actions.getDictionaryObject( "DP" ); + PDAction retval = null; + if( dp != null ) + { + retval = PDActionFactory.createAction( dp ); + } + return retval; + } + + /** + * This will set a JavaScript action to be performed + * after printing a document. + * The name DP stands for "did print". + * + * @param dp The action to be performed. + */ + public void setDP( PDAction dp ) + { + actions.setItem( "DP", dp ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/interactive/action/PDFormFieldAdditionalActions.java b/src/main/java/org/pdfbox/pdmodel/interactive/action/PDFormFieldAdditionalActions.java new file mode 100644 index 0000000..2a594f3 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/interactive/action/PDFormFieldAdditionalActions.java @@ -0,0 +1,216 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.interactive.action; + +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSDictionary; + +import org.pdfbox.pdmodel.common.COSObjectable; +import org.pdfbox.pdmodel.interactive.action.type.PDAction; + +/** + * This class represents a form field's dictionary of actions + * that occur due to events. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @author Panagiotis Toumasis (ptoumasis@mail.gr) + * @version $Revision: 1.1 $ + */ +public class PDFormFieldAdditionalActions implements COSObjectable +{ + private COSDictionary actions; + + /** + * Default constructor. + */ + public PDFormFieldAdditionalActions() + { + actions = new COSDictionary(); + } + + /** + * Constructor. + * + * @param a The action dictionary. + */ + public PDFormFieldAdditionalActions( COSDictionary a ) + { + actions = a; + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSBase getCOSObject() + { + return actions; + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSDictionary getCOSDictionary() + { + return actions; + } + + /** + * This will get a JavaScript action to be performed when the user + * types a keystroke into a text field or combo box or modifies the + * selection in a scrollable list box. This allows the keystroke to + * be checked for validity and rejected or modified. + * + * @return The K entry of form field's additional actions dictionary. + */ + public PDAction getK() + { + COSDictionary k = (COSDictionary)actions.getDictionaryObject( "K" ); + PDAction retval = null; + if( k != null ) + { + retval = PDActionFactory.createAction( k ); + } + return retval; + } + + /** + * This will set a JavaScript action to be performed when the user + * types a keystroke into a text field or combo box or modifies the + * selection in a scrollable list box. This allows the keystroke to + * be checked for validity and rejected or modified. + * + * @param k The action to be performed. + */ + public void setK( PDAction k ) + { + actions.setItem( "K", k ); + } + + /** + * This will get a JavaScript action to be performed before + * the field is formatted to display its current value. This + * allows the field's value to be modified before formatting. + * + * @return The F entry of form field's additional actions dictionary. + */ + public PDAction getF() + { + COSDictionary f = (COSDictionary)actions.getDictionaryObject( "F" ); + PDAction retval = null; + if( f != null ) + { + retval = PDActionFactory.createAction( f ); + } + return retval; + } + + /** + * This will set a JavaScript action to be performed before + * the field is formatted to display its current value. This + * allows the field's value to be modified before formatting. + * + * @param f The action to be performed. + */ + public void setF( PDAction f ) + { + actions.setItem( "F", f ); + } + + /** + * This will get a JavaScript action to be performed + * when the field's value is changed. This allows the + * new value to be checked for validity. + * The name V stands for "validate". + * + * @return The V entry of form field's additional actions dictionary. + */ + public PDAction getV() + { + COSDictionary v = (COSDictionary)actions.getDictionaryObject( "V" ); + PDAction retval = null; + if( v != null ) + { + retval = PDActionFactory.createAction( v ); + } + return retval; + } + + /** + * This will set a JavaScript action to be performed + * when the field's value is changed. This allows the + * new value to be checked for validity. + * The name V stands for "validate". + * + * @param v The action to be performed. + */ + public void setV( PDAction v ) + { + actions.setItem( "V", v ); + } + + /** + * This will get a JavaScript action to be performed in order to recalculate + * the value of this field when that of another field changes. The order in which + * the document's fields are recalculated is defined by the CO entry in the + * interactive form dictionary. + * The name C stands for "calculate". + * + * @return The C entry of form field's additional actions dictionary. + */ + public PDAction getC() + { + COSDictionary c = (COSDictionary)actions.getDictionaryObject( "C" ); + PDAction retval = null; + if( c != null ) + { + retval = PDActionFactory.createAction( c ); + } + return retval; + } + + /** + * This will set a JavaScript action to be performed in order to recalculate + * the value of this field when that of another field changes. The order in which + * the document's fields are recalculated is defined by the CO entry in the + * interactive form dictionary. + * The name C stands for "calculate". + * + * @param c The action to be performed. + */ + public void setC( PDAction c ) + { + actions.setItem( "C", c ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/interactive/action/PDPageAdditionalActions.java b/src/main/java/org/pdfbox/pdmodel/interactive/action/PDPageAdditionalActions.java new file mode 100644 index 0000000..f15ffa7 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/interactive/action/PDPageAdditionalActions.java @@ -0,0 +1,150 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.interactive.action; + +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSDictionary; + +import org.pdfbox.pdmodel.common.COSObjectable; +import org.pdfbox.pdmodel.interactive.action.type.PDAction; + +/** + * This class represents a page object's dictionary of actions + * that occur due to events. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @author Panagiotis Toumasis (ptoumasis@mail.gr) + * @version $Revision: 1.1 $ + */ +public class PDPageAdditionalActions implements COSObjectable +{ + private COSDictionary actions; + + /** + * Default constructor. + */ + public PDPageAdditionalActions() + { + actions = new COSDictionary(); + } + + /** + * Constructor. + * + * @param a The action dictionary. + */ + public PDPageAdditionalActions( COSDictionary a ) + { + actions = a; + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSBase getCOSObject() + { + return actions; + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSDictionary getCOSDictionary() + { + return actions; + } + + /** + * This will get an action to be performed when the page + * is opened. This action is independent of any that may be + * defined by the OpenAction entry in the document catalog, + * and is executed after such an action. + * + * @return The O entry of page object's additional actions dictionary. + */ + public PDAction getO() + { + COSDictionary o = (COSDictionary)actions.getDictionaryObject( "O" ); + PDAction retval = null; + if( o != null ) + { + retval = PDActionFactory.createAction( o ); + } + return retval; + } + + /** + * This will set an action to be performed when the page + * is opened. This action is independent of any that may be + * defined by the OpenAction entry in the document catalog, + * and is executed after such an action. + * + * @param o The action to be performed. + */ + public void setO( PDAction o ) + { + actions.setItem( "O", o ); + } + + /** + * This will get an action to be performed when the page + * is closed. This action applies to the page being closed, + * and is executed before any other page opened. + * + * @return The C entry of page object's additional actions dictionary. + */ + public PDAction getC() + { + COSDictionary c = (COSDictionary)actions.getDictionaryObject( "C" ); + PDAction retval = null; + if( c != null ) + { + retval = PDActionFactory.createAction( c ); + } + return retval; + } + + /** + * This will set an action to be performed when the page + * is closed. This action applies to the page being closed, + * and is executed before any other page opened. + * + * @param c The action to be performed. + */ + public void setC( PDAction c ) + { + actions.setItem( "C", c ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/interactive/action/package.html b/src/main/java/org/pdfbox/pdmodel/interactive/action/package.html new file mode 100644 index 0000000..63cbfc0 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/interactive/action/package.html @@ -0,0 +1,9 @@ + + + + + + +This package represents actions that can be performed in a PDF document. + + diff --git a/src/main/java/org/pdfbox/pdmodel/interactive/action/type/PDAction.java b/src/main/java/org/pdfbox/pdmodel/interactive/action/type/PDAction.java new file mode 100644 index 0000000..21d40fc --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/interactive/action/type/PDAction.java @@ -0,0 +1,187 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.interactive.action.type; + +import java.util.ArrayList; +import java.util.List; + +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSDictionary; + +import org.pdfbox.pdmodel.common.COSObjectable; +import org.pdfbox.pdmodel.common.COSArrayList; +import org.pdfbox.pdmodel.interactive.action.PDActionFactory; + +/** + * This represents an action that can be executed in a PDF document. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @author Panagiotis Toumasis (ptoumasis@mail.gr) + * @version $Revision: 1.1 $ + */ +public abstract class PDAction implements COSObjectable +{ + /** + * The type of PDF object. + */ + public static final String TYPE = "Action"; + + /** + * The action dictionary. + */ + protected COSDictionary action; + + /** + * Default constructor. + */ + public PDAction() + { + action = new COSDictionary(); + setType( TYPE ); + } + + /** + * Constructor. + * + * @param a The action dictionary. + */ + public PDAction( COSDictionary a ) + { + action = a; + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSBase getCOSObject() + { + return action; + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSDictionary getCOSDictionary() + { + return action; + } + + /** + * This will get the type of PDF object that the actions dictionary describes. + * If present must be Action for an action dictionary. + * + * @return The Type of PDF object. + */ + public String getType() + { + return action.getNameAsString( "Type" ); + } + + /** + * This will set the type of PDF object that the actions dictionary describes. + * If present must be Action for an action dictionary. + * + * @param type The new Type for the PDF object. + */ + public void setType( String type ) + { + action.setName( "Type", type ); + } + + /** + * This will get the type of action that the actions dictionary describes. + * If present, must be Action for an action dictionary. + * + * @return The S entry of actions dictionary. + */ + public String getSubType() + { + return action.getNameAsString( "S" ); + } + + /** + * This will set the type of action that the actions dictionary describes. + * If present, must be Action for an action dictionary. + * + * @param s The new type of action. + */ + public void setSubType( String s ) + { + action.setName( "S", s ); + } + + /** + * This will get the next action, or sequence of actions, to be performed after this one. + * The value is either a single action dictionary or an array of action dictionaries + * to be performed in order. + * + * @return The Next action or sequence of actions. + */ + public List getNext() + { + List retval = null; + COSBase next = action.getDictionaryObject( "Next" ); + if( next instanceof COSDictionary ) + { + PDAction pdAction = PDActionFactory.createAction( (COSDictionary) next ); + retval = new COSArrayList(pdAction, next, action, "Next" ); + } + else if( next instanceof COSArray ) + { + COSArray array = (COSArray)next; + List actions = new ArrayList(); + for( int i=0; i + + + + + +This package contains all of the available PDF action types. + + diff --git a/src/main/java/org/pdfbox/pdmodel/interactive/annotation/PDAnnotation.java b/src/main/java/org/pdfbox/pdmodel/interactive/annotation/PDAnnotation.java new file mode 100644 index 0000000..4d245c0 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/interactive/annotation/PDAnnotation.java @@ -0,0 +1,503 @@ +/** + * Copyright (c) 2003-2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.interactive.annotation; + +import java.io.IOException; + +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSName; + +import org.pdfbox.pdmodel.common.COSObjectable; +import org.pdfbox.pdmodel.common.PDRectangle; +import org.pdfbox.pdmodel.interactive.action.PDAdditionalActions; +import org.pdfbox.util.BitFlagHelper; +import org.pdfbox.cos.COSBase; + +/** + * This class represents a PDF annotation. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.10 $ + */ +public abstract class PDAnnotation implements COSObjectable +{ + /** + * An annotation flag. + */ + public static final int FLAG_INVISIBLE = 1 << 0; + /** + * An annotation flag. + */ + public static final int FLAG_HIDDEN = 1 << 1; + /** + * An annotation flag. + */ + public static final int FLAG_PRINTED = 1 << 2; + /** + * An annotation flag. + */ + public static final int FLAG_NO_ZOOM = 1 << 3; + /** + * An annotation flag. + */ + public static final int FLAG_NO_ROTATE = 1 << 4; + /** + * An annotation flag. + */ + public static final int FLAG_NO_VIEW = 1 << 5; + /** + * An annotation flag. + */ + public static final int FLAG_READ_ONLY = 1 << 6; + /** + * An annotation flag. + */ + public static final int FLAG_LOCKED = 1 << 7; + /** + * An annotation flag. + */ + public static final int FLAG_TOGGLE_NO_VIEW = 1 << 8; + + + + private COSDictionary dictionary; + + /** + * Create the correct annotation from the base COS object. + * + * @param base The COS object that is the annotation. + * @return The correctly typed annotation object. + * @throws IOException If there is an error while creating the annotation. + */ + public static PDAnnotation createAnnotation( COSBase base ) throws IOException + { + PDAnnotation annot = null; + if( base instanceof COSDictionary ) + { + COSDictionary annotDic = (COSDictionary)base; + String subtype = annotDic.getString( COSName.SUBTYPE ); + if( subtype.equals( PDAnnotationRubberStamp.SUB_TYPE ) ) + { + annot = new PDAnnotationRubberStamp(annotDic); + } + else + { + annot = new PDAnnotationUnknown( annotDic ); + } + } + else + { + throw new IOException( "Error: Unknown annotation type " + base ); + } + + return annot; + } + + /** + * Constructor. + */ + public PDAnnotation() + { + dictionary = new COSDictionary(); + dictionary.setItem( COSName.TYPE, COSName.getPDFName( "Annot" ) ); + } + + /** + * Constructor. + * + * @param dict The annotations dictionary. + */ + public PDAnnotation( COSDictionary dict ) + { + dictionary = dict; + } + + /** + * returns the dictionary. + * @return the dictionary + */ + public COSDictionary getDictionary() + { + return dictionary; + } + + /** + * The annotation rectangle, defining the location of the annotation + * on the page in default user space units. This is usually required and should + * not return null on valid PDF documents. But where this is a parent form field + * with children, such as radio button collections then the rectangle will be null. + * + * @return The Rect value of this annotation. + */ + public PDRectangle getRectangle() + { + COSArray rectArray = (COSArray)dictionary.getDictionaryObject( COSName.getPDFName( "Rect" ) ); + PDRectangle rectangle = null; + if( rectArray != null ) + { + rectangle = new PDRectangle( rectArray ); + } + return rectangle; + } + + /** + * This will set the rectangle for this annotation. + * + * @param rectangle The new rectangle values. + */ + public void setRectangle( PDRectangle rectangle ) + { + dictionary.setItem( COSName.getPDFName( "Rect" ), rectangle.getCOSArray() ); + } + + /** + * This will get the flags for this field. + * + * @return flags The set of flags. + */ + public int getAnnotationFlags() + { + return getDictionary().getInt( "F", 0 ); + } + + /** + * This will set the flags for this field. + * + * @param flags The new flags. + */ + public void setAnnotationFlags( int flags ) + { + getDictionary().setInt( "F", flags ); + } + + /** + * Interface method for COSObjectable. + * + * @return This object as a standard COS object. + */ + public COSBase getCOSObject() + { + return getDictionary(); + } + + /** + * This will get the name of the current appearance stream if any. + * + * @return The name of the appearance stream. + */ + public String getAppearanceStream() + { + String retval = null; + COSName name = (COSName)getDictionary().getDictionaryObject( COSName.getPDFName( "AS" ) ); + if( name != null ) + { + retval = name.getName(); + } + return retval; + } + + /** + * This will set the annotations appearance stream name. + * + * @param as The name of the appearance stream. + */ + public void setAppearanceStream( String as ) + { + if( as == null ) + { + getDictionary().removeItem( COSName.getPDFName( "AS" ) ); + } + else + { + getDictionary().setItem( COSName.getPDFName( "AS" ), COSName.getPDFName( as ) ); + } + } + + /** + * This will get the appearance dictionary associated with this annotation. + * This may return null. + * + * @return This annotations appearance. + */ + public PDAppearanceDictionary getAppearance() + { + PDAppearanceDictionary ap = null; + COSDictionary apDic = (COSDictionary)dictionary.getDictionaryObject( COSName.getPDFName( "AP" ) ); + if( apDic != null ) + { + ap = new PDAppearanceDictionary( apDic ); + } + return ap; + } + + /** + * This will set the appearance associated with this annotation. + * + * @param appearance The appearance dictionary for this annotation. + */ + public void setAppearance( PDAppearanceDictionary appearance ) + { + COSDictionary ap = null; + if( appearance != null ) + { + ap = appearance.getDictionary(); + } + dictionary.setItem( COSName.getPDFName( "AP" ), ap ); + } + + /** + * Get the invisible flag. + * + * @return The invisible flag. + */ + public boolean isInvisible() + { + return BitFlagHelper.getFlag( getDictionary(), "F", FLAG_INVISIBLE ); + } + + /** + * Set the invisible flag. + * + * @param invisible The new invisible flag. + */ + public void setInvisible( boolean invisible ) + { + BitFlagHelper.setFlag( getDictionary(), "F", FLAG_INVISIBLE, invisible ); + } + + /** + * Get the hidden flag. + * + * @return The hidden flag. + */ + public boolean isHidden() + { + return BitFlagHelper.getFlag( getDictionary(), "F", FLAG_HIDDEN ); + } + + /** + * Set the hidden flag. + * + * @param hidden The new hidden flag. + */ + public void setHidden( boolean hidden ) + { + BitFlagHelper.setFlag( getDictionary(), "F", FLAG_HIDDEN, hidden ); + } + + /** + * Get the printed flag. + * + * @return The printed flag. + */ + public boolean isPrinted() + { + return BitFlagHelper.getFlag( getDictionary(), "F", FLAG_PRINTED ); + } + + /** + * Set the printed flag. + * + * @param printed The new printed flag. + */ + public void setPrinted( boolean printed ) + { + BitFlagHelper.setFlag( getDictionary(), "F", FLAG_PRINTED, printed ); + } + + /** + * Get the noZoom flag. + * + * @return The noZoom flag. + */ + public boolean isNoZoom() + { + return BitFlagHelper.getFlag( getDictionary(), "F", FLAG_NO_ZOOM ); + } + + /** + * Set the noZoom flag. + * + * @param noZoom The new noZoom flag. + */ + public void setNoZoom( boolean noZoom ) + { + BitFlagHelper.setFlag( getDictionary(), "F", FLAG_NO_ZOOM, noZoom ); + } + + /** + * Get the noRotate flag. + * + * @return The noRotate flag. + */ + public boolean isNoRotate() + { + return BitFlagHelper.getFlag( getDictionary(), "F", FLAG_NO_ROTATE ); + } + + /** + * Set the noRotate flag. + * + * @param noRotate The new noRotate flag. + */ + public void setNoRotate( boolean noRotate ) + { + BitFlagHelper.setFlag( getDictionary(), "F", FLAG_NO_ROTATE, noRotate ); + } + + /** + * Get the noView flag. + * + * @return The noView flag. + */ + public boolean isNoView() + { + return BitFlagHelper.getFlag( getDictionary(), "F", FLAG_NO_VIEW ); + } + + /** + * Set the noView flag. + * + * @param noView The new noView flag. + */ + public void setNoView( boolean noView ) + { + BitFlagHelper.setFlag( getDictionary(), "F", FLAG_NO_VIEW, noView ); + } + + /** + * Get the readOnly flag. + * + * @return The readOnly flag. + */ + public boolean isReadOnly() + { + return BitFlagHelper.getFlag( getDictionary(), "F", FLAG_READ_ONLY ); + } + + /** + * Set the readOnly flag. + * + * @param readOnly The new readOnly flag. + */ + public void setReadOnly( boolean readOnly ) + { + BitFlagHelper.setFlag( getDictionary(), "F", FLAG_READ_ONLY, readOnly ); + } + + /** + * Get the locked flag. + * + * @return The locked flag. + */ + public boolean isLocked() + { + return BitFlagHelper.getFlag( getDictionary(), "F", FLAG_LOCKED ); + } + + /** + * Set the locked flag. + * + * @param locked The new locked flag. + */ + public void setLocked( boolean locked ) + { + BitFlagHelper.setFlag( getDictionary(), "F", FLAG_LOCKED, locked ); + } + + /** + * Get the toggleNoView flag. + * + * @return The toggleNoView flag. + */ + public boolean isToggleNoView() + { + return BitFlagHelper.getFlag( getDictionary(), "F", FLAG_TOGGLE_NO_VIEW ); + } + + /** + * Set the toggleNoView flag. + * + * @param toggleNoView The new toggleNoView flag. + */ + public void setToggleNoView( boolean toggleNoView ) + { + BitFlagHelper.setFlag( getDictionary(), "F", FLAG_TOGGLE_NO_VIEW, toggleNoView ); + } + + /** + * Get the additional actions for this field. This will return null + * if there are no additional actions for this field. + * + * @return The actions of the field. + */ + public PDAdditionalActions getActions() + { + COSDictionary aa = (COSDictionary)dictionary.getDictionaryObject( "AA" ); + PDAdditionalActions retval = null; + if( aa != null ) + { + retval = new PDAdditionalActions( aa ); + } + return retval; + } + + /** + * Set the actions of the field. + * + * @param actions The field actions. + */ + public void setActions( PDAdditionalActions actions ) + { + dictionary.setItem( "AA", actions ); + } + + /** + * Get the "contents" of the field. + * + * @return the value of the contents + */ + public String getContents() + { + return dictionary.getString(COSName.CONTENTS); + } + + /** + * Set the "contents" of the field. + * + * @param value the value of the contents. + */ + public void setContents( String value) + { + dictionary.setString(COSName.CONTENTS, value); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/interactive/annotation/PDAnnotationRubberStamp.java b/src/main/java/org/pdfbox/pdmodel/interactive/annotation/PDAnnotationRubberStamp.java new file mode 100644 index 0000000..089b19f --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/interactive/annotation/PDAnnotationRubberStamp.java @@ -0,0 +1,153 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.interactive.annotation; + +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSName; + +/** + * This is the class that represents a widget. + * + * @author Paul King + * @version $Revision: 1.1 $ + */ +public class PDAnnotationRubberStamp extends PDAnnotation +{ + + /* + * The various values of the rubber stamp as defined in + * the PDF 1.6 reference Table 8.28 + */ + + /** + * Constant for the name of a rubber stamp. + */ + public static final String NAME_APPROVED = "Approved"; + /** + * Constant for the name of a rubber stamp. + */ + public static final String NAME_EXPERIMENTAL = "Experimental"; + /** + * Constant for the name of a rubber stamp. + */ + public static final String NAME_NOT_APPROVED = "NotApproved"; + /** + * Constant for the name of a rubber stamp. + */ + public static final String NAME_AS_IS = "AsIs"; + /** + * Constant for the name of a rubber stamp. + */ + public static final String NAME_EXPIRED = "Expired"; + /** + * Constant for the name of a rubber stamp. + */ + public static final String NAME_NOT_FOR_PUBLIC_RELEASE = "NotForPublicRelease"; + /** + * Constant for the name of a rubber stamp. + */ + public static final String NAME_FOR_PUBLIC_RELEASE = "ForPublicRelease"; + /** + * Constant for the name of a rubber stamp. + */ + public static final String NAME_DRAFT = "Draft"; + /** + * Constant for the name of a rubber stamp. + */ + public static final String NAME_FOR_COMMENT = "ForComment"; + /** + * Constant for the name of a rubber stamp. + */ + public static final String NAME_TOP_SECRET = "TopSecret"; + /** + * Constant for the name of a rubber stamp. + */ + public static final String NAME_DEPARTMENTAL = "Departmental"; + /** + * Constant for the name of a rubber stamp. + */ + public static final String NAME_CONFIDENTIAL = "Confidential"; + /** + * Constant for the name of a rubber stamp. + */ + public static final String NAME_FINAL = "Final"; + /** + * Constant for the name of a rubber stamp. + */ + public static final String NAME_SOLD = "Sold"; + + /** + * The type of annotation. + */ + public static final String SUB_TYPE = "Stamp"; + + /** + * Constructor. + */ + public PDAnnotationRubberStamp() + { + super(); + getDictionary().setItem( COSName.SUBTYPE, COSName.getPDFName( SUB_TYPE ) ); + } + + /** + * Creates a Rubber Stamp annotation from a COSDictionary, expected to be + * a correct object definition. + * + * @param field the PDF objet to represent as a field. + */ + public PDAnnotationRubberStamp(COSDictionary field) + { + super( field ); + } + + /** + * This will set the name (and hence appearance, AP taking precedence) + * For this annotation. See the NAME_XXX constants for valid values. + * + * @param name The name of the rubber stamp. + */ + public void setName( String name ) + { + getDictionary().setName(COSName.NAME, name); + } + + /** + * This will retrieve the name (and hence appearance, AP taking precedence) + * For this annotation. The default is DRAFT. + * + * @return The name of this rubber stamp, see the NAME_XXX constants. + */ + public String getName() + { + return getDictionary().getNameAsString(COSName.NAME, NAME_DRAFT); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/interactive/annotation/PDAnnotationUnknown.java b/src/main/java/org/pdfbox/pdmodel/interactive/annotation/PDAnnotationUnknown.java new file mode 100644 index 0000000..408f5fb --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/interactive/annotation/PDAnnotationUnknown.java @@ -0,0 +1,54 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.interactive.annotation; + +import org.pdfbox.cos.COSDictionary; + +/** + * This is the class that represents an arbitary Unknown Annotation type. + * + * @author Paul King + * @version $Revision: 1.1 $ + */ +public class PDAnnotationUnknown extends PDAnnotation +{ + + /** + * Creates an arbitary annotation from a COSDictionary, expected to be + * a correct object definition for some sort of annotation. + * + * @param dic The dictionary which represents this Annotation. + */ + public PDAnnotationUnknown(COSDictionary dic) + { + super( dic ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/interactive/annotation/PDAnnotationWidget.java b/src/main/java/org/pdfbox/pdmodel/interactive/annotation/PDAnnotationWidget.java new file mode 100644 index 0000000..5faf983 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/interactive/annotation/PDAnnotationWidget.java @@ -0,0 +1,65 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.interactive.annotation; + +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSName; + +/** + * This is the class that represents a widget. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.1 $ + */ +public class PDAnnotationWidget extends PDAnnotation +{ + + /** + * Constructor. + */ + public PDAnnotationWidget() + { + super(); + getDictionary().setItem( COSName.SUBTYPE, COSName.getPDFName( "Widget" ) ); + } + + + /** + * Creates a PDWidget from a COSDictionary, expected to be + * a correct object definition for a field in PDF. + * + * @param field the PDF objet to represent as a field. + */ + public PDAnnotationWidget(COSDictionary field) + { + super( field ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/interactive/annotation/PDAppearanceDictionary.java b/src/main/java/org/pdfbox/pdmodel/interactive/annotation/PDAppearanceDictionary.java new file mode 100644 index 0000000..da3a182 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/interactive/annotation/PDAppearanceDictionary.java @@ -0,0 +1,245 @@ +/** + * Copyright (c) 2003-2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.interactive.annotation; + +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSName; +import org.pdfbox.cos.COSStream; + +import org.pdfbox.pdmodel.common.COSObjectable; +import org.pdfbox.pdmodel.common.COSDictionaryMap; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +/** + * This class represents a PDF /AP entry the appearance dictionary. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.3 $ + */ +public class PDAppearanceDictionary implements COSObjectable +{ + private COSDictionary dictionary; + + /** + * Constructor. + */ + public PDAppearanceDictionary() + { + dictionary = new COSDictionary(); + //the N entry is required. + dictionary.setItem( COSName.getPDFName( "N" ), new COSDictionary() ); + } + + /** + * Constructor. + * + * @param dict The annotations dictionary. + */ + public PDAppearanceDictionary( COSDictionary dict ) + { + dictionary = dict; + } + + /** + * returns the dictionary. + * @return the dictionary + */ + public COSDictionary getDictionary() + { + return dictionary; + } + + /** + * returns the dictionary. + * @return the dictionary + */ + public COSBase getCOSObject() + { + return dictionary; + } + + /** + * This will return a list of appearances. In the case where there is + * only one appearance the map will contain one entry whose key is the string + * "default". + * + * @return A list of key(java.lang.String) value(PDAppearanceStream) pairs + */ + public Map getNormalAppearance() + { + COSBase ap = dictionary.getDictionaryObject( COSName.getPDFName( "N" ) ); + if( ap instanceof COSStream ) + { + COSStream aux = (COSStream) ap; + ap = new COSDictionary(); + ((COSDictionary)ap).setItem(COSName.getPDFName( "default" ), aux ); + } + COSDictionary map = (COSDictionary)ap; + Map actuals = new HashMap(); + Map retval = new COSDictionaryMap( actuals, map ); + Iterator asNames = map.keyList().iterator(); + while( asNames.hasNext() ) + { + COSName asName = (COSName)asNames.next(); + COSStream as = (COSStream)map.getDictionaryObject( asName ); + actuals.put( asName.getName(), new PDAppearanceStream( as ) ); + } + + return retval; + } + + /** + * This will set a list of appearances. If you would like to set the single + * appearance then you should use the key "default", and when the PDF is written + * back to the filesystem then there will only be one stream. + * + * @param appearanceMap The updated map with the appearance. + */ + public void setNormalAppearance( Map appearanceMap ) + { + dictionary.setItem( COSName.getPDFName( "N" ), COSDictionaryMap.convert( appearanceMap ) ); + } + + /** + * This will set the normal appearance when there is only one appearance + * to be shown. + * + * @param ap The appearance stream to show. + */ + public void setNormalAppearance( PDAppearanceStream ap ) + { + dictionary.setItem( COSName.getPDFName( "N" ), ap.getStream() ); + } + + /** + * This will return a list of appearances. In the case where there is + * only one appearance the map will contain one entry whose key is the string + * "default". If there is no rollover appearance then the normal appearance + * will be returned. Which means that this method will never return null. + * + * @return A list of key(java.lang.String) value(PDAppearanceStream) pairs + */ + public Map getRolloverAppearance() + { + Map retval = null; + COSBase ap = dictionary.getDictionaryObject( COSName.getPDFName( "R" ) ); + if( ap == null ) + { + retval = getNormalAppearance(); + } + else + { + if( ap instanceof COSStream ) + { + ap = new COSDictionary(); + ((COSDictionary)ap).setItem(COSName.getPDFName( "default" ), ap ); + } + COSDictionary map = (COSDictionary)ap; + Map actuals = new HashMap(); + retval = new COSDictionaryMap( actuals, map ); + Iterator asNames = map.keyList().iterator(); + while( asNames.hasNext() ) + { + COSName asName = (COSName)asNames.next(); + COSStream as = (COSStream)map.getDictionaryObject( asName ); + actuals.put( asName.getName(), new PDAppearanceStream( as ) ); + } + } + + return retval; + } + + /** + * This will set a list of appearances. If you would like to set the single + * appearance then you should use the key "default", and when the PDF is written + * back to the filesystem then there will only be one stream. + * + * @param appearanceMap The updated map with the appearance. + */ + public void setRolloverAppearance( Map appearanceMap ) + { + dictionary.setItem( COSName.getPDFName( "R" ), COSDictionaryMap.convert( appearanceMap ) ); + } + + /** + * This will return a list of appearances. In the case where there is + * only one appearance the map will contain one entry whose key is the string + * "default". If there is no rollover appearance then the normal appearance + * will be returned. Which means that this method will never return null. + * + * @return A list of key(java.lang.String) value(PDAppearanceStream) pairs + */ + public Map getDownAppearance() + { + Map retval = null; + COSBase ap = dictionary.getDictionaryObject( COSName.getPDFName( "D" ) ); + if( ap == null ) + { + retval = getNormalAppearance(); + } + else + { + if( ap instanceof COSStream ) + { + ap = new COSDictionary(); + ((COSDictionary)ap).setItem(COSName.getPDFName( "default" ), ap ); + } + COSDictionary map = (COSDictionary)ap; + Map actuals = new HashMap(); + retval = new COSDictionaryMap( actuals, map ); + Iterator asNames = map.keyList().iterator(); + while( asNames.hasNext() ) + { + COSName asName = (COSName)asNames.next(); + COSStream as = (COSStream)map.getDictionaryObject( asName ); + actuals.put( asName.getName(), new PDAppearanceStream( as ) ); + } + } + + return retval; + } + + /** + * This will set a list of appearances. If you would like to set the single + * appearance then you should use the key "default", and when the PDF is written + * back to the filesystem then there will only be one stream. + * + * @param appearanceMap The updated map with the appearance. + */ + public void setDownAppearance( Map appearanceMap ) + { + dictionary.setItem( COSName.getPDFName( "D" ), COSDictionaryMap.convert( appearanceMap ) ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/interactive/annotation/PDAppearanceStream.java b/src/main/java/org/pdfbox/pdmodel/interactive/annotation/PDAppearanceStream.java new file mode 100644 index 0000000..ca3f4a4 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/interactive/annotation/PDAppearanceStream.java @@ -0,0 +1,146 @@ +/** + * Copyright (c) 2003-2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.interactive.annotation; + +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSName; +import org.pdfbox.cos.COSStream; + +import org.pdfbox.pdmodel.common.PDRectangle; +import org.pdfbox.pdmodel.common.COSObjectable; + +import org.pdfbox.pdmodel.PDResources; + + +/** + * This class represents an appearance for an annotation. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.3 $ + */ +public class PDAppearanceStream implements COSObjectable +{ + private COSStream stream = null; + + + /** + * Constructor. + * + * @param s The cos stream for this appearance. + */ + public PDAppearanceStream( COSStream s ) + { + stream = s; + } + + /** + * This will return the underlying stream. + * + * @return The wrapped stream. + */ + public COSStream getStream() + { + return stream; + } + + /** + * @see COSObjectable#getCOSObject() + */ + public COSBase getCOSObject() + { + return stream; + } + + /** + * Get the bounding box for this appearance. This may return null in which + * case the Rectangle from the annotation should be used. + * + * @return The bounding box for this appearance. + */ + public PDRectangle getBoundingBox() + { + PDRectangle box = null; + COSArray bbox = (COSArray)stream.getDictionaryObject( COSName.getPDFName( "BBox" ) ); + if( bbox != null ) + { + box = new PDRectangle( bbox ); + } + return box; + } + + /** + * This will set the bounding box for this appearance stream. + * + * @param rectangle The new bounding box. + */ + public void setBoundingBox( PDRectangle rectangle ) + { + COSArray array = null; + if( rectangle != null ) + { + array = rectangle.getCOSArray(); + } + stream.setItem( COSName.getPDFName( "BBox" ), array ); + } + + /** + * This will get the resources for this appearance stream. + * + * @return The appearance stream resources. + */ + public PDResources getResources() + { + PDResources retval = null; + COSDictionary dict = (COSDictionary)stream.getDictionaryObject( COSName.RESOURCES ); + if( dict != null ) + { + retval = new PDResources( dict ); + } + return retval; + } + + /** + * This will set the new resources. + * + * @param resources The new resources. + */ + public void setResources( PDResources resources ) + { + COSDictionary dict = null; + if( resources != null ) + { + dict = resources.getCOSDictionary(); + } + stream.setItem( COSName.RESOURCES, dict ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/interactive/annotation/package.html b/src/main/java/org/pdfbox/pdmodel/interactive/annotation/package.html new file mode 100644 index 0000000..4d9fdeb --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/interactive/annotation/package.html @@ -0,0 +1,9 @@ + + + + + + +The annotation package contains classes that work with PDF annotation elements. + + diff --git a/src/main/java/org/pdfbox/pdmodel/interactive/digitalsignature/PDSignature.java b/src/main/java/org/pdfbox/pdmodel/interactive/digitalsignature/PDSignature.java new file mode 100644 index 0000000..7ef1c1e --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/interactive/digitalsignature/PDSignature.java @@ -0,0 +1,85 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.interactive.digitalsignature; + +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSDictionary; + +import org.pdfbox.pdmodel.common.COSObjectable; + +/** + * This represents a digital signature that can be attached to a document. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.1 $ + */ +public class PDSignature implements COSObjectable +{ + private COSDictionary sig; + + /** + * Default constructor. + */ + public PDSignature() + { + sig = new COSDictionary(); + } + + /** + * Constructor. + * + * @param s The signature dictionary. + */ + public PDSignature( COSDictionary s ) + { + sig = s; + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSBase getCOSObject() + { + return sig; + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSDictionary getCOSDictionary() + { + return sig; + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/interactive/digitalsignature/package.html b/src/main/java/org/pdfbox/pdmodel/interactive/digitalsignature/package.html new file mode 100644 index 0000000..d9944e6 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/interactive/digitalsignature/package.html @@ -0,0 +1,9 @@ + + + + + + +The digitial signature library will manage signatures that are stored in the PDF document. + + diff --git a/src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/destination/PDDestination.java b/src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/destination/PDDestination.java new file mode 100644 index 0000000..98a0345 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/destination/PDDestination.java @@ -0,0 +1,125 @@ +/** + * Copyright (c) 2004-2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.interactive.documentnavigation.destination; + +import java.io.IOException; + +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSName; +import org.pdfbox.cos.COSString; + +import org.pdfbox.pdmodel.common.COSObjectable; + +/** + * This represents a destination in a PDF document. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.4 $ + */ +public abstract class PDDestination implements COSObjectable +{ + + /** + * This will create a new destination depending on the type of COSBase + * that is passed in. + * + * @param base The base level object. + * + * @return A new destination. + * + * @throws IOException If the base cannot be converted to a Destination. + */ + public static PDDestination create( COSBase base ) throws IOException + { + PDDestination retval = null; + if( base == null ) + { + //this is ok, just return null. + } + else if( base instanceof COSArray && ((COSArray)base).size() > 0 ) + { + COSArray array = (COSArray)base; + COSName type = (COSName)array.getObject( 1 ); + String typeString = type.getName(); + if( typeString.equals( PDPageFitDestination.TYPE ) || + typeString.equals( PDPageFitDestination.TYPE_BOUNDED )) + { + retval = new PDPageFitDestination( array ); + } + else if( typeString.equals( PDPageFitHeightDestination.TYPE ) || + typeString.equals( PDPageFitHeightDestination.TYPE_BOUNDED )) + { + retval = new PDPageFitHeightDestination( array ); + } + else if( typeString.equals( PDPageFitRectangleDestination.TYPE ) ) + { + retval = new PDPageFitRectangleDestination( array ); + } + else if( typeString.equals( PDPageFitWidthDestination.TYPE ) || + typeString.equals( PDPageFitWidthDestination.TYPE_BOUNDED )) + { + retval = new PDPageFitWidthDestination( array ); + } + else if( typeString.equals( PDPageXYZDestination.TYPE ) ) + { + retval = new PDPageXYZDestination( array ); + } + else + { + throw new IOException( "Unknown destination type:" + type ); + } + } + else if( base instanceof COSString ) + { + retval = new PDNamedDestination( (COSString)base ); + } + else if( base instanceof COSName ) + { + retval = new PDNamedDestination( (COSName)base ); + } + else + { + throw new IOException( "Error: can't convert to Destination " + base ); + } + return retval; + } + + /** + * Return a string representation of this class. + * + * @return A human readable string. + */ + public String toString() + { + return super.toString(); + } +} diff --git a/src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/destination/PDNamedDestination.java b/src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/destination/PDNamedDestination.java new file mode 100644 index 0000000..11da8e7 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/destination/PDNamedDestination.java @@ -0,0 +1,142 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.interactive.documentnavigation.destination; + +import java.io.IOException; + +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSName; +import org.pdfbox.cos.COSString; + +/** + * This represents a destination to a page by referencing it with a name. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.2 $ + */ +public class PDNamedDestination extends PDDestination +{ + private COSBase namedDestination; + + /** + * Constructor. + * + * @param dest The named destination. + */ + public PDNamedDestination( COSString dest ) + { + namedDestination = dest; + } + + /** + * Constructor. + * + * @param dest The named destination. + */ + public PDNamedDestination( COSName dest ) + { + namedDestination = dest; + } + + /** + * Default constructor. + */ + public PDNamedDestination() + { + //default, so do nothing + } + + /** + * Default constructor. + * + * @param dest The named destination. + */ + public PDNamedDestination( String dest ) + { + namedDestination = new COSString( dest ); + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSBase getCOSObject() + { + return namedDestination; + } + + /** + * This will get the name of the destination. + * + * @return The name of the destination. + */ + public String getNamedDestination() + { + String retval = null; + if( namedDestination instanceof COSString ) + { + retval = ((COSString)namedDestination).getString(); + } + else if( namedDestination instanceof COSName ) + { + retval = ((COSName)namedDestination).getName(); + } + + return retval; + } + + /** + * Set the named destination. + * + * @param dest The new named destination. + * + * @throws IOException If there is an error setting the named destination. + */ + public void setNamedDestination( String dest ) throws IOException + { + if( namedDestination instanceof COSString ) + { + COSString string = ((COSString)namedDestination); + string.reset(); + string.append( dest.getBytes() ); + } + else if( dest == null ) + { + namedDestination = null; + } + else + { + namedDestination = new COSString( dest ); + } + } + +} diff --git a/src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/destination/PDPageDestination.java b/src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/destination/PDPageDestination.java new file mode 100644 index 0000000..74dbf9a --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/destination/PDPageDestination.java @@ -0,0 +1,155 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.interactive.documentnavigation.destination; + +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSNumber; + +import org.pdfbox.pdmodel.PDPage; + +/** + * This represents a destination to a page, see subclasses for specific parameters. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.1 $ + */ +public abstract class PDPageDestination extends PDDestination +{ + /** + * Storage for the page destination. + */ + protected COSArray array; + + /** + * Constructor to create empty page destination. + * + */ + protected PDPageDestination() + { + array = new COSArray(); + } + + /** + * Constructor to create empty page destination. + * + * @param arr A page destination array. + */ + protected PDPageDestination( COSArray arr ) + { + array = arr; + } + + /** + * This will get the page for this destination. A page destination + * can either reference a page or a page number(when doing a remote destination to + * another PDF). If this object is referencing by page number then this method will + * return null and getPageNumber should be used. + * + * @return The page for this destination. + */ + public PDPage getPage() + { + PDPage retval = null; + if( array.size() > 0 ) + { + COSBase page = array.getObject( 0 ); + if( page instanceof COSDictionary ) + { + retval = new PDPage( (COSDictionary)page ); + } + } + return retval; + } + + /** + * Set the page for this destination. + * + * @param page The page for the destination. + */ + public void setPage( PDPage page ) + { + array.set( 0, page ); + } + + /** + * This will get the page number for this destination. A page destination + * can either reference a page or a page number(when doing a remote destination to + * another PDF). If this object is referencing by page number then this method will + * return that number, otherwise -1 will be returned. + * + * @return The page number for this destination. + */ + public int getPageNumber() + { + int retval = -1; + if( array.size() > 0 ) + { + COSBase page = array.getObject( 0 ); + if( page instanceof COSNumber ) + { + retval = ((COSNumber)page).intValue(); + } + } + return retval; + } + + /** + * Set the page number for this destination. + * + * @param pageNumber The page for the destination. + */ + public void setPageNumber( int pageNumber ) + { + array.set( 0, pageNumber ); + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSBase getCOSObject() + { + return array; + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSArray getCOSArray() + { + return array; + } +} diff --git a/src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/destination/PDPageFitDestination.java b/src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/destination/PDPageFitDestination.java new file mode 100644 index 0000000..8f46bbe --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/destination/PDPageFitDestination.java @@ -0,0 +1,102 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.interactive.documentnavigation.destination; + +import org.pdfbox.cos.COSArray; + +/** + * This represents a destination to a page and the page contents will be magnified to just + * fit on the screen. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.1 $ + */ +public class PDPageFitDestination extends PDPageDestination +{ + /** + * The type of this destination. + */ + protected static final String TYPE = "Fit"; + /** + * The type of this destination. + */ + protected static final String TYPE_BOUNDED = "FitB"; + + /** + * Default constructor. + * + */ + public PDPageFitDestination() + { + super(); + array.growToSize(2); + array.setName( 1, TYPE ); + + } + + /** + * Constructor from an existing destination array. + * + * @param arr The destination array. + */ + public PDPageFitDestination( COSArray arr ) + { + super( arr ); + } + + /** + * A flag indicating if this page destination should just fit bounding box of the PDF. + * + * @return true If the destination should fit just the bounding box. + */ + public boolean fitBoundingBox() + { + return TYPE_BOUNDED.equals( array.getName( 1 ) ); + } + + /** + * Set if this page destination should just fit the bounding box. The default is false. + * + * @param fitBoundingBox A flag indicating if this should fit the bounding box. + */ + public void setFitBoundingBox( boolean fitBoundingBox ) + { + array.growToSize( 2 ); + if( fitBoundingBox ) + { + array.setName( 1, TYPE_BOUNDED ); + } + else + { + array.setName( 1, TYPE ); + } + } +} diff --git a/src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/destination/PDPageFitHeightDestination.java b/src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/destination/PDPageFitHeightDestination.java new file mode 100644 index 0000000..64df612 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/destination/PDPageFitHeightDestination.java @@ -0,0 +1,132 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.interactive.documentnavigation.destination; + +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSBase; + +/** + * This represents a destination to a page at a x location and the height is magnified + * to just fit on the screen. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.1 $ + */ +public class PDPageFitHeightDestination extends PDPageDestination +{ + /** + * The type of this destination. + */ + protected static final String TYPE = "FitV"; + /** + * The type of this destination. + */ + protected static final String TYPE_BOUNDED = "FitBV"; + + /** + * Default constructor. + * + */ + public PDPageFitHeightDestination() + { + super(); + array.growToSize(3); + array.setName( 1, TYPE ); + + } + + /** + * Constructor from an existing destination array. + * + * @param arr The destination array. + */ + public PDPageFitHeightDestination( COSArray arr ) + { + super( arr ); + } + + /** + * Get the left x coordinate. A return value of -1 implies that the current x-coordinate + * will be used. + * + * @return The left x coordinate. + */ + public int getLeft() + { + return array.getInt( 2 ); + } + + /** + * Set the left x-coordinate, a value of -1 implies that the current x-coordinate + * will be used. + * @param x The left x coordinate. + */ + public void setLeft( int x ) + { + array.growToSize( 3 ); + if( x == -1 ) + { + array.set( 2, (COSBase)null ); + } + else + { + array.setInt( 2, x ); + } + } + + /** + * A flag indicating if this page destination should just fit bounding box of the PDF. + * + * @return true If the destination should fit just the bounding box. + */ + public boolean fitBoundingBox() + { + return TYPE_BOUNDED.equals( array.getName( 1 ) ); + } + + /** + * Set if this page destination should just fit the bounding box. The default is false. + * + * @param fitBoundingBox A flag indicating if this should fit the bounding box. + */ + public void setFitBoundingBox( boolean fitBoundingBox ) + { + array.growToSize( 2 ); + if( fitBoundingBox ) + { + array.setName( 1, TYPE_BOUNDED ); + } + else + { + array.setName( 1, TYPE ); + } + } +} diff --git a/src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/destination/PDPageFitRectangleDestination.java b/src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/destination/PDPageFitRectangleDestination.java new file mode 100644 index 0000000..00fc5f1 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/destination/PDPageFitRectangleDestination.java @@ -0,0 +1,188 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.interactive.documentnavigation.destination; + +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSBase; + +/** + * This represents a destination to a page at a y location and the width is magnified + * to just fit on the screen. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.1 $ + */ +public class PDPageFitRectangleDestination extends PDPageDestination +{ + /** + * The type of this destination. + */ + protected static final String TYPE = "FitR"; + + /** + * Default constructor. + * + */ + public PDPageFitRectangleDestination() + { + super(); + array.growToSize(6); + array.setName( 1, TYPE ); + + } + + /** + * Constructor from an existing destination array. + * + * @param arr The destination array. + */ + public PDPageFitRectangleDestination( COSArray arr ) + { + super( arr ); + } + + /** + * Get the left x coordinate. A return value of -1 implies that the current x-coordinate + * will be used. + * + * @return The left x coordinate. + */ + public int getLeft() + { + return array.getInt( 2 ); + } + + /** + * Set the left x-coordinate, a value of -1 implies that the current x-coordinate + * will be used. + * @param x The left x coordinate. + */ + public void setLeft( int x ) + { + array.growToSize( 3 ); + if( x == -1 ) + { + array.set( 2, (COSBase)null ); + } + else + { + array.setInt( 2, x ); + } + } + + /** + * Get the bottom y coordinate. A return value of -1 implies that the current y-coordinate + * will be used. + * + * @return The bottom y coordinate. + */ + public int getBottom() + { + return array.getInt( 3 ); + } + + /** + * Set the bottom y-coordinate, a value of -1 implies that the current y-coordinate + * will be used. + * @param y The bottom y coordinate. + */ + public void setBottom( int y ) + { + array.growToSize( 6 ); + if( y == -1 ) + { + array.set( 3, (COSBase)null ); + } + else + { + array.setInt( 3, y ); + } + } + + /** + * Get the right x coordinate. A return value of -1 implies that the current x-coordinate + * will be used. + * + * @return The right x coordinate. + */ + public int getRight() + { + return array.getInt( 4 ); + } + + /** + * Set the right x-coordinate, a value of -1 implies that the current x-coordinate + * will be used. + * @param x The right x coordinate. + */ + public void setRight( int x ) + { + array.growToSize( 6 ); + if( x == -1 ) + { + array.set( 4, (COSBase)null ); + } + else + { + array.setInt( 4, x ); + } + } + + + /** + * Get the top y coordinate. A return value of -1 implies that the current y-coordinate + * will be used. + * + * @return The top y coordinate. + */ + public int getTop() + { + return array.getInt( 5 ); + } + + /** + * Set the top y-coordinate, a value of -1 implies that the current y-coordinate + * will be used. + * @param y The top ycoordinate. + */ + public void setTop( int y ) + { + array.growToSize( 6 ); + if( y == -1 ) + { + array.set( 5, (COSBase)null ); + } + else + { + array.setInt( 5, y ); + } + } +} diff --git a/src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/destination/PDPageFitWidthDestination.java b/src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/destination/PDPageFitWidthDestination.java new file mode 100644 index 0000000..ef7385f --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/destination/PDPageFitWidthDestination.java @@ -0,0 +1,134 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.interactive.documentnavigation.destination; + +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSBase; + +/** + * This represents a destination to a page at a y location and the width is magnified + * to just fit on the screen. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.1 $ + */ +public class PDPageFitWidthDestination extends PDPageDestination +{ + + /** + * The type of this destination. + */ + protected static final String TYPE = "FitH"; + /** + * The type of this destination. + */ + protected static final String TYPE_BOUNDED = "FitBH"; + + /** + * Default constructor. + * + */ + public PDPageFitWidthDestination() + { + super(); + array.growToSize(3); + array.setName( 1, TYPE ); + + } + + /** + * Constructor from an existing destination array. + * + * @param arr The destination array. + */ + public PDPageFitWidthDestination( COSArray arr ) + { + super( arr ); + } + + + /** + * Get the top y coordinate. A return value of -1 implies that the current y-coordinate + * will be used. + * + * @return The top y coordinate. + */ + public int getTop() + { + return array.getInt( 2 ); + } + + /** + * Set the top y-coordinate, a value of -1 implies that the current y-coordinate + * will be used. + * @param y The top ycoordinate. + */ + public void setTop( int y ) + { + array.growToSize( 3 ); + if( y == -1 ) + { + array.set( 2, (COSBase)null ); + } + else + { + array.setInt( 2, y ); + } + } + + /** + * A flag indicating if this page destination should just fit bounding box of the PDF. + * + * @return true If the destination should fit just the bounding box. + */ + public boolean fitBoundingBox() + { + return TYPE_BOUNDED.equals( array.getName( 1 ) ); + } + + /** + * Set if this page destination should just fit the bounding box. The default is false. + * + * @param fitBoundingBox A flag indicating if this should fit the bounding box. + */ + public void setFitBoundingBox( boolean fitBoundingBox ) + { + array.growToSize( 2 ); + if( fitBoundingBox ) + { + array.setName( 1, TYPE_BOUNDED ); + } + else + { + array.setName( 1, TYPE ); + } + } +} diff --git a/src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/destination/PDPageXYZDestination.java b/src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/destination/PDPageXYZDestination.java new file mode 100644 index 0000000..543a33c --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/destination/PDPageXYZDestination.java @@ -0,0 +1,159 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.interactive.documentnavigation.destination; + +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSBase; + +/** + * This represents a destination to a page at an x,y coordinate with a zoom setting. + * The default x,y,z will be whatever is the current value in the viewer application and + * are not required. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.1 $ + */ +public class PDPageXYZDestination extends PDPageDestination +{ + /** + * The type of this destination. + */ + protected static final String TYPE = "XYZ"; + + /** + * Default constructor. + * + */ + public PDPageXYZDestination() + { + super(); + array.growToSize(5); + array.setName( 1, TYPE ); + + } + + /** + * Constructor from an existing destination array. + * + * @param arr The destination array. + */ + public PDPageXYZDestination( COSArray arr ) + { + super( arr ); + } + + /** + * Get the left x coordinate. A return value of -1 implies that the current x-coordinate + * will be used. + * + * @return The left x coordinate. + */ + public int getLeft() + { + return array.getInt( 2 ); + } + + /** + * Set the left x-coordinate, a value of -1 implies that the current x-coordinate + * will be used. + * @param x The left x coordinate. + */ + public void setLeft( int x ) + { + array.growToSize( 3 ); + if( x == -1 ) + { + array.set( 2, (COSBase)null ); + } + else + { + array.setInt( 2, x ); + } + } + + /** + * Get the top y coordinate. A return value of -1 implies that the current y-coordinate + * will be used. + * + * @return The top y coordinate. + */ + public int getTop() + { + return array.getInt( 3 ); + } + + /** + * Set the top y-coordinate, a value of -1 implies that the current y-coordinate + * will be used. + * @param y The top ycoordinate. + */ + public void setTop( int y ) + { + array.growToSize( 4 ); + if( y == -1 ) + { + array.set( 3, (COSBase)null ); + } + else + { + array.setInt( 3, y ); + } + } + + /** + * Get the zoom value. A return value of -1 implies that the current zoom + * will be used. + * + * @return The zoom value for the page. + */ + public int getZoom() + { + return array.getInt( 4 ); + } + + /** + * Set the zoom value for the page, a value of -1 implies that the current zoom + * will be used. + * @param zoom The zoom value. + */ + public void setZoom( int zoom ) + { + array.growToSize( 5 ); + if( zoom == -1 ) + { + array.set( 4, (COSBase)null ); + } + else + { + array.setInt( 4, zoom ); + } + } +} diff --git a/src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/destination/package.html b/src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/destination/package.html new file mode 100644 index 0000000..2122b1d --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/destination/package.html @@ -0,0 +1,9 @@ + + + + + + +The destination package allows destinations into a pdf document to be specified. + + diff --git a/src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/outline/PDDocumentOutline.java b/src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/outline/PDDocumentOutline.java new file mode 100644 index 0000000..157a36f --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/outline/PDDocumentOutline.java @@ -0,0 +1,62 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.interactive.documentnavigation.outline; + +import org.pdfbox.cos.COSDictionary; + +/** + * This represents an outline in a pdf document. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.1 $ + */ +public class PDDocumentOutline extends PDOutlineNode +{ + + /** + * Default Constructor. + */ + public PDDocumentOutline() + { + super(); + node.setName( "Type", "Outlines" ); + } + + /** + * Constructor for an existing document outline. + * + * @param dic The storage dictionary. + */ + public PDDocumentOutline( COSDictionary dic ) + { + super( dic ); + } +} diff --git a/src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/outline/PDOutlineItem.java b/src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/outline/PDOutlineItem.java new file mode 100644 index 0000000..648eb64 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/outline/PDOutlineItem.java @@ -0,0 +1,425 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.interactive.documentnavigation.outline; + +import java.io.IOException; +import java.util.List; + +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSFloat; +import org.pdfbox.exceptions.OutlineNotLocalException; +import org.pdfbox.pdmodel.PDDestinationNameTreeNode; +import org.pdfbox.pdmodel.PDDocument; +import org.pdfbox.pdmodel.PDDocumentNameDictionary; +import org.pdfbox.pdmodel.PDPage; +import org.pdfbox.pdmodel.documentinterchange.logicalstructure.PDStructureElement; +import org.pdfbox.pdmodel.graphics.color.PDColorSpaceInstance; +import org.pdfbox.pdmodel.graphics.color.PDDeviceRGB; +import org.pdfbox.pdmodel.interactive.action.type.PDAction; +import org.pdfbox.pdmodel.interactive.action.type.PDActionGoTo; +import org.pdfbox.pdmodel.interactive.action.PDActionFactory; +import org.pdfbox.pdmodel.interactive.documentnavigation.destination.PDDestination; +import org.pdfbox.pdmodel.interactive.documentnavigation.destination.PDNamedDestination; +import org.pdfbox.pdmodel.interactive.documentnavigation.destination.PDPageDestination; +import org.pdfbox.pdmodel.interactive.documentnavigation.destination.PDPageXYZDestination; + +/** + * This represents an outline in a pdf document. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.5 $ + */ +public class PDOutlineItem extends PDOutlineNode +{ + + private static final int ITALIC_FLAG = 1; + private static final int BOLD_FLAG = 2; + + /** + * Default Constructor. + */ + public PDOutlineItem() + { + super(); + } + + /** + * Constructor for an existing outline item. + * + * @param dic The storage dictionary. + */ + public PDOutlineItem( COSDictionary dic ) + { + super( dic ); + } + + /** + * Insert a sibling after this node. + * + * @param item The item to insert. + */ + public void insertSiblingAfter( PDOutlineItem item ) + { + item.setParent( getParent() ); + PDOutlineItem next = getNextSibling(); + setNextSibling( item ); + item.setPreviousSibling( this ); + if( next != null ) + { + item.setNextSibling( next ); + next.setPreviousSibling( item ); + } + updateParentOpenCount( 1 ); + } + + /** + * Return the previous sibling or null if there is no sibling. + * + * @return The previous sibling. + */ + public PDOutlineItem getPreviousSibling() + { + PDOutlineItem last = null; + COSDictionary lastDic = (COSDictionary)node.getDictionaryObject( "Prev" ); + if( lastDic != null ) + { + last = new PDOutlineItem( lastDic ); + } + return last; + } + + /** + * Set the previous sibling, this will be maintained by this class. + * + * @param outlineNode The new previous sibling. + */ + protected void setPreviousSibling( PDOutlineNode outlineNode ) + { + node.setItem( "Prev", outlineNode ); + } + + /** + * Return the next sibling or null if there is no next sibling. + * + * @return The next sibling. + */ + public PDOutlineItem getNextSibling() + { + PDOutlineItem last = null; + COSDictionary lastDic = (COSDictionary)node.getDictionaryObject( "Next" ); + if( lastDic != null ) + { + last = new PDOutlineItem( lastDic ); + } + return last; + } + + /** + * Set the next sibling, this will be maintained by this class. + * + * @param outlineNode The new next sibling. + */ + protected void setNextSibling( PDOutlineNode outlineNode ) + { + node.setItem( "Next", outlineNode ); + } + + /** + * Get the title of this node. + * + * @return The title of this node. + */ + public String getTitle() + { + return node.getString( "Title" ); + } + + /** + * Set the title for this node. + * + * @param title The new title for this node. + */ + public void setTitle( String title ) + { + node.setString( "Title", title ); + } + + /** + * Get the page destination of this node. + * + * @return The page destination of this node. + * @throws IOException If there is an error creating the destination. + */ + public PDDestination getDestination() throws IOException + { + return PDDestination.create( node.getDictionaryObject( "Dest" ) ); + } + + /** + * Set the page destination for this node. + * + * @param dest The new page destination for this node. + */ + public void setDestination( PDDestination dest ) + { + node.setItem( "Dest", dest ); + } + + /** + * A convenience method that will create an XYZ destination using only the defaults. + * + * @param page The page to refer to. + */ + public void setDestination( PDPage page ) + { + PDPageXYZDestination dest = null; + if( page != null ) + { + dest = new PDPageXYZDestination(); + dest.setPage( page ); + } + setDestination( dest ); + } + + /** + * This method will attempt to find the page in this PDF document that this outline points to. + * If the outline does not point to anything then this method will return null. If the outline + * is an action that is not a GoTo action then this methods will throw the OutlineNotLocationException + * + * @param doc The document to get the page from. + * + * @return The page that this outline will go to when activated or null if it does not point to anything. + * @throws IOException If there is an error when trying to find the page. + */ + public PDPage findDestinationPage( PDDocument doc ) throws IOException + { + PDPage page = null; + PDDestination rawDest = getDestination(); + if( rawDest == null ) + { + PDAction outlineAction = getAction(); + if( outlineAction instanceof PDActionGoTo ) + { + rawDest = ((PDActionGoTo)outlineAction).getDestination(); + } + else if( outlineAction == null ) + { + //if the outline action is null then this outline does not refer + //to anything and we will just return null. + } + else + { + throw new OutlineNotLocalException( "Error: Outline does not reference a local page." ); + } + } + + PDPageDestination pageDest = null; + if( rawDest instanceof PDNamedDestination ) + { + //if we have a named destination we need to lookup the PDPageDestination + PDNamedDestination namedDest = (PDNamedDestination)rawDest; + PDDocumentNameDictionary namesDict = doc.getDocumentCatalog().getNames(); + if( namesDict != null ) + { + PDDestinationNameTreeNode destsTree = namesDict.getDests(); + if( destsTree != null ) + { + pageDest = (PDPageDestination)destsTree.getValue( namedDest.getNamedDestination() ); + } + } + } + else if( rawDest instanceof PDPageDestination) + { + pageDest = (PDPageDestination) rawDest; + } + else if( rawDest == null ) + { + //if the destination is null then we will simply return a null page. + } + else + { + throw new IOException( "Error: Unknown destination type " + rawDest ); + } + + if( pageDest != null ) + { + page = pageDest.getPage(); + if( page == null ) + { + int pageNumber = pageDest.getPageNumber(); + if( pageNumber != -1 ) + { + List allPages = doc.getDocumentCatalog().getAllPages(); + page = (PDPage)allPages.get( pageNumber ); + } + } + } + + return page; + } + + /** + * Get the action of this node. + * + * @return The action of this node. + */ + public PDAction getAction() + { + return PDActionFactory.createAction( (COSDictionary)node.getDictionaryObject( "A" ) ); + } + + /** + * Set the action for this node. + * + * @param action The new action for this node. + */ + public void setAction( PDAction action ) + { + node.setItem( "A", action ); + } + + /** + * Get the structure element of this node. + * + * @return The structure element of this node. + */ + public PDStructureElement getStructureElement() + { + PDStructureElement se = null; + COSDictionary dic = (COSDictionary)node.getDictionaryObject( "SE" ); + if( dic != null ) + { + se = new PDStructureElement( dic ); + } + return se; + } + + /** + * Set the structure element for this node. + * + * @param structureElement The new structure element for this node. + */ + public void setAction( PDStructureElement structureElement ) + { + node.setItem( "SE", structureElement ); + } + + /** + * Get the text color of this node. Default is black and this method + * will never return null. + * + * @return The structure element of this node. + */ + public PDColorSpaceInstance getTextColor() + { + PDColorSpaceInstance retval = null; + COSArray csValues = (COSArray)node.getDictionaryObject( "C" ); + if( csValues == null ) + { + csValues = new COSArray(); + csValues.growToSize( 3, new COSFloat( 0 ) ); + node.setItem( "C", csValues ); + } + retval = new PDColorSpaceInstance(csValues); + retval.setColorSpace( PDDeviceRGB.INSTANCE ); + return retval; + } + + /** + * Set the text color for this node. + * + * @param textColor The text color for this node. + */ + public void setTextColor( PDColorSpaceInstance textColor ) + { + node.setItem( "C", textColor.getCOSColorSpaceValue() ); + } + + /** + * A flag telling if the text should be italic. + * + * @return The italic flag. + */ + public boolean isItalic() + { + return (node.getInt( "F", 0 ) & ITALIC_FLAG) == ITALIC_FLAG; + } + + /** + * Set the italic property of the text. + * + * @param italic The new italic flag. + */ + public void setItalic( boolean italic ) + { + int f = node.getInt( "F", 0 ); + if( italic ) + { + f = f | ITALIC_FLAG; + } + else + { + f = f ^ ITALIC_FLAG; + } + node.setInt( "F", f ); + } + + /** + * A flag telling if the text should be bold. + * + * @return The bold flag. + */ + public boolean isBold() + { + return (node.getInt( "F", 0 ) & BOLD_FLAG) == BOLD_FLAG; + } + + /** + * Set the bold property of the text. + * + * @param bold The new bold flag. + */ + public void setBold( boolean bold ) + { + int f = node.getInt( "F", 0 ); + if( bold ) + { + f = f | BOLD_FLAG; + } + else + { + f = f ^ BOLD_FLAG; + } + node.setInt( "F", f ); + } + +} diff --git a/src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/outline/PDOutlineNode.java b/src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/outline/PDOutlineNode.java new file mode 100644 index 0000000..04cc45f --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/outline/PDOutlineNode.java @@ -0,0 +1,320 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.interactive.documentnavigation.outline; + +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSDictionary; + +import org.pdfbox.pdmodel.common.COSObjectable; + +/** + * This represents an node in an outline in a pdf document. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.1 $ + */ +public class PDOutlineNode implements COSObjectable +{ + /** + * The dictionary for this node. + */ + protected COSDictionary node; + + /** + * Default Constructor. + */ + public PDOutlineNode() + { + node = new COSDictionary(); + } + + /** + * Default Constructor. + * + * @param dict The dictionary storage. + */ + public PDOutlineNode( COSDictionary dict) + { + node = dict; + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSBase getCOSObject() + { + return node; + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSDictionary getCOSDictionary() + { + return node; + } + + /** + * Get the parent of this object. This will either be a DocumentOutline or an OutlineItem. + * + * @return The parent of this object, or null if this is the document outline and there + * is no parent. + */ + public PDOutlineNode getParent() + { + PDOutlineNode retval = null; + COSDictionary parent = (COSDictionary)node.getDictionaryObject( "Parent" ); + if( parent != null ) + { + if( parent.getDictionaryObject( "Parent") == null ) + { + retval = new PDDocumentOutline( parent ); + } + else + { + retval = new PDOutlineItem( parent ); + } + } + + return retval; + } + + /** + * Set the parent of this object, this is maintained by these objects and should not + * be called by any clients of PDFBox code. + * + * @param parent The parent of this object. + */ + protected void setParent( PDOutlineNode parent ) + { + node.setItem( "Parent", parent ); + } + + /** + * append a child node to this node. + * + * @param outlineNode The node to add. + */ + public void appendChild( PDOutlineItem outlineNode ) + { + outlineNode.setParent( this ); + if( getFirstChild() == null ) + { + int currentOpenCount = getOpenCount(); + setFirstChild( outlineNode ); + //1 for the the item we are adding; + int numberOfOpenNodesWeAreAdding = 1; + if( outlineNode.isNodeOpen() ) + { + numberOfOpenNodesWeAreAdding += outlineNode.getOpenCount(); + } + if( isNodeOpen() ) + { + setOpenCount( currentOpenCount + numberOfOpenNodesWeAreAdding ); + } + else + { + setOpenCount( currentOpenCount - numberOfOpenNodesWeAreAdding ); + } + updateParentOpenCount( numberOfOpenNodesWeAreAdding ); + } + else + { + PDOutlineItem previousLastChild = getLastChild(); + previousLastChild.insertSiblingAfter( outlineNode ); + } + setLastChild( outlineNode ); + } + + /** + * Return the first child or null if there is no child. + * + * @return The first child. + */ + public PDOutlineItem getFirstChild() + { + PDOutlineItem last = null; + COSDictionary lastDic = (COSDictionary)node.getDictionaryObject( "First" ); + if( lastDic != null ) + { + last = new PDOutlineItem( lastDic ); + } + return last; + } + + /** + * Set the first child, this will be maintained by this class. + * + * @param outlineNode The new first child. + */ + protected void setFirstChild( PDOutlineNode outlineNode ) + { + node.setItem( "First", outlineNode ); + } + + /** + * Return the last child or null if there is no child. + * + * @return The last child. + */ + public PDOutlineItem getLastChild() + { + PDOutlineItem last = null; + COSDictionary lastDic = (COSDictionary)node.getDictionaryObject( "Last" ); + if( lastDic != null ) + { + last = new PDOutlineItem( lastDic ); + } + return last; + } + + /** + * Set the last child, this will be maintained by this class. + * + * @param outlineNode The new last child. + */ + protected void setLastChild( PDOutlineNode outlineNode ) + { + node.setItem( "Last", outlineNode ); + } + + /** + * Get the number of open nodes. Or a negative number if this node + * is closed. See PDF Reference for more details. This value + * is updated as you append children and siblings. + * + * @return The Count attribute of the outline dictionary. + */ + public int getOpenCount() + { + return node.getInt( "Count", 0 ); + } + + /** + * Set the open count. This number is automatically managed for you + * when you add items to the outline. + * + * @param openCount The new open cound. + */ + protected void setOpenCount( int openCount ) + { + node.setInt( "Count", openCount ); + } + + /** + * This will set this node to be open when it is shown in the viewer. By default, when + * a new node is created it will be closed. + * This will do nothing if the node is already open. + */ + public void openNode() + { + //if the node is already open then do nothing. + if( !isNodeOpen() ) + { + int openChildrenCount = 0; + PDOutlineItem currentChild = getFirstChild(); + while( currentChild != null ) + { + //first increase by one for the current child + openChildrenCount++; + //then increase by the number of open nodes the child has + if( currentChild.isNodeOpen() ) + { + openChildrenCount += currentChild.getOpenCount(); + } + currentChild = currentChild.getNextSibling(); + } + setOpenCount( openChildrenCount ); + updateParentOpenCount( openChildrenCount ); + } + } + + /** + * Close this node. + * + */ + public void closeNode() + { + //if the node is already closed then do nothing. + if( isNodeOpen() ) + { + int openCount = getOpenCount(); + updateParentOpenCount( -openCount ); + setOpenCount( -openCount ); + } + } + + /** + * Node is open if the open count is greater than zero. + * @return true if this node is open. + */ + public boolean isNodeOpen() + { + return getOpenCount() > 0; + } + + /** + * The count parameter needs to be updated when you add or remove elements to + * the outline. When you add an element at a lower level then you need to + * increase all of the parents. + * + * @param amount The amount to update by. + */ + protected void updateParentOpenCount( int amount ) + { + PDOutlineNode parent = getParent(); + if( parent != null ) + { + int currentCount = parent.getOpenCount(); + //if the currentCount is negative or it is absent then + //we will treat it as negative. The default is to be negative. + boolean negative = currentCount < 0 || + parent.getCOSDictionary().getDictionaryObject( "Count" ) == null; + currentCount = Math.abs( currentCount ); + currentCount += amount; + if( negative ) + { + currentCount = -currentCount; + } + parent.setOpenCount( currentCount ); + //recursively call parent to update count, but the parents count is only + //updated if this is an open node + if( !negative ) + { + parent.updateParentOpenCount( amount ); + } + } + } +} diff --git a/src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/outline/package.html b/src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/outline/package.html new file mode 100644 index 0000000..4ec0032 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/outline/package.html @@ -0,0 +1,9 @@ + + + + + + +The outline package allows for a PDF outline(bookmarks) to be created. + + diff --git a/src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/package.html b/src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/package.html new file mode 100644 index 0000000..b210cf5 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/interactive/documentnavigation/package.html @@ -0,0 +1,9 @@ + + + + + + +A package to allow access to document level navigation within a PDF document. + + diff --git a/src/main/java/org/pdfbox/pdmodel/interactive/form/PDAcroForm.java b/src/main/java/org/pdfbox/pdmodel/interactive/form/PDAcroForm.java new file mode 100644 index 0000000..4fb576d --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/interactive/form/PDAcroForm.java @@ -0,0 +1,328 @@ +/** + * Copyright (c) 2003-2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.interactive.form; + +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSName; +import org.pdfbox.cos.COSString; + +import org.pdfbox.pdmodel.PDDocument; +import org.pdfbox.pdmodel.PDResources; + +import org.pdfbox.pdmodel.fdf.FDFDictionary; +import org.pdfbox.pdmodel.fdf.FDFDocument; +import org.pdfbox.pdmodel.fdf.FDFCatalog; +import org.pdfbox.pdmodel.fdf.FDFField; + +import java.io.IOException; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +/** + * This class represents the acroform of a PDF document. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.8 $ + */ +public class PDAcroForm +{ + private COSDictionary acroForm; + private PDDocument document; + + private Map fieldCache; + + /** + * Constructor. + * + * @param doc The document that this form is part of. + */ + public PDAcroForm( PDDocument doc ) + { + document = doc; + acroForm = new COSDictionary(); + COSArray fields = new COSArray(); + acroForm.setItem( COSName.getPDFName( "Fields" ), fields ); + } + + /** + * Constructor. + * + * @param doc The document that this form is part of. + * @param form The existing acroForm. + */ + public PDAcroForm( PDDocument doc, COSDictionary form ) + { + document = doc; + acroForm = form; + } + + /** + * This will get the document associated with this form. + * + * @return The PDF document. + */ + public PDDocument getDocument() + { + return document; + } + + /** + * This will get the dictionary that this form wraps. + * + * @return The dictionary for this form. + */ + public COSDictionary getDictionary() + { + return acroForm; + } + + /** + * This method will import an entire FDF document into the PDF document + * that this acroform is part of. + * + * @param fdf The FDF document to import. + * + * @throws IOException If there is an error doing the import. + */ + public void importFDF( FDFDocument fdf ) throws IOException + { + List fields = fdf.getCatalog().getFDF().getFields(); + if( fields != null ) + { + for( int i=0; i 0 ) + { + fdfDict.setFields( fdfFields ); + } + return fdf; + } + + private void addFieldAndChildren( PDField docField, List fdfFields ) throws IOException + { + Object fieldValue = docField.getValue(); + FDFField fdfField = new FDFField(); + fdfField.setPartialFieldName( docField.getPartialName() ); + fdfField.setValue( fieldValue ); + List kids = docField.getKids(); + List childFDFFields = new ArrayList(); + if( kids != null ) + { + + for( int i=0; i 0 ) + { + fdfField.setKids( childFDFFields ); + } + } + if( fieldValue != null || childFDFFields.size() > 0 ) + { + fdfFields.add( fdfField ); + } + } + + /** + * This will return all of the fields in the document. The type + * will be a org.pdfbox.pdmodel.field.PDField. + * + * @return A list of all the fields. + * @throws IOException If there is an error while getting the list of fields. + */ + public List getFields() throws IOException + { + COSArray fields = + (COSArray) acroForm.getDictionaryObject( + COSName.getPDFName("Fields")); + + List retval = new ArrayList(); + for (int i = 0; i < fields.size(); i++) + { + COSDictionary element = (COSDictionary) fields.getObject(i); + if (element != null) + { + PDField field = PDFieldFactory.createField( this, element ); + if( field != null ) + { + retval.add(field); + } + } + } + return retval; + } + + /** + * This will tell this form to cache the fields into a Map structure + * for fast access via the getField method. The default is false. You would + * want this to be false if you were changing the COSDictionary behind the scenes, + * otherwise setting this to true is acceptable. + * + * @param cache A boolean telling if we should cache the fields. + * @throws IOException If there is an error while caching the fields. + */ + public void setCacheFields( boolean cache ) throws IOException + { + if( cache ) + { + fieldCache = new HashMap(); + List fields = getFields(); + Iterator fieldIter = fields.iterator(); + while( fieldIter.hasNext() ) + { + PDField next = (PDField)fieldIter.next(); + fieldCache.put( next.getFullyQualifiedName(), next ); + } + } + else + { + fieldCache = null; + } + } + + /** + * This will tell if this acro form is caching the fields. + * + * @return true if the fields are being cached. + */ + public boolean isCachingFields() + { + return fieldCache != null; + } + + /** + * This will get a field by name, possibly using the cache if setCache is true. + * + * @param name The name of the field to get. + * + * @return The field with that name of null if one was not found. + * + * @throws IOException If there is an error getting the field type. + */ + public PDField getField( String name ) throws IOException + { + PDField retval = null; + if( fieldCache != null ) + { + retval = (PDField)fieldCache.get( name ); + } + else + { + COSArray fields = + (COSArray) acroForm.getDictionaryObject( + COSName.getPDFName("Fields")); + + for (int i = 0; i < fields.size() && retval == null; i++) + { + COSDictionary element = (COSDictionary) fields.getObject(i); + if( element != null ) + { + COSString fieldName = + (COSString)element.getDictionaryObject( COSName.getPDFName( "T" ) ); + if( fieldName.getString().equals( name ) ) + { + retval = PDFieldFactory.createField( this, element ); + } + } + } + } + return retval; + } + + /** + * This will get the default resources for the acro form. + * + * @return The default resources. + */ + public PDResources getDefaultResources() + { + PDResources retval = null; + COSDictionary dr = (COSDictionary)acroForm.getDictionaryObject( COSName.getPDFName( "DR" ) ); + if( dr != null ) + { + retval = new PDResources( dr ); + } + return retval; + } + + /** + * This will set the default resources for the acroform. + * + * @param dr The new default resources. + */ + public void setDefaultResources( PDResources dr ) + { + COSDictionary drDict = null; + if( dr != null ) + { + drDict = dr.getCOSDictionary(); + } + acroForm.setItem( COSName.getPDFName( "DR" ), drDict ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/interactive/form/PDAppearance.java b/src/main/java/org/pdfbox/pdmodel/interactive/form/PDAppearance.java new file mode 100644 index 0000000..ff18c86 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/interactive/form/PDAppearance.java @@ -0,0 +1,645 @@ +/** + * Copyright (c) 2003-2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.interactive.form; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSFloat; +import org.pdfbox.cos.COSName; +import org.pdfbox.cos.COSNumber; +import org.pdfbox.cos.COSStream; +import org.pdfbox.cos.COSString; + +import org.pdfbox.pdfparser.PDFStreamParser; +import org.pdfbox.pdfwriter.ContentStreamWriter; + +import org.pdfbox.pdmodel.PDResources; + +import org.pdfbox.pdmodel.common.PDRectangle; + +import org.pdfbox.pdmodel.font.PDFont; +import org.pdfbox.pdmodel.font.PDFontDescriptor; +import org.pdfbox.pdmodel.font.PDSimpleFont; + +import org.pdfbox.pdmodel.interactive.action.PDAdditionalActions; +import org.pdfbox.pdmodel.interactive.annotation.PDAppearanceDictionary; +import org.pdfbox.pdmodel.interactive.annotation.PDAppearanceStream; +import org.pdfbox.pdmodel.interactive.annotation.PDAnnotationWidget; + +import org.pdfbox.util.PDFOperator; + +/** + * This one took me a while, but i'm proud to say that it handles + * the appearance of a textbox. This allows you to apply a value to + * a field in the document and handle the appearance so that the + * value is actually visible too. + * The problem was described by Ben Litchfield, the author of the + * example: org.pdfbox.examlpes.fdf.ImportFDF. So Ben, here is the + * solution. + * + * @author sug + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.17 $ + */ +public class PDAppearance +{ + private PDVariableText parent; + + private String value; + private COSString defaultAppearance; + + private PDAcroForm acroForm; + private List widgets = new ArrayList(); + + + /** + * Constructs a COSAppearnce from the given field. + * + * @param theAcroForm the acro form that this field is part of. + * @param field the field which you wish to control the appearance of + * @throws IOException If there is an error creating the appearance. + */ + public PDAppearance( PDAcroForm theAcroForm, PDVariableText field ) throws IOException + { + acroForm = theAcroForm; + parent = field; + + widgets = field.getKids(); + if( widgets == null ) + { + widgets = new ArrayList(); + widgets.add( field.getWidget() ); + } + + defaultAppearance = getDefaultAppearance(); + + + } + + /** + * Returns the default apperance of a textbox. If the textbox + * does not have one, then it will be taken from the AcroForm. + * @return The DA element + */ + private COSString getDefaultAppearance() + { + + COSString dap = parent.getDefaultAppearance(); + if (dap == null) + { + COSArray kids = (COSArray)parent.getDictionary().getDictionaryObject( "Kids" ); + if( kids != null && kids.size() > 0 ) + { + COSDictionary firstKid = (COSDictionary)kids.getObject( 0 ); + dap = (COSString)firstKid.getDictionaryObject( "DA" ); + } + if( dap == null ) + { + dap = (COSString) acroForm.getDictionary().getDictionaryObject(COSName.getPDFName("DA")); + } + } + return dap; + } + + private int getQ() + { + int q = parent.getQ(); + if( parent.getDictionary().getDictionaryObject( "Q" ) == null ) + { + COSArray kids = (COSArray)parent.getDictionary().getDictionaryObject( "Kids" ); + if( kids != null && kids.size() > 0 ) + { + COSDictionary firstKid = (COSDictionary)kids.getObject( 0 ); + COSNumber qNum = (COSNumber)firstKid.getDictionaryObject( "Q" ); + if( qNum != null ) + { + q = qNum.intValue(); + } + } + } + return q; + } + + /** + * Extracts the original appearance stream into a list of tokens. + * + * @return The tokens in the original appearance stream + */ + private List getStreamTokens( PDAppearanceStream appearanceStream ) throws IOException + { + List tokens = null; + if( appearanceStream != null ) + { + tokens = getStreamTokens( appearanceStream.getStream() ); + } + return tokens; + } + + private List getStreamTokens( COSString string ) throws IOException + { + PDFStreamParser parser; + + List tokens = null; + if( string != null ) + { + ByteArrayInputStream stream = new ByteArrayInputStream( string.getBytes() ); + parser = new PDFStreamParser( stream, acroForm.getDocument().getDocument().getScratchFile() ); + parser.parse(); + tokens = parser.getTokens(); + } + return tokens; + } + + private List getStreamTokens( COSStream stream ) throws IOException + { + PDFStreamParser parser; + + List tokens = null; + if( stream != null ) + { + parser = new PDFStreamParser( stream ); + parser.parse(); + tokens = parser.getTokens(); + } + return tokens; + } + + /** + * Tests if the apperance stream already contains content. + * + * @return true if it contains any content + */ + private boolean containsMarkedContent( List stream ) + { + return stream.contains( PDFOperator.getOperator( "BMC" ) ); + } + + /** + * This is the public method for setting the appearance stream. + * + * @param apValue the String value which the apperance shoud represent + * + * @throws IOException If there is an error creating the stream. + */ + public void setAppearanceValue(String apValue) throws IOException + { + // MulitLine check and set + if ( parent.isMultiline() && apValue.indexOf('\n') != -1 ) + { + apValue = convertToMultiLine( apValue ); + } + + value = apValue; + Iterator widgetIter = widgets.iterator(); + while( widgetIter.hasNext() ) + { + Object next = widgetIter.next(); + PDAnnotationWidget widget = null; + if( next instanceof PDField ) + { + widget = ((PDField)next).getWidget(); + } + else + { + widget = (PDAnnotationWidget)next; + } + PDAdditionalActions actions = widget.getActions(); + if( actions != null && + actions.getF() != null && + widget.getDictionary().getDictionaryObject( "AP" ) ==null) + { + //do nothing because the field will be formatted by acrobat + //when it is opened. See FreedomExpressions.pdf for an example of this. + } + else + { + + PDAppearanceDictionary appearance = widget.getAppearance(); + if( appearance == null ) + { + appearance = new PDAppearanceDictionary(); + widget.setAppearance( appearance ); + } + + Map normalAppearance = appearance.getNormalAppearance(); + PDAppearanceStream appearanceStream = (PDAppearanceStream)normalAppearance.get( "default" ); + if( appearanceStream == null ) + { + COSStream cosStream = new COSStream( acroForm.getDocument().getDocument().getScratchFile() ); + appearanceStream = new PDAppearanceStream( cosStream ); + appearanceStream.setBoundingBox( widget.getRectangle().createRetranslatedRectangle() ); + appearance.setNormalAppearance( appearanceStream ); + } + + List tokens = getStreamTokens( appearanceStream ); + List daTokens = getStreamTokens( getDefaultAppearance() ); + PDFont pdFont = getFontAndUpdateResources( tokens, appearanceStream ); + + if (!containsMarkedContent( tokens )) + { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + + //BJL 9/25/2004 Must prepend existing stream + //because it might have operators to draw things like + //rectangles and such + ContentStreamWriter writer = new ContentStreamWriter( output ); + writer.writeTokens( tokens ); + + output.write( " /Tx BMC\n".getBytes() ); + insertGeneratedAppearance( widget, output, pdFont, tokens, appearanceStream ); + output.write( " EMC".getBytes() ); + writeToStream( output.toByteArray(), appearanceStream ); + } + else + { + if( tokens != null ) + { + if( daTokens != null ) + { + int bmcIndex = tokens.indexOf( PDFOperator.getOperator( "BMC" )); + int emcIndex = tokens.indexOf( PDFOperator.getOperator( "EMC" )); + if( bmcIndex != -1 && emcIndex != -1 && + emcIndex == bmcIndex+1 ) + { + //if the EMC immediately follows the BMC index then should + //insert the daTokens inbetween the two markers. + tokens.addAll( emcIndex, daTokens ); + } + } + ByteArrayOutputStream output = new ByteArrayOutputStream(); + ContentStreamWriter writer = new ContentStreamWriter( output ); + float fontSize = calculateFontSize( pdFont, appearanceStream.getBoundingBox(), tokens, null ); + boolean foundString = false; + for( int i=0; i -1 ) + { + result.append(value.substring(lastIdx,currIdx)); + result.append(" ) Tj\n0 -13 Td\n("); + lastIdx = currIdx + 1; + } + result.append(line.substring(lastIdx)); + return result.toString(); + } + + /** + * Writes the stream to the actual stream in the COSStream. + * + * @throws IOException If there is an error writing to the stream + */ + private void writeToStream( byte[] data, PDAppearanceStream appearanceStream ) throws IOException + { + OutputStream out = appearanceStream.getStream().createUnfilteredStream(); + out.write( data ); + out.flush(); + } + + + /** + * w in an appearance stream represents the lineWidth. + * @return the linewidth + */ + private float getLineWidth( List tokens ) + { + + float retval = 1; + if( tokens != null ) + { + int btIndex = tokens.indexOf(PDFOperator.getOperator( "BT" )); + int wIndex = tokens.indexOf(PDFOperator.getOperator( "w" )); + //the w should only be used if it is before the first BT. + if( (wIndex > 0) && (wIndex < btIndex) ) + { + retval = ((COSNumber)tokens.get(wIndex-1)).floatValue(); + } + } + return retval; + } + + private PDRectangle getSmallestDrawnRectangle( PDRectangle boundingBox, List tokens ) + { + PDRectangle smallest = boundingBox; + for( int i=0; i potentialSmallest.getUpperRightY() ) + { + smallest = potentialSmallest; + } + + } + } + return smallest; + } + + /** + * My "not so great" method for calculating the fontsize. + * It does not work superb, but it handles ok. + * @return the calculated font-size + * + * @throws IOException If there is an error getting the font height. + */ + private float calculateFontSize( PDFont pdFont, PDRectangle boundingBox, List tokens, List daTokens ) + throws IOException + { + float fontSize = 0; + if( daTokens != null ) + { + //daString looks like "BMC /Helv 3.4 Tf EMC" + + int fontIndex = daTokens.indexOf( PDFOperator.getOperator( "Tf" ) ); + if(fontIndex != -1 ) + { + fontSize = ((COSNumber)daTokens.get(fontIndex-1)).floatValue(); + } + } + if( parent.doNotScroll() ) + { + //if we don't scroll then we will shrink the font to fit into the text area. + float widthAtFontSize1 = pdFont.getStringWidth( value ); + float availableWidth = boundingBox.getWidth(); + float perfectFitFontSize = availableWidth / widthAtFontSize1; + } + else if( fontSize == 0 ) + { + float lineWidth = getLineWidth( tokens ); + float stringWidth = pdFont.getStringWidth( value ); + float height = 0; + if( pdFont instanceof PDSimpleFont ) + { + height = ((PDSimpleFont)pdFont).getFontDescriptor().getFontBoundingBox().getHeight(); + } + else + { + //now much we can do, so lets assume font is square and use width + //as the height + height = pdFont.getAverageFontWidth(); + } + height = height/1000f; + + float availHeight = getAvailableHeight( boundingBox, lineWidth ); + fontSize =(availHeight/height); + } + return fontSize; + } + + /** + * Calculates where to start putting the text in the box. + * The positioning is not quite as accurate as when Acrobat + * places the elements, but it works though. + * + * @return the sting for representing the start position of the text + * + * @throws IOException If there is an error calculating the text position. + */ + private String getTextPosition( PDRectangle boundingBox, PDFont pdFont, float fontSize, List tokens ) + throws IOException + { + float lineWidth = getLineWidth( tokens ); + float pos = 0.0f; + if(parent.isMultiline()) + { + int rows = (int) (getAvailableHeight( boundingBox, lineWidth ) / ((int) fontSize)); + pos = ((rows)*fontSize)-fontSize; + } + else + { + if( pdFont instanceof PDSimpleFont ) + { + //BJL 9/25/2004 + //This algorithm is a little bit of black magic. It does + //not appear to be documented anywhere. Through examining a few + //PDF documents and the value that Acrobat places in there I + //have determined that the below method of computing the position + //is correct for certain documents, but maybe not all. It does + //work f1040ez.pdf and Form_1.pdf + PDFontDescriptor fd = ((PDSimpleFont)pdFont).getFontDescriptor(); + float bBoxHeight = boundingBox.getHeight(); + float fontHeight = fd.getFontBoundingBox().getHeight() + 2 * fd.getDescent(); + fontHeight = (fontHeight/1000) * fontSize; + pos = (bBoxHeight - fontHeight)/2; + } + else + { + throw new IOException( "Error: Don't know how to calculate the position for non-simple fonts" ); + } + } + PDRectangle innerBox = getSmallestDrawnRectangle( boundingBox, tokens ); + float xInset = 2+ 2*(boundingBox.getWidth() - innerBox.getWidth()); + return Math.round(xInset) + " "+ pos + " Td"; + } + + /** + * calculates the available width of the box. + * @return the calculated available width of the box + */ + private float getAvailableWidth( PDRectangle boundingBox, float lineWidth ) + { + return boundingBox.getWidth() - 2 * lineWidth; + } + + /** + * calculates the available height of the box. + * @return the calculated available height of the box + */ + private float getAvailableHeight( PDRectangle boundingBox, float lineWidth ) + { + return boundingBox.getHeight() - 2 * lineWidth; + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/interactive/form/PDCheckbox.java b/src/main/java/org/pdfbox/pdmodel/interactive/form/PDCheckbox.java new file mode 100644 index 0000000..2e175d0 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/interactive/form/PDCheckbox.java @@ -0,0 +1,187 @@ +/** + * Copyright (c) 2003-2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.interactive.form; + +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSName; + +import java.io.IOException; +import java.util.Iterator; +import java.util.List; + +/** + * A class for handling the PDF field as a checkbox. + * + * @author sug + * @version $Revision: 1.10 $ + */ +public class PDCheckbox extends PDChoiceButton +{ + private static final COSName KEY = COSName.getPDFName("AS"); + private static final COSName OFF_VALUE = COSName.getPDFName("Off"); + + private COSName value; + + /** + * @see PDField#PDField(PDAcroForm,COSDictionary) + * + * @param theAcroForm The acroForm for this field. + * @param field The checkbox field dictionary + */ + public PDCheckbox( PDAcroForm theAcroForm, COSDictionary field) + { + super( theAcroForm, field); + COSDictionary ap = (COSDictionary) field.getDictionaryObject(COSName.getPDFName("AP")); + if( ap != null ) + { + COSBase n = ap.getDictionaryObject(COSName.getPDFName("N")); + + if( n instanceof COSDictionary ) + { + List li = ((COSDictionary)n).keyList(); + for( int i=0; i 0 ) + { + Object firstKid = kids.get( 0 ); + if( firstKid instanceof PDAnnotationWidget ) + { + retval = (PDAnnotationWidget)firstKid; + } + else + { + retval = ((PDField)firstKid).getWidget(); + } + } + else + { + retval = null; + } + return retval; + } + + /** + * Get the parent field to this field, or null if none exists. + * + * @return The parent field. + * + * @throws IOException If there is an error creating the parent field. + */ + public PDField getParent() throws IOException + { + PDField parent = null; + COSDictionary parentDic = (COSDictionary)getDictionary().getDictionaryObject( "Parent" ); + if( parentDic != null ) + { + parent = PDFieldFactory.createField( getAcroForm(), parentDic ); + } + return parent; + } + + /** + * Set the parent of this field. + * + * @param parent The parent to this field. + */ + public void setParent( PDField parent ) + { + getDictionary().setItem( "Parent", parent ); + } + + /** + * This will get all the kids of this field. The values in the list + * will either be PDWidget or PDField. Normally they will be PDWidget objects + * unless this is a non-terminal field and they will be child PDField objects. + * + * @return A list of either PDWidget or PDField objects. + * @throws IOException If there is an error retrieving the kids. + */ + public List getKids() throws IOException + { + List retval = null; + COSArray kids = (COSArray)getDictionary().getDictionaryObject(COSName.KIDS); + if( kids != null ) + { + List kidsList = new ArrayList(); + for (int i = 0; i < kids.size(); i++) + { + COSDictionary kidDictionary = (COSDictionary)kids.getObject(i); + COSDictionary parent = (COSDictionary)kidDictionary.getDictionaryObject( "Parent" ); + if( kidDictionary.getDictionaryObject( "FT" ) != null || + (parent != null && parent.getDictionaryObject( "FT" ) != null ) ) + { + kidsList.add( PDFieldFactory.createField( acroForm, kidDictionary )); + } + else if( "Widget".equals( kidDictionary.getNameAsString( "Subtype" ) ) ) + { + kidsList.add( new PDAnnotationWidget( kidDictionary ) ); + } + else + { + // + kidsList.add( PDFieldFactory.createField( acroForm, kidDictionary )); + } + } + retval = new COSArrayList( kidsList, kids ); + } + return retval; + } + + /** + * This will set the list of kids. + * + * @param kids The list of child widgets. + */ + public void setKids( List kids ) + { + COSArray kidsArray = COSArrayList.converterToCOSArray( kids ); + getDictionary().setItem( COSName.KIDS, kidsArray ); + } + + /** + * This will return a string representation of this field. + * + * @return A string representation of this field. + */ + public String toString() + { + return "" + getDictionary().getDictionaryObject( COSName.getPDFName( "V" ) ); + } + + /** + * This will get the acroform that this field is part of. + * + * @return The form this field is on. + */ + public PDAcroForm getAcroForm() + { + return acroForm; + } + + /** + * This will set the form this field is on. + * + * @param value The new form to use. + */ + public void setAcroForm(PDAcroForm value) + { + acroForm = value; + } + + /** + * This will get the dictionary associated with this field. + * + * @return The dictionary that this class wraps. + */ + public COSDictionary getDictionary() + { + return dictionary; + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSBase getCOSObject() + { + return dictionary; + } + + /** + * Get the additional actions for this field. This will return null + * if there are no additional actions for this field. + * + * @return The actions of the field. + */ + public PDFormFieldAdditionalActions getActions() + { + COSDictionary aa = (COSDictionary)dictionary.getDictionaryObject( "AA" ); + PDFormFieldAdditionalActions retval = null; + if( aa != null ) + { + retval = new PDFormFieldAdditionalActions( aa ); + } + return retval; + } + + /** + * Set the actions of the field. + * + * @param actions The field actions. + */ + public void setActions( PDFormFieldAdditionalActions actions ) + { + dictionary.setItem( "AA", actions ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/interactive/form/PDFieldFactory.java b/src/main/java/org/pdfbox/pdmodel/interactive/form/PDFieldFactory.java new file mode 100644 index 0000000..c796714 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/interactive/form/PDFieldFactory.java @@ -0,0 +1,218 @@ +/** + * Copyright (c) 2003-2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.interactive.form; + +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSName; +import org.pdfbox.pdmodel.interactive.annotation.PDAnnotationWidget; + +import java.io.IOException; + +import java.util.List; + +/** + * This is the Factory for creating and returning the correct + * field elements. + * + * @author sug + * @version $Revision: 1.8 $ + */ +public class PDFieldFactory +{ + private static final int RADIO_BITMASK = 32768; + private static final int PUSHBUTTON_BITMASK = 65536; + private static final int RADIOS_IN_UNISON_BITMASK = 33554432; + + private static final String FIELD_TYPE_BTN = "Btn"; + private static final String FIELD_TYPE_TX = "Tx"; + private static final String FIELD_TYPE_CH = "Ch"; + private static final String FIELD_TYPE_SIG = "Sig"; + + /** + * Utility class so no constructor. + */ + private PDFieldFactory() + { + //do nothing. + } + + /** + * This method creates a COSField subclass from the given field. + * The field is a PDF Dictionary object that must represent a + * field element. - othewise null is returned + * + * @param acroForm The form that the field will be part of. + * @param field The dictionary representing a field element + * + * @return a subclass to COSField according to the kind of field passed to createField + * @throws IOException If there is an error determining the field type. + */ + public static PDField createField( PDAcroForm acroForm, COSDictionary field) throws IOException + { + PDField pdField = new PDUnknownField( acroForm, field ); + if( isButton(pdField) ) + { + int flags = pdField.getFieldFlags(); + //BJL, I have found that the radio flag bit is not always set + //and that sometimes there is just a kids dictionary. + //so, if there is a kids dictionary then it must be a radio button + //group. + COSArray kids = (COSArray)field.getDictionaryObject( COSName.getPDFName( "Kids" ) ); + if( kids != null || isRadio(flags) ) + { + pdField = new PDRadioCollection( acroForm, field ); + } + else if( isPushButton( flags ) ) + { + pdField = new PDPushButton( acroForm, field ); + } + else + { + pdField = new PDCheckbox( acroForm, field ); + } + + } + else if (isChoiceField(pdField)) + { + pdField = new PDChoiceField( acroForm, field ); + } + else if (isTextbox(pdField)) + { + pdField = new PDTextbox( acroForm, field ); + } + else if( isSignature( pdField ) ) + { + pdField = new PDSignature( acroForm, field ); + } + else + { + //do nothing and return an unknown field type. + } + return pdField; + } + + /** + * This method determines if the given + * field is a radiobutton collection. + * + * @param flags The field flags. + * + * @return the result of the determination + */ + private static boolean isRadio( int flags ) + { + return (flags & RADIO_BITMASK) > 0; + } + + /** + * This method determines if the given + * field is a pushbutton. + * + * @param flags The field flags. + * + * @return the result of the determination + */ + private static boolean isPushButton( int flags ) + { + return (flags & PUSHBUTTON_BITMASK) > 0; + } + + /** + * This method determines if the given field is a choicefield + * Choicefields are either listboxes or comboboxes. + * + * @param field the field to determine + * @return the result of the determination + */ + private static boolean isChoiceField(PDField field) throws IOException + { + return FIELD_TYPE_CH.equals(field.findFieldType()); + } + + /** + * This method determines if the given field is a button. + * + * @param field the field to determine + * @return the result of the determination + * + * @throws IOException If there is an error determining the field type. + */ + private static boolean isButton(PDField field) throws IOException + { + String ft = field.findFieldType(); + boolean retval = FIELD_TYPE_BTN.equals( ft ); + List kids = field.getKids(); + if( ft == null && kids != null && kids.size() > 0) + { + //sometimes if it is a button the type is only defined by one + //of the kids entries + Object obj = kids.get( 0 ); + COSDictionary kidDict = null; + if( obj instanceof PDField ) + { + kidDict = ((PDField)obj).getDictionary(); + } + else if( obj instanceof PDAnnotationWidget ) + { + kidDict = ((PDAnnotationWidget)obj).getDictionary(); + } + else + { + throw new IOException( "Error:Unexpected type of kids field:" + obj ); + } + retval = isButton( new PDUnknownField( field.getAcroForm(), kidDict ) ); + } + return retval; + } + + /** + * This method determines if the given field is a signature. + * + * @param field the field to determine + * @return the result of the determination + */ + private static boolean isSignature(PDField field) throws IOException + { + return FIELD_TYPE_SIG.equals(field.findFieldType()); + } + + /** + * This method determines if the given field is a Textbox. + * + * @param field the field to determine + * @return the result of the determination + */ + private static boolean isTextbox(PDField field) throws IOException + { + return FIELD_TYPE_TX.equals(field.findFieldType()); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/interactive/form/PDPushButton.java b/src/main/java/org/pdfbox/pdmodel/interactive/form/PDPushButton.java new file mode 100644 index 0000000..e832921 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/interactive/form/PDPushButton.java @@ -0,0 +1,84 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.interactive.form; + +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSName; +import org.pdfbox.cos.COSString; + +import java.io.IOException; + +/** + * A class for handling the PDF field as a PDPushButton. + * + * @author sug + * @version $Revision: 1.3 $ + */ +public class PDPushButton extends PDField +{ + + /** + * @see org.pdfbox.pdmodel.field.PDField#COSField(org.pdfbox.cos.COSDictionary) + * + * @param theAcroForm The acroForm for this field. + * @param field The field for this push button. + */ + public PDPushButton( PDAcroForm theAcroForm, COSDictionary field) + { + super(theAcroForm, field); + } + + /** + * @see as.interactive.pdf.form.cos.COSField#setValue(java.lang.String) + * + * @param value The new value for the field. + * + * @throws IOException If there is an error creating the appearance stream. + */ + public void setValue(String value) throws IOException + { + COSString fieldValue = new COSString(value); + getDictionary().setItem( COSName.getPDFName( "V" ), fieldValue ); + getDictionary().setItem( COSName.getPDFName( "DV" ), fieldValue ); + } + + /** + * getValue gets the fields value to as a string. + * + * @return The string value of this field. + * + * @throws IOException If there is an error getting the value. + */ + public String getValue() throws IOException + { + return getDictionary().getString( "V" ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/interactive/form/PDRadioCollection.java b/src/main/java/org/pdfbox/pdmodel/interactive/form/PDRadioCollection.java new file mode 100644 index 0000000..27b48d6 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/interactive/form/PDRadioCollection.java @@ -0,0 +1,170 @@ +/** + * Copyright (c) 2003-2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.interactive.form; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSName; + +import org.pdfbox.pdmodel.common.COSArrayList; +import org.pdfbox.util.BitFlagHelper; + +/** + * A class for handling the PDF field as a Radio Collection. + * This class automatically keeps track of the child radio buttons + * in the collection. + * + * @see PDCheckbox + * @author sug + * @version $Revision: 1.12 $ + */ +public class PDRadioCollection extends PDChoiceButton +{ + /** + * A Ff flag. + */ + public static final int FLAG_RADIOS_IN_UNISON = 1 << 25; + + /** + * @see PDField#PDField(PDAcroForm,COSDictionary) + * + * @param theAcroForm The acroForm for this field. + * @param field The field that makes up the radio collection. + */ + public PDRadioCollection( PDAcroForm theAcroForm, COSDictionary field) + { + super(theAcroForm,field); + } + + /** + * From the PDF Spec
    + * If set, a group of radio buttons within a radio button field that + * use the same value for the on state will turn on and off in unison; that is if + * one is checked, they are all checked. If clear, the buttons are mutually exclusive + * (the same behavior as HTML radio buttons). + * + * @param radiosInUnison The new flag for radiosInUnison. + */ + public void setRadiosInUnison(boolean radiosInUnison) + { + BitFlagHelper.setFlag( getDictionary(), "Ff", FLAG_RADIOS_IN_UNISON, radiosInUnison ); + } + + /** + * + * @return true If the flag is set for radios in unison. + */ + public boolean isRadiosInUnison() + { + return BitFlagHelper.getFlag( getDictionary(), "Ff", FLAG_RADIOS_IN_UNISON ); + } + + /** + * This setValue method iterates the collection of radiobuttons + * and checks or unchecks each radiobutton according to the + * given value. + * If the value is not represented by any of the radiobuttons, + * then none will be checked. + * + * @see org.pdfbox.pdmodel.interactive.form.PDField#setValue(java.lang.String) + */ + public void setValue(String value) throws IOException + { + getDictionary().setString( "V", value ); + List kids = getKids(); + for (int i = 0; i < kids.size(); i++) + { + PDCheckbox btn = (PDCheckbox)kids.get(i); + if( btn.getOnValue().equals(value) ) + { + btn.check(); + } + else + { + btn.unCheck(); + } + } + } + + /** + * getValue gets the fields value to as a string. + * + * @return The string value of this field. + * + * @throws IOException If there is an error getting the value. + */ + public String getValue()throws IOException + { + String retval = null; + List kids = getKids(); + for (int i = 0; i < kids.size(); i++) + { + PDCheckbox btn = (PDCheckbox)kids.get(i); + if( btn.isChecked() ) + { + retval = btn.getOnValue(); + } + } + if( retval == null ) + { + retval = getDictionary().getNameAsString( "V" ); + } + return retval; + } + + + /** + * This will return a list of PDField objects that are part of this radio collection. + * + * @see PDField#getWidget() + * @return A list of PDWidget objects. + * @throws IOException if there is an error while creating the children objects. + */ + public List getKids() throws IOException + { + List retval = null; + COSArray kids = (COSArray)getDictionary().getDictionaryObject(COSName.KIDS); + if( kids != null ) + { + List kidsList = new ArrayList(); + for (int i = 0; i < kids.size(); i++) + { + kidsList.add( PDFieldFactory.createField( getAcroForm(), (COSDictionary)kids.getObject(i) ) ); + } + retval = new COSArrayList( kidsList, kids ); + } + return retval; + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/interactive/form/PDSignature.java b/src/main/java/org/pdfbox/pdmodel/interactive/form/PDSignature.java new file mode 100644 index 0000000..66ed3e3 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/interactive/form/PDSignature.java @@ -0,0 +1,90 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.interactive.form; + +import org.pdfbox.cos.COSDictionary; + +import java.io.IOException; + +/** + * A class for handling the PDF field as a signature. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.3 $ + */ +public class PDSignature extends PDField +{ + + /** + * @see org.pdfbox.pdmodel.field.PDField#COSField(org.pdfbox.cos.COSDictionary) + * + * @param theAcroForm The acroForm for this field. + * @param field The dictionary for the signature. + */ + public PDSignature( PDAcroForm theAcroForm, COSDictionary field) + { + super(theAcroForm,field); + } + + /** + * @see as.interactive.pdf.form.cos.COSField#setValue(java.lang.String) + * + * @param value The new value for the field. + * + * @throws IOException If there is an error creating the appearance stream. + */ + public void setValue(String value) throws IOException + { + throw new RuntimeException( "Not yet implemented" ); + } + + /** + * @see as.interactive.pdf.form.cos.COSField#setValue(java.lang.String) + * + * @return The string value of this field. + * + * @throws IOException If there is an error creating the appearance stream. + */ + public String getValue() throws IOException + { + throw new RuntimeException( "Not yet implemented" ); + } + + /** + * Return a string rep of this object. + * + * @return A string rep of this object. + */ + public String toString() + { + return "PDSignature"; + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/interactive/form/PDTextbox.java b/src/main/java/org/pdfbox/pdmodel/interactive/form/PDTextbox.java new file mode 100644 index 0000000..fd9550e --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/interactive/form/PDTextbox.java @@ -0,0 +1,64 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.interactive.form; + +import org.pdfbox.cos.COSDictionary; + +/** + * A class for handling the PDF field as a textbox. + * + * @author sug + * @version $Revision: 1.9 $ + */ +public class PDTextbox extends PDVariableText +{ + + /** + * @see PDField#PDField(PDAcroForm,COSDictionary) + * + * @param theAcroForm The acroform. + */ + public PDTextbox( PDAcroForm theAcroForm ) + { + super( theAcroForm ); + } + + /** + * @see org.pdfbox.pdmodel.interactive.form.PDField#PDField(PDAcroForm,COSDictionary) + * + * @param theAcroForm The acroForm for this field. + * @param field The field's dictionary. + */ + public PDTextbox( PDAcroForm theAcroForm, COSDictionary field) + { + super( theAcroForm, field); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/interactive/form/PDUnknownField.java b/src/main/java/org/pdfbox/pdmodel/interactive/form/PDUnknownField.java new file mode 100644 index 0000000..806b5f5 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/interactive/form/PDUnknownField.java @@ -0,0 +1,72 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.interactive.form; + +import java.io.IOException; + +import org.pdfbox.cos.COSDictionary; + +/** + * This class represents a form field with an unknown type. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.3 $ + */ +public class PDUnknownField extends PDField +{ + /** + * @see org.pdfbox.pdmodel.interactive.form.PDField#PDField(PDAcroForm, COSDictionary) + * + * @param theAcroForm The acroForm for this field. + * @param field The field's dictionary. + */ + public PDUnknownField( PDAcroForm theAcroForm, COSDictionary field) + { + super( theAcroForm, field); + } + + /** + * @see org.pdfbox.pdmodel.interactive.form.PDField#setValue(String) + */ + public void setValue(String value) throws IOException + { + //do nothing + } + + /** + * @see org.pdfbox.pdmodel.interactive.form.PDField#getValue() + */ + public String getValue() throws IOException + { + return null; + } + +} diff --git a/src/main/java/org/pdfbox/pdmodel/interactive/form/PDVariableText.java b/src/main/java/org/pdfbox/pdmodel/interactive/form/PDVariableText.java new file mode 100644 index 0000000..7ed5008 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/interactive/form/PDVariableText.java @@ -0,0 +1,324 @@ +/** + * Copyright (c) 2004-2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.interactive.form; + +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSInteger; +import org.pdfbox.cos.COSName; +import org.pdfbox.cos.COSNumber; +import org.pdfbox.cos.COSString; +import org.pdfbox.util.BitFlagHelper; + +import java.io.IOException; + +/** + * A class for handling PDF fields that display text. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.6 $ + */ +public abstract class PDVariableText extends PDField +{ + /** + * A Ff flag. + */ + public static final int FLAG_MULTILINE = 1 << 12; + /** + * A Ff flag. + */ + public static final int FLAG_PASSWORD = 1 << 13; + /** + * A Ff flag. + */ + public static final int FLAG_FILE_SELECT = 1 << 20; + /** + * A Ff flag. + */ + public static final int FLAG_DO_NOT_SPELL_CHECK = 1 << 22; + /** + * A Ff flag. + */ + public static final int FLAG_DO_NOT_SCROLL = 1 << 23; + /** + * A Ff flag. + */ + public static final int FLAG_COMB = 1 << 24; + /** + * A Ff flag. + */ + public static final int FLAG_RICH_TEXT = 1 << 25; + + + /** + * DA Default appearance. + */ + private COSString da; + + private PDAppearance appearance; + + + /** + * A Q value. + */ + public static final int QUADDING_LEFT = 0; + + /** + * A Q value. + */ + public static final int QUADDING_CENTERED = 1; + + /** + * A Q value. + */ + public static final int QUADDING_RIGHT = 2; + + /** + * @see PDField#PDField(PDAcroForm,COSDictionary) + * + * @param theAcroForm The acroform. + */ + public PDVariableText( PDAcroForm theAcroForm ) + { + super( theAcroForm ); + } + + /** + * @see org.pdfbox.pdmodel.interactive.form.PDField#PDField(PDAcroForm,COSDictionary) + * + * @param theAcroForm The acroForm for this field. + * @param field The field's dictionary. + */ + public PDVariableText( PDAcroForm theAcroForm, COSDictionary field) + { + super( theAcroForm, field); + da = (COSString) field.getDictionaryObject(COSName.getPDFName("DA")); + } + + /** + * @see org.pdfbox.pdmodel.interactive.form.PDField#setValue(java.lang.String) + * + * @param value The new value for this text field. + * + * @throws IOException If there is an error calculating the appearance stream. + */ + public void setValue(String value) throws IOException + { + COSString fieldValue = new COSString(value); + getDictionary().setItem( COSName.getPDFName( "V" ), fieldValue ); + + //hmm, not sure what the case where the DV gets set to the field + //value, for now leave blank until we can come up with a case + //where it needs to be in there + //getDictionary().setItem( COSName.getPDFName( "DV" ), fieldValue ); + if(appearance == null) + { + this.appearance = new PDAppearance( getAcroForm(), this ); + } + appearance.setAppearanceValue(value); + } + + /** + * getValue gets the fields value to as a string. + * + * @return The string value of this field. + * + * @throws IOException If there is an error getting the value. + */ + public String getValue() throws IOException + { + return getDictionary().getString( "V" ); + } + + /** + * @return true if the field is multiline + */ + public boolean isMultiline() + { + return BitFlagHelper.getFlag( getDictionary(), "Ff", FLAG_MULTILINE ); + } + + /** + * Set the multiline bit. + * + * @param multiline The value for the multiline. + */ + public void setMultiline( boolean multiline ) + { + BitFlagHelper.setFlag( getDictionary(), "Ff", FLAG_MULTILINE, multiline ); + } + + /** + * @return true if the field is a password field. + */ + public boolean isPassword() + { + return BitFlagHelper.getFlag( getDictionary(), "Ff", FLAG_PASSWORD ); + } + + /** + * Set the password bit. + * + * @param password The value for the password. + */ + public void setPassword( boolean password ) + { + BitFlagHelper.setFlag( getDictionary(), "Ff", FLAG_PASSWORD, password ); + } + + /** + * @return true if the field is a file select field. + */ + public boolean isFileSelect() + { + return BitFlagHelper.getFlag( getDictionary(), "Ff", FLAG_FILE_SELECT ); + } + + /** + * Set the file select bit. + * + * @param fileSelect The value for the fileSelect. + */ + public void setFileSelect( boolean fileSelect ) + { + BitFlagHelper.setFlag( getDictionary(), "Ff", FLAG_FILE_SELECT, fileSelect ); + } + + /** + * @return true if the field is not suppose to spell check. + */ + public boolean doNotSpellCheck() + { + return BitFlagHelper.getFlag( getDictionary(), "Ff", FLAG_DO_NOT_SPELL_CHECK ); + } + + /** + * Set the doNotSpellCheck bit. + * + * @param doNotSpellCheck The value for the doNotSpellCheck. + */ + public void setDoNotSpellCheck( boolean doNotSpellCheck ) + { + BitFlagHelper.setFlag( getDictionary(), "Ff", FLAG_DO_NOT_SPELL_CHECK, doNotSpellCheck ); + } + + /** + * @return true if the field is not suppose to scroll. + */ + public boolean doNotScroll() + { + return BitFlagHelper.getFlag( getDictionary(), "Ff", FLAG_DO_NOT_SCROLL ); + } + + /** + * Set the doNotScroll bit. + * + * @param doNotScroll The value for the doNotScroll. + */ + public void setDoNotScroll( boolean doNotScroll ) + { + BitFlagHelper.setFlag( getDictionary(), "Ff", FLAG_DO_NOT_SCROLL, doNotScroll ); + } + + /** + * @return true if the field is not suppose to comb the text display. + */ + public boolean shouldComb() + { + return BitFlagHelper.getFlag( getDictionary(), "Ff", FLAG_COMB ); + } + + /** + * Set the comb bit. + * + * @param comb The value for the comb. + */ + public void setComb( boolean comb ) + { + BitFlagHelper.setFlag( getDictionary(), "Ff", FLAG_COMB, comb ); + } + + /** + * @return true if the field is a rich text field. + */ + public boolean isRichText() + { + return BitFlagHelper.getFlag( getDictionary(), "Ff", FLAG_RICH_TEXT ); + } + + /** + * Set the richText bit. + * + * @param richText The value for the richText. + */ + public void setRichText( boolean richText ) + { + BitFlagHelper.setFlag( getDictionary(), "Ff", FLAG_RICH_TEXT, richText ); + } + + /** + * @return the DA element of the dictionary object + */ + protected COSString getDefaultAppearance() + { + return da; + } + + /** + * This will get the 'quadding' or justification of the text to be displayed. + * 0 - Left(default)
    + * 1 - Centered
    + * 2 - Right
    + * Please see the QUADDING_CONSTANTS. + * + * @return The justification of the text strings. + */ + public int getQ() + { + int retval = 0; + COSNumber number = (COSNumber)getDictionary().getDictionaryObject( COSName.getPDFName( "Q" ) ); + if( number != null ) + { + retval = number.intValue(); + } + return retval; + } + + /** + * This will set the quadding/justification of the text. See QUADDING constants. + * + * @param q The new text justification. + */ + public void setQ( int q ) + { + getDictionary().setItem( COSName.getPDFName( "Q" ), new COSInteger( q ) ); + } + +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/interactive/form/package.html b/src/main/java/org/pdfbox/pdmodel/interactive/form/package.html new file mode 100644 index 0000000..36c4b4b --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/interactive/form/package.html @@ -0,0 +1,9 @@ + + + + + + +The interactive package contains classes that deal with interactive annotations such as textfields and buttons. + + diff --git a/src/main/java/org/pdfbox/pdmodel/interactive/pagenavigation/PDThread.java b/src/main/java/org/pdfbox/pdmodel/interactive/pagenavigation/PDThread.java new file mode 100644 index 0000000..5226099 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/interactive/pagenavigation/PDThread.java @@ -0,0 +1,152 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.interactive.pagenavigation; + +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSDictionary; + +import org.pdfbox.pdmodel.PDDocumentInformation; +import org.pdfbox.pdmodel.common.COSObjectable; + +/** + * This a single thread in a PDF document. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.1 $ + */ +public class PDThread implements COSObjectable +{ + + + private COSDictionary thread; + + /** + * Constructor that is used for a preexisting dictionary. + * + * @param t The underlying dictionary. + */ + public PDThread( COSDictionary t ) + { + thread = t; + } + + /** + * Default constructor. + * + */ + public PDThread() + { + thread = new COSDictionary(); + thread.setName( "Type", "Thread" ); + } + + /** + * This will get the underlying dictionary that this object wraps. + * + * @return The underlying info dictionary. + */ + public COSDictionary getDictionary() + { + return thread; + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSBase getCOSObject() + { + return thread; + } + + /** + * Get info about the thread, or null if there is nothing. + * + * @return The thread information. + */ + public PDDocumentInformation getThreadInfo() + { + PDDocumentInformation retval = null; + COSDictionary info = (COSDictionary)thread.getDictionaryObject( "I" ); + if( info != null ) + { + retval = new PDDocumentInformation( info ); + } + + return retval; + } + + /** + * Set the thread info, can be null. + * + * @param info The info dictionary about this thread. + */ + public void setThreadInfo( PDDocumentInformation info ) + { + thread.setItem( "I", info ); + } + + /** + * Get the first bead in the thread, or null if it has not been set yet. This + * is a required field for this object. + * + * @return The first bead in the thread. + */ + public PDThreadBead getFirstBead() + { + PDThreadBead retval = null; + COSDictionary bead = (COSDictionary)thread.getDictionaryObject( "F" ); + if( bead != null ) + { + retval = new PDThreadBead( bead ); + } + + return retval; + } + + /** + * This will set the first bead in the thread. When this is set it will + * also set the thread property of the bead object. + * + * @param bead The first bead in the thread. + */ + public void setFirstBead( PDThreadBead bead ) + { + if( bead != null ) + { + bead.setThread( this ); + } + thread.setItem( "F", bead ); + } + + +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/interactive/pagenavigation/PDThreadBead.java b/src/main/java/org/pdfbox/pdmodel/interactive/pagenavigation/PDThreadBead.java new file mode 100644 index 0000000..547d4bc --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/interactive/pagenavigation/PDThreadBead.java @@ -0,0 +1,234 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.interactive.pagenavigation; + +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSName; + +import org.pdfbox.pdmodel.PDPage; +import org.pdfbox.pdmodel.common.COSObjectable; +import org.pdfbox.pdmodel.common.PDRectangle; + +/** + * This a single bead in a thread in a PDF document. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.3 $ + */ +public class PDThreadBead implements COSObjectable +{ + + + private COSDictionary bead; + + /** + * Constructor that is used for a preexisting dictionary. + * + * @param b The underlying dictionary. + */ + public PDThreadBead( COSDictionary b ) + { + bead = b; + } + + /** + * Default constructor. + * + */ + public PDThreadBead() + { + bead = new COSDictionary(); + bead.setName( "Type", "Bead" ); + setNextBead( this ); + setPreviousBead( this ); + } + + /** + * This will get the underlying dictionary that this object wraps. + * + * @return The underlying info dictionary. + */ + public COSDictionary getDictionary() + { + return bead; + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSBase getCOSObject() + { + return bead; + } + + /** + * This will get the thread that this bead is part of. This is only required + * for the first bead in a thread, so other beads 'may' return null. + * + * @return The thread that this bead is part of. + */ + public PDThread getThread() + { + PDThread retval = null; + COSDictionary dic = (COSDictionary)bead.getDictionaryObject( "T" ); + if( dic != null ) + { + retval = new PDThread( dic ); + } + return retval; + } + + /** + * Set the thread that this bead is part of. This is only required for the + * first bead in a thread. Note: This property is set for you by the PDThread.setFirstBead() method. + * + * @param thread The thread that this bead is part of. + */ + public void setThread( PDThread thread ) + { + bead.setItem( "T", thread ); + } + + /** + * This will get the next bead. If this bead is the last bead in the list then this + * will return the first bead. + * + * @return The next bead in the list or the first bead if this is the last bead. + */ + public PDThreadBead getNextBead() + { + return new PDThreadBead( (COSDictionary) bead.getDictionaryObject( "N" ) ); + } + + /** + * Set the next bead in the thread. + * + * @param next The next bead. + */ + protected void setNextBead( PDThreadBead next ) + { + bead.setItem( "N", next ); + } + + /** + * This will get the previous bead. If this bead is the first bead in the list then this + * will return the last bead. + * + * @return The previous bead in the list or the last bead if this is the first bead. + */ + public PDThreadBead getPreviousBead() + { + return new PDThreadBead( (COSDictionary) bead.getDictionaryObject( "V" ) ); + } + + /** + * Set the previous bead in the thread. + * + * @param previous The previous bead. + */ + protected void setPreviousBead( PDThreadBead previous ) + { + bead.setItem( "V", previous ); + } + + /** + * Append a bead after this bead. This will correctly set the next/previous beads in the + * linked list. + * + * @param append The bead to insert. + */ + public void appendBead( PDThreadBead append ) + { + PDThreadBead nextBead = getNextBead(); + nextBead.setPreviousBead( append ); + append.setNextBead( nextBead ); + setNextBead( append ); + append.setPreviousBead( this ); + } + + /** + * Get the page that this bead is part of. + * + * @return The page that this bead is part of. + */ + public PDPage getPage() + { + PDPage page = null; + COSDictionary dic = (COSDictionary)bead.getDictionaryObject( "P" ); + if( dic != null ) + { + page = new PDPage( dic ); + } + return page; + } + + /** + * Set the page that this bead is part of. This is a required property and must be + * set when creating a new bead. The PDPage object also has a list of beads in the natural + * reading order. It is recommended that you add this object to that list as well. + * + * @param page The page that this bead is on. + */ + public void setPage( PDPage page ) + { + bead.setItem( "P", page ); + } + + /** + * The rectangle on the page that this bead is part of. + * + * @return The part of the page that this bead covers. + */ + public PDRectangle getRectangle() + { + PDRectangle rect = null; + COSArray array = (COSArray)bead.getDictionaryObject( COSName.R ); + if( array != null ) + { + rect = new PDRectangle( array ); + } + return rect; + } + + /** + * Set the rectangle on the page that this bead covers. + * + * @param rect The portion of the page that this bead covers. + */ + public void setRectangle( PDRectangle rect ) + { + bead.setItem( COSName.R, rect ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/interactive/pagenavigation/package.html b/src/main/java/org/pdfbox/pdmodel/interactive/pagenavigation/package.html new file mode 100644 index 0000000..5fb1b88 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/interactive/pagenavigation/package.html @@ -0,0 +1,9 @@ + + + + + + +A package to allow provide access to PDF page navigation functionality. + + diff --git a/src/main/java/org/pdfbox/pdmodel/interactive/viewerpreferences/PDViewerPreferences.java b/src/main/java/org/pdfbox/pdmodel/interactive/viewerpreferences/PDViewerPreferences.java new file mode 100644 index 0000000..d9958e6 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/interactive/viewerpreferences/PDViewerPreferences.java @@ -0,0 +1,365 @@ +/** + * Copyright (c) 2003-2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.interactive.viewerpreferences; + +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSDictionary; + +import org.pdfbox.pdmodel.common.COSObjectable; + +/** + * This is the document viewing preferences. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.2 $ + */ +public class PDViewerPreferences implements COSObjectable +{ + /** + * From PDF Reference: "Neither document outline nor thumbnail images visible". + */ + public static final String NON_FULL_SCREEN_PAGE_MODE_USE_NONE = "UseNone"; + /** + * From PDF Reference: "Document outline visible". + */ + public static final String NON_FULL_SCREEN_PAGE_MODE_USE_OUTLINES = "UseOutlines"; + /** + * From PDF Reference: "Thumbnail images visible". + */ + public static final String NON_FULL_SCREEN_PAGE_MODE_USE_THUMBS = "UseThumbs"; + /** + * From PDF Reference: "Optional content group panel visible". + */ + public static final String NON_FULL_SCREEN_PAGE_MODE_USE_OPTIONAL_CONTENT = "UseOC"; + + /** + * Reading direction. + */ + public static final String READING_DIRECTION_L2R = "L2R"; + /** + * Reading direction. + */ + public static final String READING_DIRECTION_R2L = "R2L"; + + /** + * Boundary constant. + */ + public static final String BOUNDARY_MEDIA_BOX = "MediaBox"; + /** + * Boundary constant. + */ + public static final String BOUNDARY_CROP_BOX = "CropBox"; + /** + * Boundary constant. + */ + public static final String BOUNDARY_BLEED_BOX = "BleedBox"; + /** + * Boundary constant. + */ + public static final String BOUNDARY_TRIM_BOX = "TrimBox"; + /** + * Boundary constant. + */ + public static final String BOUNDARY_ART_BOX = "ArtBox"; + + + private COSDictionary prefs; + + /** + * Constructor that is used for a preexisting dictionary. + * + * @param dic The underlying dictionary. + */ + public PDViewerPreferences( COSDictionary dic ) + { + prefs = dic; + } + + /** + * This will get the underlying dictionary that this object wraps. + * + * @return The underlying info dictionary. + */ + public COSDictionary getDictionary() + { + return prefs; + } + + /** + * Convert this standard java object to a COS object. + * + * @return The cos object that matches this Java object. + */ + public COSBase getCOSObject() + { + return prefs; + } + + /** + * Get the toolbar preference. + * + * @return the toolbar preference. + */ + public boolean hideToolbar() + { + return prefs.getBoolean( "HideToolbar", false ); + } + + /** + * Set the toolbar preference. + * + * @param value Set the toolbar preference. + */ + public void setHideToolbar( boolean value ) + { + prefs.setBoolean( "HideToolbar", value ); + } + + /** + * Get the menubar preference. + * + * @return the menubar preference. + */ + public boolean hideMenubar() + { + return prefs.getBoolean( "HideMenubar", false ); + } + + /** + * Set the menubar preference. + * + * @param value Set the menubar preference. + */ + public void setHideMenubar( boolean value ) + { + prefs.setBoolean( "HideMenubar", value ); + } + + /** + * Get the window UI preference. + * + * @return the window UI preference. + */ + public boolean hideWindowUI() + { + return prefs.getBoolean( "HideWindowUI", false ); + } + + /** + * Set the window UI preference. + * + * @param value Set the window UI preference. + */ + public void setHideWindowUI( boolean value ) + { + prefs.setBoolean( "HideWindowUI", value ); + } + + /** + * Get the fit window preference. + * + * @return the fit window preference. + */ + public boolean fitWindow() + { + return prefs.getBoolean( "FitWindow", false ); + } + + /** + * Set the fit window preference. + * + * @param value Set the fit window preference. + */ + public void setFitWindow( boolean value ) + { + prefs.setBoolean( "FitWindow", value ); + } + + /** + * Get the center window preference. + * + * @return the center window preference. + */ + public boolean centerWindow() + { + return prefs.getBoolean( "CenterWindow", false ); + } + + /** + * Set the center window preference. + * + * @param value Set the center window preference. + */ + public void setCenterWindow( boolean value ) + { + prefs.setBoolean( "CenterWindow", value ); + } + + /** + * Get the display doc title preference. + * + * @return the display doc title preference. + */ + public boolean displayDocTitle() + { + return prefs.getBoolean( "DisplayDocTitle", false ); + } + + /** + * Set the display doc title preference. + * + * @param value Set the display doc title preference. + */ + public void setDisplayDocTitle( boolean value ) + { + prefs.setBoolean( "DisplayDocTitle", value ); + } + + /** + * Get the non full screen page mode preference. + * + * @return the non full screen page mode preference. + */ + public String getNonFullScreenPageMode() + { + return prefs.getNameAsString( "NonFullScreenPageMode", NON_FULL_SCREEN_PAGE_MODE_USE_NONE); + } + + /** + * Set the non full screen page mode preference. + * + * @param value Set the non full screen page mode preference. + */ + public void setNonFullScreenPageMode( String value ) + { + prefs.setName( "NonFullScreenPageMode", value ); + } + + /** + * Get the reading direction preference. + * + * @return the reading direction preference. + */ + public String getReadingDirection() + { + return prefs.getNameAsString( "Direction", READING_DIRECTION_L2R); + } + + /** + * Set the reading direction preference. + * + * @param value Set the reading direction preference. + */ + public void setReadingDirection( String value ) + { + prefs.setName( "Direction", value ); + } + + /** + * Get the ViewArea preference. See BOUNDARY_XXX constants. + * + * @return the ViewArea preference. + */ + public String getViewArea() + { + return prefs.getNameAsString( "ViewArea", BOUNDARY_CROP_BOX); + } + + /** + * Set the ViewArea preference. See BOUNDARY_XXX constants. + * + * @param value Set the ViewArea preference. + */ + public void setViewArea( String value ) + { + prefs.setName( "ViewArea", value ); + } + + /** + * Get the ViewClip preference. See BOUNDARY_XXX constants. + * + * @return the ViewClip preference. + */ + public String getViewClip() + { + return prefs.getNameAsString( "ViewClip", BOUNDARY_CROP_BOX); + } + + /** + * Set the ViewClip preference. See BOUNDARY_XXX constants. + * + * @param value Set the ViewClip preference. + */ + public void setViewClip( String value ) + { + prefs.setName( "ViewClip", value ); + } + + /** + * Get the PrintArea preference. See BOUNDARY_XXX constants. + * + * @return the PrintArea preference. + */ + public String getPrintArea() + { + return prefs.getNameAsString( "PrintArea", BOUNDARY_CROP_BOX); + } + + /** + * Set the PrintArea preference. See BOUNDARY_XXX constants. + * + * @param value Set the PrintArea preference. + */ + public void setPrintArea( String value ) + { + prefs.setName( "PrintArea", value ); + } + + /** + * Get the PrintClip preference. See BOUNDARY_XXX constants. + * + * @return the PrintClip preference. + */ + public String getPrintClip() + { + return prefs.getNameAsString( "PrintClip", BOUNDARY_CROP_BOX); + } + + /** + * Set the PrintClip preference. See BOUNDARY_XXX constants. + * + * @param value Set the PrintClip preference. + */ + public void setPrintClip( String value ) + { + prefs.setName( "PrintClip", value ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/interactive/viewerpreferences/package.html b/src/main/java/org/pdfbox/pdmodel/interactive/viewerpreferences/package.html new file mode 100644 index 0000000..310d6b4 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/interactive/viewerpreferences/package.html @@ -0,0 +1,9 @@ + + + + + + +A package to allow access to document viewing preferences. + + diff --git a/src/main/java/org/pdfbox/pdmodel/package.html b/src/main/java/org/pdfbox/pdmodel/package.html new file mode 100644 index 0000000..85bbe62 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/package.html @@ -0,0 +1,9 @@ + + + + + + +The PDModel package represents a high level API for creating and manipulating PDF documents. + + diff --git a/src/main/java/org/pdfbox/pdmodel/text/PDTextState.java b/src/main/java/org/pdfbox/pdmodel/text/PDTextState.java new file mode 100644 index 0000000..45e9516 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/text/PDTextState.java @@ -0,0 +1,286 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.text; + +import org.pdfbox.pdmodel.font.PDFont; + +/** + * This class will hold the current state of the text parameters when executing a + * content stream. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.3 $ + */ +public class PDTextState implements Cloneable +{ + /** + * See PDF Reference 1.5 Table 5.3. + */ + public static final int RENDERING_MODE_FILL_TEXT = 0; + /** + * See PDF Reference 1.5 Table 5.3. + */ + public static final int RENDERING_MODE_STROKE_TEXT = 1; + /** + * See PDF Reference 1.5 Table 5.3. + */ + public static final int RENDERING_MODE_FILL_THEN_STROKE_TEXT = 2; + /** + * See PDF Reference 1.5 Table 5.3. + */ + public static final int RENDERING_MODE_NEITHER_FILL_NOR_STROKE_TEXT = 3; + /** + * See PDF Reference 1.5 Table 5.3. + */ + public static final int RENDERING_MODE_FILL_TEXT_AND_ADD_TO_PATH_FOR_CLIPPING = 4; + /** + * See PDF Reference 1.5 Table 5.3. + */ + public static final int RENDERING_MODE_STROKE_TEXT_AND_ADD_TO_PATH_FOR_CLIPPING = 5; + /** + * See PDF Reference 1.5 Table 5.3. + */ + public static final int RENDERING_MODE_FILL_THEN_STROKE_TEXT_AND_ADD_TO_PATH_FOR_CLIPPING = 6; + /** + * See PDF Reference 1.5 Table 5.3. + */ + public static final int RENDERING_MODE_ADD_TEXT_TO_PATH_FOR_CLIPPING = 7; + + + //these are set default according to PDF Reference 1.5 section 5.2 + private float characterSpacing = 0; + private float wordSpacing = 0; + private float horizontalScaling = 100; + private float leading = 0; + private PDFont font; + private float fontSize; + private int renderingMode = 0; + private float rise = 0; + private boolean knockout = true; + + /** + * Get the value of the characterSpacing. + * + * @return The current characterSpacing. + */ + public float getCharacterSpacing() + { + return characterSpacing; + } + + /** + * Set the value of the characterSpacing. + * + * @param value The characterSpacing. + */ + public void setCharacterSpacing(float value) + { + characterSpacing = value; + } + + /** + * Get the value of the wordSpacing. + * + * @return The wordSpacing. + */ + public float getWordSpacing() + { + return wordSpacing; + } + + /** + * Set the value of the wordSpacing. + * + * @param value The wordSpacing. + */ + public void setWordSpacing(float value) + { + wordSpacing = value; + } + + /** + * Get the value of the horizontalScaling. The default is 100. This value + * is the percentage value 0-100 and not 0-1. So for mathematical operations + * you will probably need to divide by 100 first. + * + * @return The horizontalScaling. + */ + public float getHorizontalScalingPercent() + { + return horizontalScaling; + } + + /** + * Set the value of the horizontalScaling. + * + * @param value The horizontalScaling. + */ + public void setHorizontalScalingPercent(float value) + { + horizontalScaling = value; + } + + /** + * Get the value of the leading. + * + * @return The leading. + */ + public float getLeading() + { + return leading; + } + + /** + * Set the value of the leading. + * + * @param value The leading. + */ + public void setLeading(float value) + { + leading = value; + } + + /** + * Get the value of the font. + * + * @return The font. + */ + public PDFont getFont() + { + return font; + } + + /** + * Set the value of the font. + * + * @param value The font. + */ + public void setFont(PDFont value) + { + font = value; + } + + /** + * Get the value of the fontSize. + * + * @return The fontSize. + */ + public float getFontSize() + { + return fontSize; + } + + /** + * Set the value of the fontSize. + * + * @param value The fontSize. + */ + public void setFontSize(float value) + { + fontSize = value; + } + + /** + * Get the value of the renderingMode. + * + * @return The renderingMode. + */ + public int getRenderingMode() + { + return renderingMode; + } + + /** + * Set the value of the renderingMode. + * + * @param value The renderingMode. + */ + public void setRenderingMode(int value) + { + renderingMode = value; + } + + /** + * Get the value of the rise. + * + * @return The rise. + */ + public float getRise() + { + return rise; + } + + /** + * Set the value of the rise. + * + * @param value The rise. + */ + public void setRise(float value) + { + rise = value; + } + + /** + * Get the value of the knockout. + * + * @return The knockout. + */ + public boolean getKnockoutFlag() + { + return knockout; + } + + /** + * Set the value of the knockout. + * + * @param value The knockout. + */ + public void setKnockoutFlag(boolean value) + { + knockout = value; + } + + /** + * @see Object#clone() + */ + public Object clone() + { + try + { + return super.clone(); + } + catch (CloneNotSupportedException ignore) + { + //ignore + } + return null; + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/text/package.html b/src/main/java/org/pdfbox/pdmodel/text/package.html new file mode 100644 index 0000000..50bb7c5 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/text/package.html @@ -0,0 +1,9 @@ + + + + + + +The PDModel text package deals with text states, operations, and parameters within the PDF document. + + \ No newline at end of file diff --git a/src/main/java/org/pdfbox/persistence/util/COSHEXTable.java b/src/main/java/org/pdfbox/persistence/util/COSHEXTable.java new file mode 100644 index 0000000..b483213 --- /dev/null +++ b/src/main/java/org/pdfbox/persistence/util/COSHEXTable.java @@ -0,0 +1,566 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.persistence.util; + +/** + * helper type for faster mapping of bytes to their hex equivalent. + * + * @author Michael Traut + * @version $Revision: 1.4 $ + */ +public final class COSHEXTable +{ + /** + * ASCII byte values for the hex strings. + */ + public static final byte[][] TABLE = + { + "00".getBytes(), + "01".getBytes(), + "02".getBytes(), + "03".getBytes(), + "04".getBytes(), + "05".getBytes(), + "06".getBytes(), + "07".getBytes(), + "08".getBytes(), + "09".getBytes(), + "0A".getBytes(), + "0B".getBytes(), + "0C".getBytes(), + "0D".getBytes(), + "0E".getBytes(), + "0F".getBytes(), + "10".getBytes(), + "11".getBytes(), + "12".getBytes(), + "13".getBytes(), + "14".getBytes(), + "15".getBytes(), + "16".getBytes(), + "17".getBytes(), + "18".getBytes(), + "19".getBytes(), + "1A".getBytes(), + "1B".getBytes(), + "1C".getBytes(), + "1D".getBytes(), + "1E".getBytes(), + "1F".getBytes(), + "20".getBytes(), + "21".getBytes(), + "22".getBytes(), + "23".getBytes(), + "24".getBytes(), + "25".getBytes(), + "26".getBytes(), + "27".getBytes(), + "28".getBytes(), + "29".getBytes(), + "2A".getBytes(), + "2B".getBytes(), + "2C".getBytes(), + "2D".getBytes(), + "2E".getBytes(), + "2F".getBytes(), + "30".getBytes(), + "31".getBytes(), + "32".getBytes(), + "33".getBytes(), + "34".getBytes(), + "35".getBytes(), + "36".getBytes(), + "37".getBytes(), + "38".getBytes(), + "39".getBytes(), + "3A".getBytes(), + "3B".getBytes(), + "3C".getBytes(), + "3D".getBytes(), + "3E".getBytes(), + "3F".getBytes(), + "40".getBytes(), + "41".getBytes(), + "42".getBytes(), + "43".getBytes(), + "44".getBytes(), + "45".getBytes(), + "46".getBytes(), + "47".getBytes(), + "48".getBytes(), + "49".getBytes(), + "4A".getBytes(), + "4B".getBytes(), + "4C".getBytes(), + "4D".getBytes(), + "4E".getBytes(), + "4F".getBytes(), + "50".getBytes(), + "51".getBytes(), + "52".getBytes(), + "53".getBytes(), + "54".getBytes(), + "55".getBytes(), + "56".getBytes(), + "57".getBytes(), + "58".getBytes(), + "59".getBytes(), + "5A".getBytes(), + "5B".getBytes(), + "5C".getBytes(), + "5D".getBytes(), + "5E".getBytes(), + "5F".getBytes(), + "60".getBytes(), + "61".getBytes(), + "62".getBytes(), + "63".getBytes(), + "64".getBytes(), + "65".getBytes(), + "66".getBytes(), + "67".getBytes(), + "68".getBytes(), + "69".getBytes(), + "6A".getBytes(), + "6B".getBytes(), + "6C".getBytes(), + "6D".getBytes(), + "6E".getBytes(), + "6F".getBytes(), + "70".getBytes(), + "71".getBytes(), + "72".getBytes(), + "73".getBytes(), + "74".getBytes(), + "75".getBytes(), + "76".getBytes(), + "77".getBytes(), + "78".getBytes(), + "79".getBytes(), + "7A".getBytes(), + "7B".getBytes(), + "7C".getBytes(), + "7D".getBytes(), + "7E".getBytes(), + "7F".getBytes(), + "80".getBytes(), + "81".getBytes(), + "82".getBytes(), + "83".getBytes(), + "84".getBytes(), + "85".getBytes(), + "86".getBytes(), + "87".getBytes(), + "88".getBytes(), + "89".getBytes(), + "8A".getBytes(), + "8B".getBytes(), + "8C".getBytes(), + "8D".getBytes(), + "8E".getBytes(), + "8F".getBytes(), + "90".getBytes(), + "91".getBytes(), + "92".getBytes(), + "93".getBytes(), + "94".getBytes(), + "95".getBytes(), + "96".getBytes(), + "97".getBytes(), + "98".getBytes(), + "99".getBytes(), + "9A".getBytes(), + "9B".getBytes(), + "9C".getBytes(), + "9D".getBytes(), + "9E".getBytes(), + "9F".getBytes(), + "A0".getBytes(), + "A1".getBytes(), + "A2".getBytes(), + "A3".getBytes(), + "A4".getBytes(), + "A5".getBytes(), + "A6".getBytes(), + "A7".getBytes(), + "A8".getBytes(), + "A9".getBytes(), + "AA".getBytes(), + "AB".getBytes(), + "AC".getBytes(), + "AD".getBytes(), + "AE".getBytes(), + "AF".getBytes(), + "B0".getBytes(), + "B1".getBytes(), + "B2".getBytes(), + "B3".getBytes(), + "B4".getBytes(), + "B5".getBytes(), + "B6".getBytes(), + "B7".getBytes(), + "B8".getBytes(), + "B9".getBytes(), + "BA".getBytes(), + "BB".getBytes(), + "BC".getBytes(), + "BD".getBytes(), + "BE".getBytes(), + "BF".getBytes(), + "C0".getBytes(), + "C1".getBytes(), + "C2".getBytes(), + "C3".getBytes(), + "C4".getBytes(), + "C5".getBytes(), + "C6".getBytes(), + "C7".getBytes(), + "C8".getBytes(), + "C9".getBytes(), + "CA".getBytes(), + "CB".getBytes(), + "CC".getBytes(), + "CD".getBytes(), + "CE".getBytes(), + "CF".getBytes(), + "D0".getBytes(), + "D1".getBytes(), + "D2".getBytes(), + "D3".getBytes(), + "D4".getBytes(), + "D5".getBytes(), + "D6".getBytes(), + "D7".getBytes(), + "D8".getBytes(), + "D9".getBytes(), + "DA".getBytes(), + "DB".getBytes(), + "DC".getBytes(), + "DD".getBytes(), + "DE".getBytes(), + "DF".getBytes(), + "E0".getBytes(), + "E1".getBytes(), + "E2".getBytes(), + "E3".getBytes(), + "E4".getBytes(), + "E5".getBytes(), + "E6".getBytes(), + "E7".getBytes(), + "E8".getBytes(), + "E9".getBytes(), + "EA".getBytes(), + "EB".getBytes(), + "EC".getBytes(), + "ED".getBytes(), + "EE".getBytes(), + "EF".getBytes(), + "F0".getBytes(), + "F1".getBytes(), + "F2".getBytes(), + "F3".getBytes(), + "F4".getBytes(), + "F5".getBytes(), + "F6".getBytes(), + "F7".getBytes(), + "F8".getBytes(), + "F9".getBytes(), + "FA".getBytes(), + "FB".getBytes(), + "FC".getBytes(), + "FD".getBytes(), + "FE".getBytes(), + "FF".getBytes() + }; + + /** + * ASCII byte values for the hex strings. + */ + public static final String[] HEX_TABLE = + { + "00", + "01", + "02", + "03", + "04", + "05", + "06", + "07", + "08", + "09", + "0A", + "0B", + "0C", + "0D", + "0E", + "0F", + "10", + "11", + "12", + "13", + "14", + "15", + "16", + "17", + "18", + "19", + "1A", + "1B", + "1C", + "1D", + "1E", + "1F", + "20", + "21", + "22", + "23", + "24", + "25", + "26", + "27", + "28", + "29", + "2A", + "2B", + "2C", + "2D", + "2E", + "2F", + "30", + "31", + "32", + "33", + "34", + "35", + "36", + "37", + "38", + "39", + "3A", + "3B", + "3C", + "3D", + "3E", + "3F", + "40", + "41", + "42", + "43", + "44", + "45", + "46", + "47", + "48", + "49", + "4A", + "4B", + "4C", + "4D", + "4E", + "4F", + "50", + "51", + "52", + "53", + "54", + "55", + "56", + "57", + "58", + "59", + "5A", + "5B", + "5C", + "5D", + "5E", + "5F", + "60", + "61", + "62", + "63", + "64", + "65", + "66", + "67", + "68", + "69", + "6A", + "6B", + "6C", + "6D", + "6E", + "6F", + "70", + "71", + "72", + "73", + "74", + "75", + "76", + "77", + "78", + "79", + "7A", + "7B", + "7C", + "7D", + "7E", + "7F", + "80", + "81", + "82", + "83", + "84", + "85", + "86", + "87", + "88", + "89", + "8A", + "8B", + "8C", + "8D", + "8E", + "8F", + "90", + "91", + "92", + "93", + "94", + "95", + "96", + "97", + "98", + "99", + "9A", + "9B", + "9C", + "9D", + "9E", + "9F", + "A0", + "A1", + "A2", + "A3", + "A4", + "A5", + "A6", + "A7", + "A8", + "A9", + "AA", + "AB", + "AC", + "AD", + "AE", + "AF", + "B0", + "B1", + "B2", + "B3", + "B4", + "B5", + "B6", + "B7", + "B8", + "B9", + "BA", + "BB", + "BC", + "BD", + "BE", + "BF", + "C0", + "C1", + "C2", + "C3", + "C4", + "C5", + "C6", + "C7", + "C8", + "C9", + "CA", + "CB", + "CC", + "CD", + "CE", + "CF", + "D0", + "D1", + "D2", + "D3", + "D4", + "D5", + "D6", + "D7", + "D8", + "D9", + "DA", + "DB", + "DC", + "DD", + "DE", + "DF", + "E0", + "E1", + "E2", + "E3", + "E4", + "E5", + "E6", + "E7", + "E8", + "E9", + "EA", + "EB", + "EC", + "ED", + "EE", + "EF", + "F0", + "F1", + "F2", + "F3", + "F4", + "F5", + "F6", + "F7", + "F8", + "F9", + "FA", + "FB", + "FC", + "FD", + "FE", + "FF" + }; +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/persistence/util/COSObjectKey.java b/src/main/java/org/pdfbox/persistence/util/COSObjectKey.java new file mode 100644 index 0000000..4a4d778 --- /dev/null +++ b/src/main/java/org/pdfbox/persistence/util/COSObjectKey.java @@ -0,0 +1,131 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.persistence.util; + +import org.pdfbox.cos.COSObject; + +/** + * object representing the physical reference to an indirect pdf object. + * + * @author Michael Traut + * @version $Revision: 1.4 $ + */ + +public class COSObjectKey +{ + private long number; + private long generation; + + /** + * PDFObjectKey constructor comment. + * + * @param object The object that this key will represent. + */ + public COSObjectKey(COSObject object) + { + this( object.getObjectNumber().longValue(), object.getGenerationNumber().longValue() ); + } + + /** + * PDFObjectKey constructor comment. + * + * @param num The object number. + * @param gen The object generation number. + */ + public COSObjectKey(long num, long gen) + { + setNumber(num); + setGeneration(gen); + } + + /** + * @see Object#equals( Object ) + */ + public boolean equals(Object obj) + { + return (obj instanceof COSObjectKey) && + ((COSObjectKey)obj).getNumber() == getNumber() && + ((COSObjectKey)obj).getGeneration() == getGeneration(); + } + + /** + * This will get the generation number. + * + * @return The objects generation number. + */ + public long getGeneration() + { + return generation; + } + /** + * This will get the objects id. + * + * @return The object's id. + */ + public long getNumber() + { + return number; + } + + /** + * @see Object#hashCode() + */ + public int hashCode() + { + return (int)(number + generation); + } + /** + * This will set the objects generation number. + * + * @param newGeneration The objects generation number. + */ + public void setGeneration(long newGeneration) + { + generation = newGeneration; + } + /** + * This will set the objects id. + * + * @param newNumber The objects number. + */ + public void setNumber(long newNumber) + { + number = newNumber; + } + + /** + * @see Object#toString() + */ + public String toString() + { + return "" + getNumber() + " " + getGeneration() + " R"; + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/persistence/util/package.html b/src/main/java/org/pdfbox/persistence/util/package.html new file mode 100644 index 0000000..fb8a0f8 --- /dev/null +++ b/src/main/java/org/pdfbox/persistence/util/package.html @@ -0,0 +1,9 @@ + + + + + + +These are utilities used by the persistence layer. + + diff --git a/src/main/java/org/pdfbox/pfb/PfbParser.java b/src/main/java/org/pdfbox/pfb/PfbParser.java new file mode 100644 index 0000000..ab069d6 --- /dev/null +++ b/src/main/java/org/pdfbox/pfb/PfbParser.java @@ -0,0 +1,211 @@ +/** + * Copyright (c) 2004-2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ + +package org.pdfbox.pfb; + +import java.io.BufferedInputStream; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.EOFException; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * Parser for a pfb-file. + * + * @author Michael Niedermair + * @version $Revision: 1.3 $ + */ +public class PfbParser +{ + /** + * the pdf header length. + * (start-marker (1 byte), ascii-/binary-marker (1 byte), size (4 byte)) + * 3*6 == 18 + */ + private static final int PFB_HEADER_LENGTH = 18; + + /** + * the start marker. + */ + private static final int START_MARKER = 0x80; + + /** + * the ascii marker. + */ + private static final int ASCII_MARKER = 0x01; + + /** + * the binary marker. + */ + private static final int BINARY_MARKER = 0x02; + + /** + * The record types in the pfb-file. + */ + private static final int[] PFB_RECORDS = {ASCII_MARKER, BINARY_MARKER, + ASCII_MARKER}; + + /** + * buffersize. + */ + private static final int BUFFER_SIZE = 0xffff; + + /** + * the parsed pfb-data. + */ + private byte[] pfbdata; + + /** + * the lengths of the records. + */ + private int[] lengths; + + // sample (pfb-file) + // 00000000 80 01 8b 15 00 00 25 21 50 53 2d 41 64 6f 62 65 + // ......%!PS-Adobe + + + /** + * Create a new object. + * @param filename the file name + * @throws IOException if an IO-error occurs. + */ + public PfbParser(final String filename) throws IOException + { + this( new BufferedInputStream(new FileInputStream(filename),BUFFER_SIZE) ); + } + + /** + * Create a new object. + * @param in The input. + * @throws IOException if an IO-error occurs. + */ + public PfbParser(final InputStream in) throws IOException + { + byte[] pfb = readPfbInput(in); + parsePfb(pfb); + } + + /** + * Parse the pfb-array. + * @param pfb The pfb-Array + * @throws IOException in an IO-error occurs. + */ + private void parsePfb(final byte[] pfb) throws IOException + { + + ByteArrayInputStream in = new ByteArrayInputStream(pfb); + pfbdata = new byte[pfb.length - PFB_HEADER_LENGTH]; + lengths = new int[PFB_RECORDS.length]; + int pointer = 0; + for (int records = 0; records < PFB_RECORDS.length; records++) + { + if (in.read() != START_MARKER) + { + throw new IOException("Start marker missing"); + } + + if (in.read() != PFB_RECORDS[records]) + { + throw new IOException("Incorrect record type"); + } + + int size = in.read(); + size += in.read() << 8; + size += in.read() << 16; + size += in.read() << 24; + lengths[records] = size; + int got = in.read(pfbdata, pointer, size); + if (got < 0) + { + throw new EOFException(); + } + pointer += got; + } + } + + /** + * Read the pdf input. + * @param in The input. + * @return Returns the pdf-array. + * @throws IOException if an IO-error occurs. + */ + private byte[] readPfbInput(final InputStream in) throws IOException + { + // copy into an array + ByteArrayOutputStream out = new ByteArrayOutputStream(); + byte[] tmpbuf = new byte[BUFFER_SIZE]; + int amountRead = -1; + while ((amountRead = in.read(tmpbuf)) != -1) + { + out.write(tmpbuf, 0, amountRead); + } + return out.toByteArray(); + } + + /** + * Returns the lengths. + * @return Returns the lengths. + */ + public int[] getLengths() + { + return lengths; + } + + /** + * Returns the pfbdata. + * @return Returns the pfbdata. + */ + public byte[] getPfbdata() + { + return pfbdata; + } + + /** + * Returns the pfb data as stream. + * @return Returns the pfb data as stream. + */ + public InputStream getInputStream() + { + return new ByteArrayInputStream(pfbdata); + } + + /** + * Returns the size of the pfb-data. + * @return Returns the size of the pfb-data. + */ + public int size() + { + return pfbdata.length; + } +} diff --git a/src/main/java/org/pdfbox/pfb/package.html b/src/main/java/org/pdfbox/pfb/package.html new file mode 100644 index 0000000..fcc23f0 --- /dev/null +++ b/src/main/java/org/pdfbox/pfb/package.html @@ -0,0 +1,9 @@ + + + + + + +Classes that are used to parse pfb files. + + diff --git a/src/main/java/org/pdfbox/searchengine/lucene/IndexFiles.java b/src/main/java/org/pdfbox/searchengine/lucene/IndexFiles.java new file mode 100644 index 0000000..dd36dd9 --- /dev/null +++ b/src/main/java/org/pdfbox/searchengine/lucene/IndexFiles.java @@ -0,0 +1,308 @@ +package org.pdfbox.searchengine.lucene; + +/* + * This source was originally written as an example for the lucene project. + * It has been modified to use PDFBox as a lucene document creator. + * -Ben Litchfield + * + *==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. 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. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache Lucene" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache Lucene", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR + * ITS 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 software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +import org.apache.lucene.analysis.standard.StandardAnalyzer; + +import org.apache.lucene.demo.HTMLDocument; + +import org.apache.lucene.document.Document; + +import org.apache.lucene.index.IndexReader; +import org.apache.lucene.index.IndexWriter; +import org.apache.lucene.index.Term; +import org.apache.lucene.index.TermEnum; + +import java.util.Arrays; + + +import java.io.File; +import java.io.IOException; + +import java.util.Date; + + +/** + * This is a class that will index some files on a local filesystem. This code + * was modified from a demo that comes with the lucene search engine. + * + * @author Lucene team + * @author Ben Litchfield (ben@csh.rit.edu) + * + * @version $Revision: 1.6 $ + */ +public class IndexFiles +{ + private boolean deleting = false; // true during deletion pass + private IndexReader reader; // existing index + private IndexWriter writer; // new index being built + private TermEnum uidIter; // document id iterator + + /** + * This is the main entry point for the indexer. + * + * @param argv The command line arguments. + */ + public static void main(String[] argv) + { + + String index = "index"; + boolean create = false; + File root = null; + + String usage = "org.pdfbox.searchengine.lucene.IndexFiles [-create] [-index ] "; + + if (argv.length == 0) + { + System.err.println("Usage: " + usage); + return; + } + + for (int i = 0; i < argv.length; i++) + { + if (argv[i].equals("-index")) + { // parse -index option + index = argv[++i]; + } + else if (argv[i].equals("-create")) + { // parse -create option + create = true; + } + else if (i != argv.length-1) + { + System.err.println("Usage: " + usage); + return; + } + else + { + System.out.println( "root=" +argv[i] ); + root = new File(argv[i]); + } + } + IndexFiles indexer = new IndexFiles(); + indexer.index( root, create, index ); + } + + /** + * This will index a directory. + * + * @param root The root directory to start indexing. + * @param create Should we create a new index? + * @param index The name of the index. + */ + public void index( File root, boolean create, String index ) + { + + try + { + Date start = new Date(); + + writer = new IndexWriter(index, new StandardAnalyzer(), create); + writer.maxFieldLength = 1000000; + + if (!create) + { // delete stale docs + deleting = true; + indexDocs(root, index, create); + } + + indexDocs(root, index, create); // add new docs + + System.out.println("Optimizing index..."); + writer.optimize(); + writer.close(); + + Date end = new Date(); + + System.out.print(end.getTime() - start.getTime()); + System.out.println(" total milliseconds"); + + } + catch( Exception e ) + { + e.printStackTrace(); + } + } + + /** + * Walk directory hierarchy in uid order, while keeping uid iterator from + * existing index in sync. Mismatches indicate one of: (a) old documents to + * be deleted; (b) unchanged documents, to be left alone; or (c) new + * documents, to be indexed. + * + * @param file The directory to index. + * @param index The index to add the file to. + * @param create A flag telling if we should create the index. + * + * @throws Exception If there is any error indexing the directory. + */ + private void indexDocs(File file, String index, boolean create) throws Exception + { + if (!create) + { // incrementally update + + reader = IndexReader.open(index); // open existing index + uidIter = reader.terms(new Term("uid", "")); // init uid iterator + + indexDocs(file); + + if (deleting) + { // delete rest of stale docs + while (uidIter.term() != null && uidIter.term().field().equals( "uid" ) ) + { + System.out.println("deleting " + + HTMLDocument.uid2url(uidIter.term().text())); + reader.delete(uidIter.term()); + uidIter.next(); + } + deleting = false; + } + + uidIter.close(); // close uid iterator + reader.close(); // close existing index + + } + else + { + indexDocs(file); + } + } + + + private void indexDocs(File file) throws Exception + { + if (file.isDirectory()) + { // if a directory + String[] files = file.list(); // list its files + Arrays.sort(files); // sort the files + for (int i = 0; i < files.length; i++) // recursively index them + { + indexDocs(new File(file, files[i])); + } + } + else + { + if (uidIter != null) + { + String uid = HTMLDocument.uid(file); // construct uid for doc + + while( uidIter.term() != null && + uidIter.term().field().equals( "uid" ) && + uidIter.term().text().compareTo(uid) < 0) + { + if (deleting) + { // delete stale docs + System.out.println("deleting " + + HTMLDocument.uid2url(uidIter.term().text())); + reader.delete(uidIter.term()); + } + uidIter.next(); + } + if( uidIter.term() != null && + uidIter.term().field().equals( "uid" ) && + uidIter.term().text().compareTo(uid) == 0) + { + System.out.println( "Next uid=" +uidIter ); + uidIter.next(); // keep matching docs + } + } + else + { + try + { + addDocument( file ); + } + catch( IOException e ) + { + //catch exception and move onto the next document + System.out.println( e.getMessage() ); + } + } + } + } + + private void addDocument( File file ) throws IOException, InterruptedException + { + String path = file.getName().toUpperCase(); + Document doc = null; + //Gee, this would be a great place for a command pattern + if( path.endsWith(".HTML") || // index .html files + path.endsWith(".HTM") || // index .htm files + path.endsWith(".TXT")) + { + System.out.println( "Indexing Text document: " + file ); + doc = HTMLDocument.Document(file); + } + else if( path.endsWith( ".PDF" ) ) + { + System.out.println( "Indexing PDF document: " + file ); + doc = LucenePDFDocument.getDocument( file ); + } + else + { + System.out.println( "Skipping " + file ); + } + + if( doc != null ) + { + writer.addDocument(doc); + } + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/searchengine/lucene/LucenePDFDocument.java b/src/main/java/org/pdfbox/searchengine/lucene/LucenePDFDocument.java new file mode 100644 index 0000000..1bb8d0c --- /dev/null +++ b/src/main/java/org/pdfbox/searchengine/lucene/LucenePDFDocument.java @@ -0,0 +1,387 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.searchengine.lucene; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.io.IOException; +import java.io.StringReader; +import java.io.StringWriter; + +import java.net.URL; +import java.net.URLConnection; + +import java.util.Date; + +import org.apache.lucene.document.DateField; +import org.apache.lucene.document.Document; +import org.apache.lucene.document.Field; + +import org.pdfbox.pdmodel.PDDocument; +import org.pdfbox.pdmodel.PDDocumentInformation; + +import org.pdfbox.exceptions.CryptographyException; +import org.pdfbox.exceptions.InvalidPasswordException; + +import org.pdfbox.util.PDFTextStripper; + +/** + * This class is used to create a document for the lucene search engine. + * This should easily plug into the IndexHTML or IndexFiles that comes with + * the lucene project. This class will populate the following fields. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
    Lucene Field NameDescription
    pathFile system path if loaded from a file
    urlURL to PDF document
    contentsEntire contents of PDF document, indexed but not stored
    summaryFirst 500 characters of content
    modifiedThe modified date/time according to the url or path
    uidA unique identifier for the Lucene document.
    CreationDateFrom PDF meta-data if available
    CreatorFrom PDF meta-data if available
    KeywordsFrom PDF meta-data if available
    ModificationDateFrom PDF meta-data if available
    ProducerFrom PDF meta-data if available
    SubjectFrom PDF meta-data if available
    TrappedFrom PDF meta-data if available
    + * + * @author Ben Litchfield + * @version $Revision: 1.18 $ + */ +public final class LucenePDFDocument +{ + private static final char FILE_SEPARATOR = System.getProperty("file.separator").charAt(0); + + + /** + * private constructor because there are only static methods. + */ + private LucenePDFDocument() + { + //utility class should not be instantiated + } + + /** + * This will get a lucene document from a PDF file. + * + * @param is The stream to read the PDF from. + * + * @return The lucene document. + * + * @throws IOException If there is an error parsing or indexing the document. + */ + public static Document getDocument( InputStream is ) throws IOException + { + Document document = new Document(); + addContent( document, is, "" ); + return document; + } + + /** + * This will get a lucene document from a PDF file. + * + * @param file The file to get the document for. + * + * @return The lucene document. + * + * @throws IOException If there is an error parsing or indexing the document. + */ + public static Document getDocument( File file ) throws IOException + { + Document document = new Document(); + + // Add the url as a field named "url". Use an UnIndexed field, so + // that the url is just stored with the document, but is not searchable. + document.add( Field.UnIndexed("path", file.getPath() ) ); + document.add(Field.UnIndexed("url", file.getPath().replace(FILE_SEPARATOR, '/'))); + + // Add the last modified date of the file a field named "modified". Use a + // Keyword field, so that it's searchable, but so that no attempt is made + // to tokenize the field into words. + document.add(Field.Keyword("modified", DateField.timeToString( file.lastModified() ))); + + String uid = file.getPath().replace(FILE_SEPARATOR, '\u0000') + "\u0000" + + DateField.timeToString(file.lastModified() ); + + // Add the uid as a field, so that index can be incrementally maintained. + // This field is not stored with document, it is indexed, but it is not + // tokenized prior to indexing. + document.add(new Field("uid", uid, false, true, false)); + + FileInputStream input = null; + try + { + input = new FileInputStream( file ); + addContent( document, input, file.getPath() ); + } + finally + { + if( input != null ) + { + input.close(); + } + } + + + // return the document + + return document; + } + + /** + * This will get a lucene document from a PDF file. + * + * @param url The file to get the document for. + * + * @return The lucene document. + * + * @throws IOException If there is an error parsing or indexing the document. + */ + public static Document getDocument( URL url ) throws IOException + { + Document document = new Document(); + URLConnection connection = url.openConnection(); + connection.connect(); + // Add the url as a field named "url". Use an UnIndexed field, so + // that the url is just stored with the document, but is not searchable. + document.add( Field.UnIndexed("url", url.toExternalForm() ) ); + + // Add the last modified date of the file a field named "modified". Use a + // Keyword field, so that it's searchable, but so that no attempt is made + // to tokenize the field into words. + document.add(Field.Keyword("modified", DateField.timeToString( connection.getLastModified()))); + + String uid = url.toExternalForm().replace(FILE_SEPARATOR, '\u0000') + "\u0000" + + DateField.timeToString( connection.getLastModified() ); + + // Add the uid as a field, so that index can be incrementally maintained. + // This field is not stored with document, it is indexed, but it is not + // tokenized prior to indexing. + document.add(new Field("uid", uid, false, true, false)); + + InputStream input = null; + try + { + input = connection.getInputStream(); + addContent( document, input,url.toExternalForm() ); + } + finally + { + if( input != null ) + { + input.close(); + } + } + + // return the document + return document; + } + + /** + * This will add the contents to the lucene document. + * + * @param document The document to add the contents to. + * @param is The stream to get the contents from. + * @param documentLocation The location of the document, used just for debug messages. + * + * @throws IOException If there is an error parsing the document. + */ + private static void addContent( Document document, InputStream is, String documentLocation ) throws IOException + { + PDDocument pdfDocument = null; + try + { + pdfDocument = PDDocument.load( is ); + + + if( pdfDocument.isEncrypted() ) + { + //Just try using the default password and move on + pdfDocument.decrypt( "" ); + } + + //create a writer where to append the text content. + StringWriter writer = new StringWriter(); + PDFTextStripper stripper = new PDFTextStripper(); + stripper.writeText( pdfDocument, writer ); + + // Note: the buffer to string operation is costless; + // the char array value of the writer buffer and the content string + // is shared as long as the buffer content is not modified, which will + // not occur here. + String contents = writer.getBuffer().toString(); + + StringReader reader = new StringReader( contents ); + + // Add the tag-stripped contents as a Reader-valued Text field so it will + // get tokenized and indexed. + document.add( Field.Text( "contents", reader ) ); + + PDDocumentInformation info = pdfDocument.getDocumentInformation(); + if( info.getAuthor() != null ) + { + document.add(Field.Text( "Author", info.getAuthor() ) ); + } + if( info.getCreationDate() != null ) + { + Date date = info.getCreationDate().getTime(); + //for some reason lucene cannot handle dates before the epoch + //and throws a nasty RuntimeException, so we will check and + //verify that this does not happen + if( date.getTime() >= 0 ) + { + document.add(Field.Text("CreationDate", DateField.dateToString( date ) ) ); + } + } + if( info.getCreator() != null ) + { + document.add( Field.Text( "Creator", info.getCreator() ) ); + } + if( info.getKeywords() != null ) + { + document.add( Field.Text( "Keywords", info.getKeywords() ) ); + } + if( info.getModificationDate() != null ) + { + Date date = info.getModificationDate().getTime(); + //for some reason lucene cannot handle dates before the epoch + //and throws a nasty RuntimeException, so we will check and + //verify that this does not happen + if( date.getTime() >= 0 ) + { + document.add(Field.Text("ModificationDate", DateField.dateToString( date ) ) ); + } + } + if( info.getProducer() != null ) + { + document.add( Field.Text( "Producer", info.getProducer() ) ); + } + if( info.getSubject() != null ) + { + document.add( Field.Text( "Subject", info.getSubject() ) ); + } + if( info.getTitle() != null ) + { + document.add( Field.Text( "Title", info.getTitle() ) ); + } + if( info.getTrapped() != null ) + { + document.add( Field.Text( "Trapped", info.getTrapped() ) ); + } + + int summarySize = Math.min( contents.length(), 500 ); + String summary = contents.substring( 0, summarySize ); + // Add the summary as an UnIndexed field, so that it is stored and returned + // with hit documents for display. + document.add( Field.UnIndexed( "summary", summary ) ); + } + catch( CryptographyException e ) + { + throw new IOException( "Error decrypting document(" + documentLocation + "): " + e ); + } + catch( InvalidPasswordException e ) + { + //they didn't suppply a password and the default of "" was wrong. + throw new IOException( "Error: The document(" + documentLocation + + ") is encrypted and will not be indexed." ); + } + finally + { + if( pdfDocument != null ) + { + pdfDocument.close(); + } + } + } + + /** + * This will test creating a document. + * + * usage: java pdfparser.searchengine.lucene.LucenePDFDocument <pdf-document> + * + * @param args command line arguments. + * + * @throws IOException If there is an error. + */ + public static void main( String[] args ) throws IOException + { + if( args.length != 1 ) + { + System.err.println( "usage: java org.pdfbox.searchengine.lucene.LucenePDFDocument " ); + System.exit( 1 ); + } + System.out.println( "Document=" + getDocument( new File( args[0] ) ) ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/searchengine/lucene/package.html b/src/main/java/org/pdfbox/searchengine/lucene/package.html new file mode 100644 index 0000000..fbf3a38 --- /dev/null +++ b/src/main/java/org/pdfbox/searchengine/lucene/package.html @@ -0,0 +1,9 @@ + + + + + + +This package holds classes that are used to integrate the PDFBox project with lucene. + + diff --git a/src/main/java/org/pdfbox/searchengine/package.html b/src/main/java/org/pdfbox/searchengine/package.html new file mode 100644 index 0000000..1cb4629 --- /dev/null +++ b/src/main/java/org/pdfbox/searchengine/package.html @@ -0,0 +1,9 @@ + + + + + + +Classes that are used to integrate PDFBox with a search engine are located here. + + diff --git a/src/main/java/org/pdfbox/ttf/CMAPEncodingEntry.java b/src/main/java/org/pdfbox/ttf/CMAPEncodingEntry.java new file mode 100644 index 0000000..a740203 --- /dev/null +++ b/src/main/java/org/pdfbox/ttf/CMAPEncodingEntry.java @@ -0,0 +1,219 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.ttf; + +import java.io.IOException; + +/** + * An encoding entry for a cmap. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.1 $ + */ +public class CMAPEncodingEntry +{ + + private int platformId; + private int platformEncodingId; + private long subTableOffset; + private int[] glyphIdToCharacterCode; + /** + * This will read the required data from the stream. + * + * @param ttf The font that is being read. + * @param data The stream to read the data from. + * @throws IOException If there is an error reading the data. + */ + public void initData( TrueTypeFont ttf, TTFDataStream data ) throws IOException + { + platformId = data.readUnsignedShort(); + platformEncodingId = data.readUnsignedShort(); + subTableOffset = data.readUnsignedInt(); + } + + /** + * This will read the required data from the stream. + * + * @param ttf The font that is being read. + * @param data The stream to read the data from. + * @throws IOException If there is an error reading the data. + */ + public void initSubtable( TrueTypeFont ttf, TTFDataStream data ) throws IOException + { + data.seek( ttf.getCMAP().getOffset() + subTableOffset ); + int subtableFormat = data.readUnsignedShort(); + int length = data.readUnsignedShort(); + int version = data.readUnsignedShort(); + int numGlyphs = ttf.getMaximumProfile().getNumGlyphs(); + if( subtableFormat == 0 ) + { + byte[] glyphMapping = data.read( 256 ); + glyphIdToCharacterCode = new int[256]; + for( int i=0;i 0 ) + { + endPointsOfContours = new int[ numberOfContours ]; + for( int i=0; i= 1 ) + { + codePageRange1 = data.readUnsignedInt(); + codePageRange2 = data.readUnsignedInt(); + } + } +} diff --git a/src/main/java/org/pdfbox/ttf/PostScriptTable.java b/src/main/java/org/pdfbox/ttf/PostScriptTable.java new file mode 100644 index 0000000..e7b7822 --- /dev/null +++ b/src/main/java/org/pdfbox/ttf/PostScriptTable.java @@ -0,0 +1,304 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.ttf; + +import java.io.IOException; + +import org.pdfbox.cos.COSName; + +import org.pdfbox.encoding.MacRomanEncoding; + +/** + * A table in a true type font. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.1 $ + */ +public class PostScriptTable extends TTFTable +{ + private float formatType; + private float italicAngle; + private short underlinePosition; + private short underlineThickness; + private long isFixedPitch; + private long minMemType42; + private long maxMemType42; + private long mimMemType1; + private long maxMemType1; + private String[] glyphNames = null; + + /** + * A tag that identifies this table type. + */ + public static final String TAG = "post"; + + /** + * This will read the required data from the stream. + * + * @param ttf The font that is being read. + * @param data The stream to read the data from. + * @throws IOException If there is an error reading the data. + */ + public void initData( TrueTypeFont ttf, TTFDataStream data ) throws IOException + { + MaximumProfileTable maxp = ttf.getMaximumProfile(); + formatType = data.read32Fixed(); + italicAngle = data.read32Fixed(); + underlinePosition = data.readSignedShort(); + underlineThickness = data.readSignedShort(); + isFixedPitch = data.readUnsignedInt(); + minMemType42 = data.readUnsignedInt(); + maxMemType42 = data.readUnsignedInt(); + mimMemType1 = data.readUnsignedInt(); + maxMemType1 = data.readUnsignedInt(); + MacRomanEncoding encoding = new MacRomanEncoding(); + + + if( formatType == 1.0f ) + { + /* + * This TrueType font file contains exactly the 258 glyphs in the standard + * Macintosh TrueType. + */ + glyphNames = new String[258]; + for( int i=0; i= 258 ) + { + nameArray = new String[ maxIndex-258 +1 ]; + for( int i=0; i= 258 && index <= 32767 ) + { + glyphNames[i] = nameArray[index-258]; + } + else + { + throw new IOException( "Unknown glyph name index:" + index ); + } + } + } + else if( formatType == 2.5f ) + { + int[] glyphNameIndex = new int[maxp.getNumGlyphs()]; + for( int i=0; i + * usage: java org.pdfbox.ttf.TTFParser <ttf-file> + * + * @param args The command line arguments. + * + * @throws IOException If there is an error while parsing the font file. + */ + public static void main( String[] args ) throws IOException + { + if( args.length != 1 ) + { + System.err.println( "usage: java org.pdfbox.ttf.TTFParser " ); + System.exit( -1 ); + } + TTFParser parser = new TTFParser(); + TrueTypeFont font = parser.parseTTF( args[0] ); + System.out.println( "Font:" + font ); + } + + /** + * Parse a file and get a true type font. + * @param ttfFile The TTF file. + * @return A true type font. + * @throws IOException If there is an error parsing the true type font. + */ + public TrueTypeFont parseTTF( String ttfFile ) throws IOException + { + RAFDataStream raf = new RAFDataStream( ttfFile, "r" ); + return parseTTF( raf ); + } + + /** + * Parse a file and get a true type font. + * @param ttfFile The TTF file. + * @return A true type font. + * @throws IOException If there is an error parsing the true type font. + */ + public TrueTypeFont parseTTF( File ttfFile ) throws IOException + { + RAFDataStream raf = new RAFDataStream( ttfFile, "r" ); + return parseTTF( raf ); + } + + /** + * Parse a file and get a true type font. + * @param raf The TTF file. + * @return A true type font. + * @throws IOException If there is an error parsing the true type font. + */ + public TrueTypeFont parseTTF( TTFDataStream raf ) throws IOException + { + TrueTypeFont font = new TrueTypeFont( raf ); + font.setVersion( raf.read32Fixed() ); + int numberOfTables = raf.readUnsignedShort(); + int searchRange = raf.readUnsignedShort(); + int entrySelector = raf.readUnsignedShort(); + int rangeShift = raf.readUnsignedShort(); + for( int i=0; i + + + + + +This package contains classes to parse a TTF file. + + diff --git a/src/main/java/org/pdfbox/util/BitFlagHelper.java b/src/main/java/org/pdfbox/util/BitFlagHelper.java new file mode 100644 index 0000000..058f733 --- /dev/null +++ b/src/main/java/org/pdfbox/util/BitFlagHelper.java @@ -0,0 +1,85 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util; + +import org.pdfbox.cos.COSDictionary; + +/** + * This class will be used for bit flag operations. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.2 $ + */ +public class BitFlagHelper +{ + private BitFlagHelper() + { + //helper class should not be constructed + } + + /** + * Sets the given boolean value at bitPos in the flags. + * + * @param dic The dictionary to set the value into. + * @param field The name of the field to set the value into. + * @param bitFlag the bit position to set the value in. + * @param value the value the bit position should have. + */ + public static void setFlag( COSDictionary dic, String field, int bitFlag, boolean value ) + { + int currentFlags = dic.getInt( field, 0 ); + if( value ) + { + currentFlags = currentFlags | bitFlag; + } + else + { + currentFlags = currentFlags &= ~bitFlag; + } + dic.setInt( field, currentFlags ); + } + + /** + * Gets the boolean value from the flags at the given bit + * position. + * + * @param dic The dictionary to get the field from. + * @param field The name of the field to get the flag from. + * @param bitFlag the bitPosition to get the value from. + * + * @return true if the number at bitPos is '1' + */ + public static boolean getFlag(COSDictionary dic, String field, int bitFlag) + { + int ff = dic.getInt( field, 0 ); + return (ff & bitFlag) == bitFlag; + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/util/BoundingBox.java b/src/main/java/org/pdfbox/util/BoundingBox.java new file mode 100644 index 0000000..aaea354 --- /dev/null +++ b/src/main/java/org/pdfbox/util/BoundingBox.java @@ -0,0 +1,188 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util; + +import java.awt.Point; + +/** + * This is an implementation of a bounding box. This was originally written for the + * AMF parser. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.6 $ + */ +public class BoundingBox +{ + private float lowerLeftX; + private float lowerLeftY; + private float upperRightX; + private float upperRightY; + + /** + * Getter for property lowerLeftX. + * + * @return Value of property lowerLeftX. + */ + public float getLowerLeftX() + { + return lowerLeftX; + } + + /** + * Setter for property lowerLeftX. + * + * @param lowerLeftXValue New value of property lowerLeftX. + */ + public void setLowerLeftX(float lowerLeftXValue) + { + this.lowerLeftX = lowerLeftXValue; + } + + /** + * Getter for property lowerLeftY. + * + * @return Value of property lowerLeftY. + */ + public float getLowerLeftY() + { + return lowerLeftY; + } + + /** + * Setter for property lowerLeftY. + * + * @param lowerLeftYValue New value of property lowerLeftY. + */ + public void setLowerLeftY(float lowerLeftYValue) + { + this.lowerLeftY = lowerLeftYValue; + } + + /** + * Getter for property upperRightX. + * + * @return Value of property upperRightX. + */ + public float getUpperRightX() + { + return upperRightX; + } + + /** + * Setter for property upperRightX. + * + * @param upperRightXValue New value of property upperRightX. + */ + public void setUpperRightX(float upperRightXValue) + { + this.upperRightX = upperRightXValue; + } + + /** + * Getter for property upperRightY. + * + * @return Value of property upperRightY. + */ + public float getUpperRightY() + { + return upperRightY; + } + + /** + * Setter for property upperRightY. + * + * @param upperRightYValue New value of property upperRightY. + */ + public void setUpperRightY(float upperRightYValue) + { + this.upperRightY = upperRightYValue; + } + + /** + * This will get the width of this rectangle as calculated by + * upperRightX - lowerLeftX. + * + * @return The width of this rectangle. + */ + public float getWidth() + { + return getUpperRightX() - getLowerLeftX(); + } + + /** + * This will get the height of this rectangle as calculated by + * upperRightY - lowerLeftY. + * + * @return The height of this rectangle. + */ + public float getHeight() + { + return getUpperRightY() - getLowerLeftY(); + } + + /** + * Checks if a point is inside this rectangle. + * + * @param x The x coordinate. + * @param y The y coordinate. + * + * @return true If the point is on the edge or inside the rectangle bounds. + */ + public boolean contains( float x, float y ) + { + return x >= lowerLeftX && x <= upperRightX && + y >= lowerLeftY && y <= upperRightY; + } + + /** + * Checks if a point is inside this rectangle. + * + * @param point The point to check + * + * @return true If the point is on the edge or inside the rectangle bounds. + */ + public boolean contains( Point point ) + { + return contains( (float)point.getX(), (float)point.getY() ); + } + + /** + * This will return a string representation of this rectangle. + * + * @return This object as a string. + */ + public String toString() + { + return "[" + getLowerLeftX() + "," + getLowerLeftY() + "," + + getUpperRightX() + "," + getUpperRightY() +"]"; + } + +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/util/DateConverter.java b/src/main/java/org/pdfbox/util/DateConverter.java new file mode 100644 index 0000000..43d3566 --- /dev/null +++ b/src/main/java/org/pdfbox/util/DateConverter.java @@ -0,0 +1,281 @@ +/** + * Copyright (c) 2003-2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util; + +import java.text.ParseException; +import java.text.SimpleDateFormat; + +import java.io.IOException; + +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.SimpleTimeZone; +import java.util.TimeZone; + +import org.pdfbox.cos.COSString; + +/** + * This class is used to convert dates to strings and back using the PDF + * date standards. Date are described in PDFReference1.4 section 3.8.2 + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.9 $ + */ +public class DateConverter +{ + private static final SimpleDateFormat PDF_DATE_FORMAT = new SimpleDateFormat( "yyyyMMddHHmmss" ); + + //The Date format is supposed to be the PDF_DATE_FORMAT, but not all PDF documents + //will use that date, so I have added a couple other potential formats + //to try if the original one does not work. + private static final SimpleDateFormat[] POTENTIAL_FORMATS = new SimpleDateFormat[] { + new SimpleDateFormat("EEEE, dd MMM yyyy hh:mm:ss a"), + new SimpleDateFormat("EEEE, MMM dd, yyyy hh:mm:ss a")}; + + private static final SimpleDateFormat ISO_8601_DATE_FORMAT = new SimpleDateFormat( "yyyy-MM-dd'T'HH:mm:ss" ); + + private DateConverter() + { + //utility class should not be constructed. + } + + /** + * This will convert the calendar to a string. + * + * @param date The date to convert to a string. + * + * @return The date as a String to be used in a PDF document. + */ + public static String toString( Calendar date ) + { + String retval = null; + if( date != null ) + { + StringBuffer buffer = new StringBuffer(); + TimeZone zone = date.getTimeZone(); + long offsetInMinutes = zone.getOffset( date.getTimeInMillis() )/1000/60; + long hours = Math.abs( offsetInMinutes/60 ); + long minutes = Math.abs( offsetInMinutes%60 ); + buffer.append( "D:" ); + buffer.append( PDF_DATE_FORMAT.format( date.getTime() ) ); + if( offsetInMinutes == 0 ) + { + buffer.append( "Z" ); + } + else if( offsetInMinutes < 0 ) + { + buffer.append( "-" ); + } + else + { + buffer.append( "+" ); + } + if( hours < 10 ) + { + buffer.append( "0" ); + } + buffer.append( hours ); + buffer.append( "'" ); + if( minutes < 10 ) + { + buffer.append( "0" ); + } + buffer.append( minutes ); + buffer.append( "'" ); + retval = buffer.toString(); + + } + return retval; + } + + /** + * This will convert a string to a calendar. + * + * @param date The string representation of the calendar. + * + * @return The calendar that this string represents. + * + * @throws IOException If the date string is not in the correct format. + */ + public static Calendar toCalendar( COSString date ) throws IOException + { + Calendar retval = null; + if( date != null ) + { + retval = toCalendar( date.getString() ); + } + + return retval; + } + + /** + * This will convert a string to a calendar. + * + * @param date The string representation of the calendar. + * + * @return The calendar that this string represents. + * + * @throws IOException If the date string is not in the correct format. + */ + public static Calendar toCalendar( String date ) throws IOException + { + Calendar retval = null; + if( date != null ) + { + //these are the default values + int year = 0; + int month = 1; + int day = 1; + int hour = 0; + int minute = 0; + int second = 0; + //first string off the prefix if it exists + try + { + SimpleTimeZone zone = null; + if( date.startsWith( "D:" ) ) + { + date = date.substring( 2, date.length() ); + } + if( date.length() < 4 ) + { + throw new IOException( "Error: Invalid date format '" + date + "'" ); + } + year = Integer.parseInt( date.substring( 0, 4 ) ); + if( date.length() >= 6 ) + { + month = Integer.parseInt( date.substring( 4, 6 ) ); + } + if( date.length() >= 8 ) + { + day = Integer.parseInt( date.substring( 6, 8 ) ); + } + if( date.length() >= 10 ) + { + hour = Integer.parseInt( date.substring( 8, 10 ) ); + } + if( date.length() >= 12 ) + { + minute = Integer.parseInt( date.substring( 10, 12 ) ); + } + if( date.length() >= 14 ) + { + second = Integer.parseInt( date.substring( 12, 14 ) ); + } + retval = new GregorianCalendar( year, month-1, day, hour, minute, second ); + if( date.length() >= 15 ) + { + char sign = date.charAt( 14 ); + if( sign == 'Z' ) + { + zone = new SimpleTimeZone(0,"Unknown"); + } + else + { + int hours = 0; + int minutes = 0; + if( date.length() >= 17 ) + { + hours = Integer.parseInt( date.substring( 15, 17 ) ); + } + if( date.length() > 20 ) + { + minutes = Integer.parseInt( date.substring( 18, 20 ) ); + } + zone = new SimpleTimeZone( hours*60*60*1000 + minutes*60*1000, "Unknown" ); + } + retval.setTimeZone( zone ); + } + } + catch( NumberFormatException e ) + { + for( int i=0; retval == null && i0 && i + * Adobe Highlight File Format + */ +public class PDFHighlighter extends PDFTextStripper +{ + private Writer highlighterOutput = null; + //private Color highlightColor = Color.YELLOW; + + private String[] searchedWords; + private ByteArrayOutputStream textOS = null; + private Writer textWriter = null; + + /** + * Default constructor. + * + * @throws IOException If there is an error constructing this class. + */ + public PDFHighlighter() throws IOException + { + super(); + super.setLineSeparator( "" ); + super.setPageSeparator( "" ); + super.setWordSeparator( "" ); + super.setShouldSeparateByBeads( false ); + super.setSuppressDuplicateOverlappingText( false ); + } + + /** + * Generate an XML highlight string based on the PDF. + * + * @param pdDocument The PDF to find words in. + * @param highlightWord The word to search for. + * @param xmlOutput The resulting output xml file. + * + * @throws IOException If there is an error reading from the PDF, or writing to the XML. + */ + public void generateXMLHighlight(PDDocument pdDocument, String highlightWord, Writer xmlOutput ) throws IOException + { + generateXMLHighlight( pdDocument, new String[] { highlightWord }, xmlOutput ); + } + + /** + * Generate an XML highlight string based on the PDF. + * + * @param pdDocument The PDF to find words in. + * @param sWords The words to search for. + * @param xmlOutput The resulting output xml file. + * + * @throws IOException If there is an error reading from the PDF, or writing to the XML. + */ + public void generateXMLHighlight(PDDocument pdDocument, String[] sWords, Writer xmlOutput ) throws IOException + { + highlighterOutput = xmlOutput; + searchedWords = sWords; + highlighterOutput.write("\n\n\n"); + textOS = new ByteArrayOutputStream(); + textWriter = new OutputStreamWriter( textOS, "UTF-16" ); + writeText(pdDocument, textWriter); + highlighterOutput.write("\n\n"); + highlighterOutput.flush(); + } + + /** + * @see PDFTextStripper#endPage( PDPage ) + */ + protected void endPage( PDPage pdPage ) throws IOException + { + textWriter.flush(); + + String page = new String( textOS.toByteArray(), "UTF-16" ); + textOS.reset(); + //page = page.replaceAll( "\n", "" ); + //page = page.replaceAll( "\r", "" ); + //page = CCRStringUtil.stripChar(page, '\n'); + //page = CCRStringUtil.stripChar(page, '\r'); + + // Traitement des listes à puces (caractères spéciaux) + if (page.indexOf("a") != -1) + { + page = page.replaceAll("a[0-9]{1,3}", "."); + } + + for (int i = 0; i < searchedWords.length; i++) + { + Pattern pattern = Pattern.compile(searchedWords[i], Pattern.CASE_INSENSITIVE); + Matcher matcher = pattern.matcher(page); + while( matcher.find() ) + { + int begin = matcher.start(); + int end = matcher.end(); + highlighterOutput.write(" \n"); + } + } + } + + /** + * Command line application. + * + * @param args The command line arguments to the application. + * + * @throws IOException If there is an error generating the highlight file. + */ + public static void main(String[] args) throws IOException + { + PDFHighlighter xmlExtractor = new PDFHighlighter(); + PDDocument doc = null; + try + { + if( args.length < 2 ) + { + usage(); + } + String[] highlightStrings = new String[ args.length - 1]; + System.arraycopy( args, 1, highlightStrings, 0, highlightStrings.length ); + doc = PDDocument.load( args[0] ); + + xmlExtractor.generateXMLHighlight( + doc, + highlightStrings, + new OutputStreamWriter( System.out ) ); + } + finally + { + if( doc != null ) + { + doc.close(); + } + } + } + + private static void usage() + { + System.err.println( "usage: java " + PDFHighlighter.class.getName() + " word1 word2 word3 ..." ); + System.exit( 1 ); + } + + + /** + * Get the color to highlight the strings with. Default is Color.YELLOW. + * + * @return The color to highlight strings with. + */ + /*public Color getHighlightColor() + { + return highlightColor; + }**/ + + /** + * Get the color to highlight the strings with. Default is Color.YELLOW. + * + * @param color The color to highlight strings with. + */ + /*public void setHighlightColor(Color color) + { + this.highlightColor = color; + }**/ + + /** + * Set the highlight color using HTML like rgb string. The string must be 6 characters long. + * + * @param color The color to use for highlighting. Should be in the format of "FF0000". + */ + /*public void setHighlightColor( String color ) + { + highlightColor = Color.decode( color ); + }**/ + + /** + * Get the highlight color as an HTML like string. This will return a string of six characters. + * + * @return The current highlight color. For example FF0000 + */ + /*public String getHighlightColorAsString() + { + //BJL: kudos to anyone that has a cleaner way of doing this! + String red = Integer.toHexString( highlightColor.getRed() ); + String green = Integer.toHexString( highlightColor.getGreen() ); + String blue = Integer.toHexString( highlightColor.getBlue() ); + + return (red.length() < 2 ? "0" + red : red) + + (green.length() < 2 ? "0" + green : green) + + (blue.length() < 2 ? "0" + blue : blue); + }**/ +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/util/PDFOperator.java b/src/main/java/org/pdfbox/util/PDFOperator.java new file mode 100644 index 0000000..76d9887 --- /dev/null +++ b/src/main/java/org/pdfbox/util/PDFOperator.java @@ -0,0 +1,153 @@ +/** + * Copyright (c) 2003-2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * This class represents an Operator in the content stream. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.13 $ + */ +public class PDFOperator +{ + private String theOperator; + private byte[] imageData; + private ImageParameters imageParameters; + + private static Map operators = Collections.synchronizedMap( new HashMap() ); + + /** + * Constructor. + * + * @param aOperator The operator that this object will represent. + */ + private PDFOperator( String aOperator ) + { + theOperator = aOperator; + if( aOperator.startsWith( "/" ) ) + { + throw new RuntimeException( "Operators are not allowed to start with / '" + aOperator + "'" ); + } + } + + /** + * This is used to create/cache operators in the system. + * + * @param operator The operator for the system. + * + * @return The operator that matches the operator keyword. + */ + public static PDFOperator getOperator( String operator ) + { + PDFOperator operation = null; + if( operator.equals( "ID" ) || operator.equals( "BI" ) ) + { + //we can't cache the ID operators. + operation = new PDFOperator( operator ); + } + else + { + operation = (PDFOperator)operators.get( operator ); + if( operation == null ) + { + operation = new PDFOperator( operator ); + operators.put( operator, operation ); + } + } + + return operation; + } + + /** + * This will get the operation that this operator represents. + * + * @return The string representation of the operation. + */ + public String getOperation() + { + return theOperator; + } + + /** + * This will print a string rep of this class. + * + * @return A string rep of this class. + */ + public String toString() + { + return "PDFOperator{" + theOperator + "}"; + } + + /** + * This is the special case for the ID operator where there are just random + * bytes inlined the stream. + * + * @return Value of property imageData. + */ + public byte[] getImageData() + { + return this.imageData; + } + + /** + * This will set the image data, this is only used for the ID operator. + * + * @param imageDataArray New value of property imageData. + */ + public void setImageData(byte[] imageDataArray) + { + imageData = imageDataArray; + } + + /** + * This will get the image parameters, this is only valid for BI operators. + * + * @return The image parameters. + */ + public ImageParameters getImageParameters() + { + return imageParameters; + } + + /** + * This will set the image parameters, this is only valid for BI operators. + * + * @param params The image parameters. + */ + public void setImageParameters( ImageParameters params) + { + imageParameters = params; + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/util/PDFStreamEngine.java b/src/main/java/org/pdfbox/util/PDFStreamEngine.java new file mode 100644 index 0000000..1e05f8a --- /dev/null +++ b/src/main/java/org/pdfbox/util/PDFStreamEngine.java @@ -0,0 +1,622 @@ +/** + * Copyright (c) 2003-2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util; + +import java.io.IOException; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Stack; + +import org.pdfbox.cos.COSObject; +import org.pdfbox.cos.COSStream; +import org.pdfbox.exceptions.WrappedIOException; + +import org.pdfbox.pdmodel.PDPage; +import org.pdfbox.pdmodel.PDResources; + +import org.pdfbox.pdmodel.font.PDFont; + +import org.pdfbox.pdmodel.graphics.PDGraphicsState; + +import org.pdfbox.util.operator.OperatorProcessor; + +import org.apache.log4j.Logger; + +/** + * This class will run through a PDF content stream and execute certain operations + * and provide a callback interface for clients that want to do things with the stream. + * See the PDFTextStripper class for an example of how to use this class. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.29 $ + */ +public class PDFStreamEngine +{ + private static Logger log = Logger.getLogger(PDFStreamEngine.class); + + static protected final byte[] SPACE_BYTES = { (byte)32 }; + + private PDGraphicsState graphicsState = null; + + protected Matrix textMatrix = null; + protected Matrix textLineMatrix = null; + protected Stack graphicsStack = new Stack(); + //private PDResources resources = null; + + protected Map operators = new HashMap(); + + protected Map fontToAverageWidths = new HashMap(); + + protected Stack streamResourcesStack = new Stack(); + + protected PDPage page; + + /** + * This is a simple internal class used by the Stream engine to handle the + * resources stack. + */ + protected static class StreamResources + { + protected Map fonts; + protected Map colorSpaces; + protected Map xobjects; + protected Map graphicsStates; + protected PDResources resources; + } + + /** + * Constructor. + */ + public PDFStreamEngine() + { + //default constructor + } + + /** + * Constructor with engine properties. The property keys are all + * PDF operators, the values are class names used to execute those + * operators. + * + * @param properties The engine properties. + * + * @throws IOException If there is an error setting the engine properties. + */ + public PDFStreamEngine( Properties properties ) throws IOException + { + try + { + Iterator keys = properties.keySet().iterator(); + while( keys.hasNext() ) + { + String operator = (String)keys.next(); + String operatorClass = properties.getProperty( operator ); + if( log.isDebugEnabled() ) + { + log.debug( "Operator Class: " + operator + "=" + operatorClass ); + } + OperatorProcessor op = (OperatorProcessor)Class.forName( operatorClass ).newInstance(); + op.setContext( this ); + operators.put( operator, op ); + } + } + catch( Exception e ) + { + throw new WrappedIOException( e ); + } + } + + /** + * This will process the contents of the stream. + * + * @param aPage The page. + * @param resources The location to retrieve resources. + * @param cosStream the Stream to execute. + * + * + * @throws IOException if there is an error accessing the stream. + */ + public void processStream( PDPage aPage, PDResources resources, COSStream cosStream ) throws IOException + { + graphicsState = new PDGraphicsState(); + textMatrix = null; + textLineMatrix = null; + graphicsStack.clear(); + streamResourcesStack.clear(); + fontToAverageWidths.clear(); + + processSubStream( aPage, resources, cosStream ); + } + + /** + * Process a sub stream of the current stream. + * + * @param aPage The page used for drawing. + * @param resources The resources used when processing the stream. + * @param cosStream The stream to process. + * + * @throws IOException If there is an exception while processing the stream. + */ + public void processSubStream( PDPage aPage, PDResources resources, COSStream cosStream ) throws IOException + { + page = aPage; + if( resources != null ) + { + StreamResources sr = new StreamResources(); + sr.fonts = resources.getFonts(); + sr.colorSpaces = resources.getColorSpaces(); + sr.xobjects = resources.getXObjects(); + sr.graphicsStates = resources.getGraphicsStates(); + sr.resources = resources; + streamResourcesStack.push(sr); + } + try + { + List arguments = new ArrayList(); + long startTokens = System.currentTimeMillis(); + List tokens = cosStream.getStreamTokens(); + long stopTokens = System.currentTimeMillis(); + if( log.isDebugEnabled() ) + { + log.debug( "Getting tokens time=" + (stopTokens-startTokens) ); + } + if( tokens != null ) + { + Iterator iter = tokens.iterator(); + while( iter.hasNext() ) + { + Object next = iter.next(); + if( next instanceof COSObject ) + { + arguments.add( ((COSObject)next).getObject() ); + } + else if( next instanceof PDFOperator ) + { + processOperator( (PDFOperator)next, arguments ); + arguments = new ArrayList(); + } + else + { + arguments.add( next ); + } + } + } + } + finally + { + if( resources != null ) + { + streamResourcesStack.pop(); + } + } + + } + + /** + * A method provided as an event interface to allow a subclass to perform + * some specific functionality when a character needs to be displayed. + * + * @param text The character to be displayed. + */ + protected void showCharacter( TextPosition text ) + { + //subclasses can override to provide specific functionality. + } + + /** + * You should override this method if you want to perform an action when a + * string is being shown. + * + * @param string The string to display. + * + * @throws IOException If there is an error showing the string + */ + public void showString( byte[] string ) throws IOException + { + float spaceWidth = 0; + float spacing = 0; + StringBuffer stringResult = new StringBuffer(string.length); + + float characterDisplacement = 0; + float spaceDisplacement = 0; + float fontSize = graphicsState.getTextState().getFontSize(); + float horizontalScaling = graphicsState.getTextState().getHorizontalScalingPercent()/100f; + float rise = graphicsState.getTextState().getRise(); + final float wordSpacing = graphicsState.getTextState().getWordSpacing(); + final float characterSpacing = graphicsState.getTextState().getCharacterSpacing(); + float wordSpacingDisplacement = 0; + + PDFont font = graphicsState.getTextState().getFont(); + + //This will typically be 1000 but in the case of a type3 font + //this might be a different number + float glyphSpaceToTextSpaceFactor = 1f/font.getFontMatrix().getValue( 0, 0 ); + Float averageWidth = (Float)fontToAverageWidths.get( font ); + if( averageWidth == null ) + { + averageWidth = new Float( font.getAverageFontWidth() ); + fontToAverageWidths.put( font, averageWidth ); + } + + Matrix initialMatrix = new Matrix(); + initialMatrix.setValue(0,0,1); + initialMatrix.setValue(0,1,0); + initialMatrix.setValue(0,2,0); + initialMatrix.setValue(1,0,0); + initialMatrix.setValue(1,1,1); + initialMatrix.setValue(1,2,0); + initialMatrix.setValue(2,0,0); + initialMatrix.setValue(2,1,rise); + initialMatrix.setValue(2,2,1); + + + //this + int codeLength = 1; + Matrix ctm = graphicsState.getCurrentTransformationMatrix(); + + //lets see what the space displacement should be + spaceDisplacement = (font.getFontWidth( SPACE_BYTES, 0, 1 )/glyphSpaceToTextSpaceFactor); + if( spaceDisplacement == 0 ) + { + spaceDisplacement = (averageWidth.floatValue()/glyphSpaceToTextSpaceFactor); + //The average space width appears to be higher than necessary + //so lets make it a little bit smaller. + spaceDisplacement *= .80f; + if( log.isDebugEnabled() ) + { + log.debug( "Font: Space From Average=" + spaceDisplacement ); + } + } + int pageRotation = page.findRotation(); + Matrix trm = initialMatrix.multiply( textMatrix ).multiply( ctm ); + float x = trm.getValue(2,0); + float y = trm.getValue(2,1); + if( pageRotation == 0 ) + { + trm.setValue( 2,1, -y + page.findMediaBox().getHeight() ); + } + else if( pageRotation == 90 ) + { + trm.setValue( 2,0, y ); + trm.setValue( 2,1, x ); + } + else if( pageRotation == 270 ) + { + trm.setValue( 2,0, -y + page.findMediaBox().getHeight() ); + trm.setValue( 2,1, x ); + } + for( int i=0; i"); + buf.append(""); + buf.append(getTitleGuess()); + buf.append(""); + buf.append(""); + buf.append("\n"); + getOutput().write(buf.toString()); + } + + /** + * The guess to the document title. + * + * @return A string that is the title of this document. + */ + protected String getTitleGuess() + { + return titleGuess; + } + + /** + * @see PDFTextStripper#flushText + */ + protected void flushText() throws IOException + { + Iterator textIter = getCharactersByArticle().iterator(); + + if (onFirstPage) + { + guessTitle(textIter); + writeHeader(); + onFirstPage = false; + } + super.flushText(); + } + + /** + * @see PDFTextStripper#endDocument( PDDocument ) + */ + public void endDocument(PDDocument pdf) throws IOException + { + output.write(""); + } + + /** + * This method will attempt to guess the title of the document. + * + * @param textIter The characters on the first page. + * @return The text position that is guessed to be the title. + */ + protected TextPosition guessTitle(Iterator textIter) + { + float lastFontSize = -1.0f; + int stringsInFont = 0; + StringBuffer titleText = new StringBuffer(); + while (textIter.hasNext()) + { + Iterator textByArticle = ((List)textIter.next()).iterator(); + while( textByArticle.hasNext() ) + { + TextPosition position = (TextPosition) textByArticle.next(); + float currentFontSize = position.getFontSize(); + if (currentFontSize != lastFontSize) + { + if (beginTitle != null) + { // font change in candidate title. + if (stringsInFont == 0) + { + beginTitle = null; // false alarm + titleText.setLength(0); + } + else + { + // had a significant font with some words: call it a title + titleGuess = titleText.toString(); + log.debug("Title candidate =" + titleGuess); + afterEndTitle = position; + return beginTitle; + } + } + else + { // font change and begin == null + if (currentFontSize > 13.0f) + { // most body text is 12pt max I guess + beginTitle = position; + } + } + + lastFontSize = currentFontSize; + stringsInFont = 0; + } + stringsInFont++; + if (beginTitle != null) + { + titleText.append(position.getCharacter()+" "); + } + } + } + return beginTitle; // null + } + + /** + * Write out the paragraph separator. + * + * @throws IOException If there is an error writing to the stream. + */ + protected void startParagraph() throws IOException + { + if (! suppressParagraphs) + { + getOutput().write("

    "); + } + } + /** + * Write out the paragraph separator. + * + * @throws IOException If there is an error writing to the stream. + */ + protected void endParagraph() throws IOException + { + if (! suppressParagraphs) + { + getOutput().write("

    "); + } + } + + /** + * @see PDFTextStripper#writeCharacters( TextPosition ) + */ + protected void writeCharacters(TextPosition position ) throws IOException + { + if (position == beginTitle) + { + output.write("

    "); + suppressParagraphs = true; + } + if (position == afterEndTitle) + { + output.write("

    "); // end title and start first paragraph + suppressParagraphs = false; + } + + String chars = position.getCharacter(); + + for (int i = 0; i < chars.length(); i++) + { + char c = chars.charAt(i); + if ((c < 32) || (c > 126)) + { + int charAsInt = c; + output.write("&#" + charAsInt + ";"); + } + else + { + switch (c) + { + case 34: + output.write("""); + break; + case 38: + output.write("&"); + break; + case 60: + output.write("<"); + break; + case 62: + output.write(">"); + break; + default: + output.write(c); + } + } + } + } + + /** + * @return Returns the suppressParagraphs. + */ + public boolean isSuppressParagraphs() + { + return suppressParagraphs; + } + /** + * @param shouldSuppressParagraphs The suppressParagraphs to set. + */ + public void setSuppressParagraphs(boolean shouldSuppressParagraphs) + { + this.suppressParagraphs = shouldSuppressParagraphs; + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/util/PDFTextStripper.java b/src/main/java/org/pdfbox/util/PDFTextStripper.java new file mode 100644 index 0000000..56e80cc --- /dev/null +++ b/src/main/java/org/pdfbox/util/PDFTextStripper.java @@ -0,0 +1,1033 @@ +/** + * Copyright (c) 2003-2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util; + +import java.io.IOException; +import java.io.StringWriter; +import java.io.Writer; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Vector; + +import org.pdfbox.cos.COSDocument; +import org.pdfbox.cos.COSStream; + +import org.pdfbox.pdmodel.PDDocument; +import org.pdfbox.pdmodel.PDPage; + +import org.pdfbox.pdmodel.common.PDRectangle; +import org.pdfbox.pdmodel.common.PDStream; + +import org.pdfbox.pdmodel.encryption.PDEncryptionDictionary; +import org.pdfbox.pdmodel.encryption.PDStandardEncryption; +import org.pdfbox.pdmodel.interactive.documentnavigation.outline.PDOutlineItem; +import org.pdfbox.pdmodel.interactive.pagenavigation.PDThreadBead; + +import org.pdfbox.exceptions.CryptographyException; +import org.pdfbox.exceptions.InvalidPasswordException; + +import org.apache.log4j.Logger; + + +/** + * This class will take a pdf document and strip out all of the text and ignore the + * formatting and such. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.62 $ + */ +public class PDFTextStripper extends PDFStreamEngine +{ + private static Logger log = Logger.getLogger(PDFTextStripper.class); + + private int currentPageNo = 0; + private int startPage = 1; + private int endPage = Integer.MAX_VALUE; + private PDOutlineItem startBookmark = null; + private int startBookmarkPageNumber = -1; + private PDOutlineItem endBookmark = null; + private int endBookmarkPageNumber = -1; + private PDDocument document; + private boolean suppressDuplicateOverlappingText = true; + private boolean shouldSeparateByBeads = true; + private boolean sortByPosition = false; + + private List pageArticles = null; + /** + * The charactersByArticle is used to extract text by article divisions. For example + * a PDF that has two columns like a newspaper, we want to extract the first column and + * then the second column. In this example the PDF would have 2 beads(or articles), one for + * each column. The size of the charactersByArticle would be 5, because not all text on the + * screen will fall into one of the articles. The five divisions are shown below + * + * Text before first article + * first article text + * text between first article and second article + * second article text + * text after second article + * + * Most PDFs won't have any beads, so charactersByArticle will contain a single entry. + */ + protected Vector charactersByArticle = new Vector(); + + private Map characterListMapping = new HashMap(); + + private String lineSeparator = System.getProperty("line.separator"); + private String pageSeparator = System.getProperty("line.separator"); + private String wordSeparator = " "; + + /** + * The stream to write the output to. + */ + protected Writer output; + + /** + * Instantiate a new PDFTextStripper object. This object will load properties from + * Resources/PDFTextStripper.properties. + * @throws IOException If there is an error loading the properties. + */ + public PDFTextStripper() throws IOException + { + super( ResourceLoader.loadProperties( "Resources/PDFTextStripper.properties" ) ); + } + + /** + * This will return the text of a document. See writeText.
    + * NOTE: The document must not be encrypted when coming into this method. + * + * @param doc The document to get the text from. + * + * @return The text of the PDF document. + * + * @throws IOException if the doc state is invalid or it is encrypted. + */ + public String getText( PDDocument doc ) throws IOException + { + StringWriter outputStream = new StringWriter(); + writeText( doc, outputStream ); + return outputStream.toString(); + } + + /** + * @deprecated + * @see PDFTextStripper#getText( PDDocument ) + * @param doc The document to extract the text from. + * @return The document text. + * @throws IOException If there is an error extracting the text. + */ + public String getText( COSDocument doc ) throws IOException + { + return getText( new PDDocument( doc ) ); + } + + /** + * @deprecated + * @see PDFTextStripper#writeText( PDDocument, Writer ) + * @param doc The document to extract the text. + * @param outputStream The stream to write the text to. + * @throws IOException If there is an error extracting the text. + */ + public void writeText( COSDocument doc, Writer outputStream ) throws IOException + { + writeText( new PDDocument( doc ), outputStream ); + } + + /** + * This will take a PDDocument and write the text of that document to the print writer. + * + * @param doc The document to get the data from. + * @param outputStream The location to put the text. + * + * @throws IOException If the doc is in an invalid state. + */ + public void writeText( PDDocument doc, Writer outputStream ) throws IOException + { + + PDEncryptionDictionary encDictionary = doc.getEncryptionDictionary(); + + //only care about standard encryption and if it was decrypted with the + //user password + if( encDictionary instanceof PDStandardEncryption && + !doc.wasDecryptedWithOwnerPassword() ) + { + PDStandardEncryption stdEncryption = (PDStandardEncryption)encDictionary; + if( !stdEncryption.canExtractContent() ) + { + throw new IOException( "You do not have permission to extract text" ); + } + } + currentPageNo = 0; + document = doc; + output = outputStream; + startDocument(document); + + if( document.isEncrypted() ) + { + // We are expecting non-encrypted documents here, but it is common + // for users to pass in a document that is encrypted with an empty + // password (such a document appears to not be encrypted by + // someone viewing the document, thus the confusion). We will + // attempt to decrypt with the empty password to handle this case. + // + log.debug("Document is encrypted, decrypting with empty password"); + try + { + document.decrypt(""); + } + catch (CryptographyException e) + { + throw new IOException("Error decrypting document, details: " + e.getMessage()); + } + catch (InvalidPasswordException e) + { + throw new IOException("Error: document is encrypted"); + } + } + + processPages( document.getDocumentCatalog().getAllPages() ); + endDocument(document); + } + + /** + * This will process all of the pages and the text that is in them. + * + * @param pages The pages object in the document. + * + * @throws IOException If there is an error parsing the text. + */ + protected void processPages( List pages ) throws IOException + { + if( log.isDebugEnabled() ) + { + log.debug( "processPages( " + pages + " )" ); + } + + if( startBookmark != null ) + { + startBookmarkPageNumber = getPageNumber( startBookmark, pages ); + } + + if( endBookmark != null ) + { + endBookmarkPageNumber = getPageNumber( endBookmark, pages ); + } + + if( startBookmarkPageNumber == -1 && startBookmark != null && + endBookmarkPageNumber == -1 && endBookmark != null && + startBookmark.getCOSObject() == endBookmark.getCOSObject() ) + { + //this is a special case where both the start and end bookmark + //are the same but point to nothing. In this case + //we will not extract any text. + startBookmarkPageNumber = 0; + endBookmarkPageNumber = 0; + } + + + Iterator pageIter = pages.iterator(); + while( pageIter.hasNext() ) + { + PDPage nextPage = (PDPage)pageIter.next(); + PDStream contentStream = nextPage.getContents(); + if( contentStream != null ) + { + COSStream contents = contentStream.getStream(); + processPage( nextPage, contents ); + } + } + if( log.isDebugEnabled() ) + { + log.debug( "processPages() end" ); + } + } + + private int getPageNumber( PDOutlineItem bookmark, List allPages ) throws IOException + { + int pageNumber = -1; + PDPage page = bookmark.findDestinationPage( document ); + if( page != null ) + { + pageNumber = allPages.indexOf( page )+1;//use one based indexing + } + return pageNumber; + } + + /** + * This method is available for subclasses of this class. It will be called before processing + * of the document start. + * + * @param pdf The PDF document that is being processed. + * @throws IOException If an IO error occurs. + */ + protected void startDocument(PDDocument pdf) throws IOException + { + // no default implementation, but available for subclasses + } + + /** + * This method is available for subclasses of this class. It will be called after processing + * of the document finishes. + * + * @param pdf The PDF document that is being processed. + * @throws IOException If an IO error occurs. + */ + protected void endDocument(PDDocument pdf ) throws IOException + { + // no default implementation, but available for subclasses + } + + /** + * This will process the contents of a page. + * + * @param page The page to process. + * @param content The contents of the page. + * + * @throws IOException If there is an error processing the page. + */ + protected void processPage( PDPage page, COSStream content ) throws IOException + { + long start = System.currentTimeMillis(); + if( log.isDebugEnabled() ) + { + log.debug( "processPage( " + page + ", " + content + " )" ); + } + currentPageNo++; + if( currentPageNo >= startPage && currentPageNo <= endPage && + (startBookmarkPageNumber == -1 || currentPageNo >= startBookmarkPageNumber ) && + (endBookmarkPageNumber == -1 || currentPageNo <= endBookmarkPageNumber )) + { + startPage( page ); + pageArticles = page.getThreadBeads(); + int numberOfArticleSections = 1 + pageArticles.size() * 2; + if( !shouldSeparateByBeads ) + { + numberOfArticleSections = 1; + } + int originalSize = charactersByArticle.size(); + charactersByArticle.setSize( numberOfArticleSections ); + for( int i=0; i"); + } + float endOfLastTextX = -1; + float startOfNextWordX = -1; + float lastWordSpacing = -1; + TextPosition lastProcessedCharacter = null; + + for( int i=0; i (currentY + (position.getFontSize() * 0.9f * verticalScaling))))) + { + if (log.isDebugEnabled()) + { + log.debug(""); + } + output.write(lineSeparator); + endOfLastTextX = -1; + startOfNextWordX = -1; + currentY = -1; + lastBaselineFontSize = -1; + } + + if (startOfNextWordX != -1 && startOfNextWordX < position.getX() && + lastProcessedCharacter != null && + //only bother adding a space if the last character was not a space + lastProcessedCharacter.getCharacter() != null && + !lastProcessedCharacter.getCharacter().endsWith( " " ) ) + { + if (log.isDebugEnabled()) + { + log.debug(""); + } + output.write( wordSeparator ); + } + + + if (log.isDebugEnabled()) + { + log.debug("flushText" + + " x=" + position.getX() + + " y=" + position.getY() + + " xScale=" + position.getXScale() + + " yScale=" + position.getYScale() + + " width=" + position.getWidth() + + " currentY=" + currentY + + " endOfLastTextX=" + endOfLastTextX + + " startOfNextWordX=" + startOfNextWordX + + " fontSize=" + position.getFontSize() + + " wordSpacing=" + wordSpacing + + " string=\"" + characterValue + "\""); + } + + if (currentY == -1) + { + currentY = position.getY(); + } + + if (currentY == position.getY()) + { + lastBaselineFontSize = position.getFontSize(); + } + + // RDD - endX is what PDF considers to be the x coordinate of the + // end position of the text. We use it in computing our metrics below. + // + endOfLastTextX = position.getX() + position.getWidth(); + + + if (characterValue != null) + { + output.write(characterValue); + } + else + { + log.debug( "Position.getString() is null so not writing anything" ); + } + lastProcessedCharacter = position; + } + endParagraph(); + } + + + // RDD - newline at end of flush - required for end of page (so that the top + // of the next page starts on its own line. + // + if( log.isDebugEnabled() ) + { + log.debug(""); + } + output.write(pageSeparator); + + output.flush(); + } + + /** + * Write the string to the output stream. + * + * @param text The text to write to the stream. + * @throws IOException If there is an error when writing the text. + */ + protected void writeCharacters( TextPosition text ) throws IOException + { + output.write( text.getCharacter() ); + } + + /** + * This will determine of two floating point numbers are within a specified variance. + * + * @param first The first number to compare to. + * @param second The second number to compare to. + * @param variance The allowed variance. + */ + private boolean within( float first, float second, float variance ) + { + return second > first - variance && second < first + variance; + } + + /** + * This will show add a character to the list of characters to be printed to + * the text file. + * + * @param text The description of the character to display. + */ + protected void showCharacter( TextPosition text ) + { + boolean showCharacter = true; + if( suppressDuplicateOverlappingText ) + { + showCharacter = false; + String textCharacter = text.getCharacter(); + float textX = text.getX(); + float textY = text.getY(); + List sameTextCharacters = (List)characterListMapping.get( textCharacter ); + if( sameTextCharacters == null ) + { + sameTextCharacters = new ArrayList(); + characterListMapping.put( textCharacter, sameTextCharacters ); + } + + // RDD - Here we compute the value that represents the end of the rendered + // text. This value is used to determine whether subsequent text rendered + // on the same line overwrites the current text. + // + // We subtract any positive padding to handle cases where extreme amounts + // of padding are applied, then backed off (not sure why this is done, but there + // are cases where the padding is on the order of 10x the character width, and + // the TJ just backs up to compensate after each character). Also, we subtract + // an amount to allow for kerning (a percentage of the width of the last + // character). + // + boolean suppressCharacter = false; + float tolerance = (text.getWidth()/textCharacter.length())/3.0f; + for( int i=0; i + * The default is to not sort by position.
    + *
    + * A PDF writer could choose to write each character in a different order. By + * default PDFBox does not sort the text tokens before processing them due to + * performance reasons. + * + * @param newSortByPosition Tell PDFBox to sort the text positions. + */ + public void setSortByPosition(boolean newSortByPosition) + { + sortByPosition = newSortByPosition; + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/util/PDFTextStripperByArea.java b/src/main/java/org/pdfbox/util/PDFTextStripperByArea.java new file mode 100644 index 0000000..91c76a5 --- /dev/null +++ b/src/main/java/org/pdfbox/util/PDFTextStripperByArea.java @@ -0,0 +1,165 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util; + +import java.awt.Rectangle; +import java.io.IOException; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Vector; + +import org.pdfbox.cos.COSStream; +import org.pdfbox.pdmodel.PDPage; +import org.pdfbox.pdmodel.common.PDStream; + +/** + * This will extract text from a specified region in the PDF. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.3 $ + */ +public class PDFTextStripperByArea extends PDFTextStripper +{ + private List regions = new ArrayList(); + private Map regionArea = new HashMap(); + private Map regionCharacterList = new HashMap(); + private Map regionText = new HashMap(); + + /** + * Constructor. + * @throws IOException If there is an error loading properties. + */ + public PDFTextStripperByArea() throws IOException + { + super(); + } + + /** + * Add a new region to group text by. + * + * @param regionName The name of the region. + * @param rect The rectangle area to retrieve the text from. + */ + public void addRegion( String regionName, Rectangle rect ) + { + regions.add( regionName ); + regionArea.put( regionName, rect ); + } + + /** + * Get the list of regions that have been setup. + * + * @return A list of java.lang.String objects to identify the region names. + */ + public List getRegions() + { + return regions; + } + + /** + * Get the text for the region, this should be called after extractRegions(). + * + * @param regionName The name of the region to get the text from. + * @return The text that was identified in that region. + */ + public String getTextForRegion( String regionName ) + { + StringWriter text = (StringWriter)regionText.get( regionName ); + return text.toString(); + } + + /** + * Process the page to extract the region text. + * + * @param page The page to extract the regions from. + * @throws IOException If there is an error while extracting text. + */ + public void extractRegions( PDPage page ) throws IOException + { + Iterator regionIter = regions.iterator(); + while( regionIter.hasNext() ) + { + //reset the stored text for the region so this class + //can be reused. + String regionName = (String)regionIter.next(); + Vector regionCharactersByArticle = new Vector(); + regionCharactersByArticle.add( new ArrayList() ); + regionCharacterList.put( regionName, regionCharactersByArticle ); + regionText.put( regionName, new StringWriter() ); + } + + PDStream contentStream = page.getContents(); + if( contentStream != null ) + { + COSStream contents = contentStream.getStream(); + processPage( page, contents ); + } + } + + /** + * @see PDFTextStripper#showCharacter(TextPosition) + */ + protected void showCharacter( TextPosition text ) + { + Iterator regionIter = regionArea.keySet().iterator(); + while( regionIter.hasNext() ) + { + String region = (String)regionIter.next(); + Rectangle rect = (Rectangle)regionArea.get( region ); + if( rect.contains( text.getX(), text.getY() ) ) + { + charactersByArticle = (Vector)regionCharacterList.get( region ); + super.showCharacter( text ); + } + } + } + + /** + * This will print the text to the output stream. + * + * @throws IOException If there is an error writing the text. + */ + protected void flushText() throws IOException + { + Iterator regionIter = regionArea.keySet().iterator(); + while( regionIter.hasNext() ) + { + String region = (String)regionIter.next(); + charactersByArticle = (Vector)regionCharacterList.get( region ); + output = (StringWriter)regionText.get( region ); + super.flushText(); + } + } +} diff --git a/src/main/java/org/pdfbox/util/ResourceLoader.java b/src/main/java/org/pdfbox/util/ResourceLoader.java new file mode 100644 index 0000000..0f80d09 --- /dev/null +++ b/src/main/java/org/pdfbox/util/ResourceLoader.java @@ -0,0 +1,169 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + */ +package org.pdfbox.util; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.io.IOException; + +import java.util.Properties; + +import org.apache.log4j.Logger; + +/** + * This class will handle loading resource files(AFM/CMAP). + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.6 $ + */ +public class ResourceLoader +{ + private static Logger log = Logger.getLogger( ResourceLoader.class ); + + /** + * private constructor for utility class. + */ + private ResourceLoader() + { + //private utility class + } + + /** + * This will attempt to load the resource given the resource name. + * + * @param resourceName The resource to try and load. + * + * @return The resource as a stream or null if it could not be found. + * + * @throws IOException If there is an error while attempting to load the resource. + */ + public static InputStream loadResource( String resourceName ) throws IOException + { + if( log.isDebugEnabled() ) + { + log.debug( "loadResource( " + resourceName + ")" ); + } + + ClassLoader loader = ResourceLoader.class.getClassLoader(); + + InputStream is = null; + + if( loader != null ) + { + is = loader.getResourceAsStream( resourceName ); + } + + //see sourceforge bug 863053, this is a fix for a user that + //needed to have PDFBox loaded by the bootstrap classloader + if( is == null ) + { + loader = ClassLoader.getSystemClassLoader(); + if( loader != null ) + { + is = loader.getResourceAsStream( resourceName ); + } + } + + if( is == null ) + { + File f = new File( resourceName ); + if( f.exists() ) + { + is = new FileInputStream( f ); + } + } + + return is; + } + + /** + * This will attempt to load the resource given the resource name. + * + * @param resourceName The resource to try and load. + * + * @return The resource as a stream or null if it could not be found. + * + * @throws IOException If there is an error loading the properties. + */ + public static Properties loadProperties( String resourceName ) throws IOException + { + Properties properties = null; + InputStream is = null; + try + { + is = loadResource( resourceName ); + if( is != null ) + { + properties = new Properties(); + properties.load( is ); + } + } + finally + { + if( is != null ) + { + is.close(); + } + } + return properties; + } + + /** + * This will attempt to load the resource given the resource name. + * + * @param resourceName The resource to try and load. + * @param defaults A stream of default properties. + * + * @return The resource as a stream or null if it could not be found. + * + * @throws IOException If there is an error loading the properties. + */ + public static Properties loadProperties( String resourceName, Properties defaults ) throws IOException + { + InputStream is = null; + try + { + is = loadResource( resourceName ); + if( is != null ) + { + defaults.load( is ); + } + } + finally + { + if( is != null ) + { + is.close(); + } + } + return defaults; + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/util/SimpleConfigurator.java b/src/main/java/org/pdfbox/util/SimpleConfigurator.java new file mode 100644 index 0000000..df94029 --- /dev/null +++ b/src/main/java/org/pdfbox/util/SimpleConfigurator.java @@ -0,0 +1,68 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + */ +package org.pdfbox.util; + +import java.net.URL; + +import org.apache.log4j.BasicConfigurator; +import org.apache.log4j.Logger; +import org.apache.log4j.Level; + +import org.apache.log4j.spi.Configurator; +import org.apache.log4j.spi.LoggerRepository; + +/** + * Log4J configurator. + * + * @author Robert Dickinson (bob@brutesquadlabs.com) + * @version $Revision: 1.2 $ + */ +public class SimpleConfigurator implements Configurator +{ + /** + * Constructor. + */ + public SimpleConfigurator() + { + } + + /** + * Interpret a resource pointed to by a URL and set up log4J accordingly. + * The configuration is done relative to the heirarchy parameter. + * + * @param url The URL to parse + * @param repository The heirarchy to operate upon + */ + public void doConfigure(URL url, LoggerRepository repository) + { + BasicConfigurator.configure(); + Logger.getRootLogger().setLevel(Level.DEBUG); + } +} diff --git a/src/main/java/org/pdfbox/util/Splitter.java b/src/main/java/org/pdfbox/util/Splitter.java new file mode 100644 index 0000000..c03a989 --- /dev/null +++ b/src/main/java/org/pdfbox/util/Splitter.java @@ -0,0 +1,201 @@ +/** + * Copyright (c) 2004-2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util; + +import org.pdfbox.pdmodel.PDDocument; +import org.pdfbox.pdmodel.PDPage; + +import java.io.IOException; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * Split a document into several other documents. + * + * @author Mario Ivankovits (mario@ops.co.at) + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.6 $ + */ +public class Splitter +{ + + /** + * The source PDF document. + */ + protected PDDocument pdfDocument; + + /** + * The current PDF document that contains the splitted page. + */ + protected PDDocument currentDocument = null; + + private int splitAtPage=1; + private List newDocuments = null; + + /** + * The current page number that we are processing, zero based. + */ + protected int pageNumber = 0; + + /** + * This will take a document and split into several other documents. + * + * @param document The document to split. + * + * @return A list of all the split documents. + * + * @throws IOException If there is an IOError + */ + public List split( PDDocument document ) throws IOException + { + newDocuments = new ArrayList(); + pdfDocument = document; + + List pages = pdfDocument.getDocumentCatalog().getAllPages(); + processPages(pages); + return newDocuments; + } + + /** + * This will tell the splitting algorithm where to split the pages. The default + * is 1, so every page will become a new document. If it was to then each document would + * contain 2 pages. So it the source document had 5 pages it would split into + * 3 new documents, 2 documents containing 2 pages and 1 document containing one + * page. + * + * @param split The number of pages each split document should contain. + */ + public void setSplitAtPage( int split ) + { + if( split <= 0 ) + { + throw new RuntimeException( "Error split must be at least one page." ); + } + splitAtPage = split; + } + + /** + * This will return how many pages each split document will contain. + * + * @return The split parameter. + */ + public int getSplitAtPage() + { + return splitAtPage; + } + + /** + * Interface method to handle the start of the page processing. + * + * @param pages The list of pages from the source document. + * + * @throws IOException If an IO error occurs. + */ + protected void processPages(List pages) throws IOException + { + Iterator iter = pages.iterator(); + while( iter.hasNext() ) + { + PDPage page = (PDPage)iter.next(); + processNextPage( page ); + } + } + + /** + * Interface method, you can control where a document gets split by implementing + * this method. By default a split occurs at every page. If you wanted to split + * based on some complex logic then you could override this method. For example. + * + * protected void createNewDocumentIfNecessary() + * { + * if( isPrime( pageNumber ) ) + * { + * super.createNewDocumentIfNecessary(); + * } + * } + * + * + * @throws IOException If there is an error creating the new document. + */ + protected void createNewDocumentIfNecessary() throws IOException + { + if (isNewDocNecessary()) + { + createNewDocument(); + } + } + + /** + * Check if it is necessary to create a new document. + * + * @return true If a new document should be created. + */ + protected boolean isNewDocNecessary() + { + return pageNumber % splitAtPage == 0 || currentDocument == null; + } + + /** + * Create a new document to write the splitted contents to. + * + * @throws IOException If there is an problem creating the new document. + */ + protected void createNewDocument() throws IOException + { + currentDocument = new PDDocument(); + currentDocument.setDocumentInformation(pdfDocument.getDocumentInformation()); + currentDocument.getDocumentCatalog().setViewerPreferences( + pdfDocument.getDocumentCatalog().getViewerPreferences()); + newDocuments.add(currentDocument); + } + + + + /** + * Interface to start processing a new page. + * + * @param page The page that is about to get processed. + * + * @throws IOException If there is an error creating the new document. + */ + protected void processNextPage( PDPage page ) throws IOException + { + createNewDocumentIfNecessary(); + PDPage imported = currentDocument.importPage( page ); + imported.setCropBox( page.findCropBox() ); + imported.setMediaBox( page.findMediaBox() ); + imported.setResources( page.findResources() ); + imported.setRotation( page.findRotation() ); + pageNumber++; + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/util/TextPosition.java b/src/main/java/org/pdfbox/util/TextPosition.java new file mode 100644 index 0000000..f44ca56 --- /dev/null +++ b/src/main/java/org/pdfbox/util/TextPosition.java @@ -0,0 +1,203 @@ +/** + * Copyright (c) 2003-2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util; + +import org.pdfbox.pdmodel.font.PDFont; + +/** + * This represents a character and a position on the screen of those characters. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.9 $ + */ +public class TextPosition +{ + private float x; + private float y; + private float xScale; + private float yScale; + private float width; + private float widthOfSpace; + private String c; + private PDFont font; + private float fontSize; + private float wordSpacing; + + /** + * Constructor. + * + * @param xPos The x coordinate of the character. + * @param yPos The y coordinate of the character. + * @param xScl The x scaling of the character. + * @param yScl The y scaling of the character. + * @param widthValue The width of the character. + * @param spaceWidth The width of the space character. + * @param string The character to be displayed. + * @param currentFont The current for for this text position. + * @param fontSizeValue The new font size. + * @param ws The word spacing parameter + */ + public TextPosition( + float xPos, + float yPos, + float xScl, + float yScl, + float widthValue, + float spaceWidth, + String string, + PDFont currentFont, + float fontSizeValue, + float ws + ) + { + this.x = xPos; + this.y = yPos; + this.xScale = xScl; + this.yScale = yScl; + this.width = widthValue; + this.widthOfSpace = spaceWidth; + this.c = string; + this.font = currentFont; + this.fontSize = fontSizeValue; + this.wordSpacing = ws; + } + + /** + * This will the character that will be displayed on the screen. + * + * @return The character on the screen. + */ + public String getCharacter() + { + return c; + } + + /** + * This will get the x position of the character. + * + * @return The x coordinate of the character. + */ + public float getX() + { + return x; + } + + /** + * This will get the y position of the character. + * + * @return The y coordinate of the character. + */ + public float getY() + { + return y; + } + + /** + * This will get with width of this character. + * + * @return The width of this character. + */ + public float getWidth() + { + return width; + } + + /** + * This will get the font size that this object is + * suppose to be drawn at. + * + * @return The font size. + */ + public float getFontSize() + { + return fontSize; + } + + /** + * This will get the font for the text being drawn. + * + * @return The font size. + */ + public PDFont getFont() + { + return font; + } + + /** + * This will get the current word spacing. + * + * @return The current word spacing. + */ + public float getWordSpacing() + { + return wordSpacing; + } + + /** + * This will get the width of a space character. This is useful for some + * algorithms such as the text stripper, that need to know the width of a + * space character. + * + * @return The width of a space character. + */ + public float getWidthOfSpace() + { + return widthOfSpace; + } + /** + * @return Returns the xScale. + */ + public float getXScale() + { + return xScale; + } + /** + * @param scale The xScale to set. + */ + public void setXScale(float scale) + { + xScale = scale; + } + /** + * @return Returns the yScale. + */ + public float getYScale() + { + return yScale; + } + /** + * @param scale The yScale to set. + */ + public void setYScale(float scale) + { + yScale = scale; + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/util/TextPositionComparator.java b/src/main/java/org/pdfbox/util/TextPositionComparator.java new file mode 100644 index 0000000..fab6a6e --- /dev/null +++ b/src/main/java/org/pdfbox/util/TextPositionComparator.java @@ -0,0 +1,126 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util; + +import java.util.Comparator; + +import org.pdfbox.pdmodel.PDPage; + +/** + * This class is a comparator for TextPosition operators. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.2 $ + */ +public class TextPositionComparator implements Comparator +{ + private PDPage thePage = null; + + /** + * Constuctor, comparison of TextPosition depends on the rotation + * of the page. + * @param page The page that the text position is on. + */ + public TextPositionComparator( PDPage page ) + { + thePage = page; + } + + /** + * @see Comparator#compare(java.lang.Object, java.lang.Object) + */ + public int compare(Object o1, Object o2) + { + int retval = 0; + TextPosition pos1 = (TextPosition)o1; + TextPosition pos2 = (TextPosition)o2; + int rotation = thePage.findRotation(); + float x1 = 0; + float x2 = 0; + float y1 = 0; + float y2 = 0; + if( rotation == 0 ) + { + x1 = pos1.getX(); + x2 = pos2.getX(); + y1 = pos1.getY(); + y2 = pos2.getY(); + } + else if( rotation == 90 ) + { + x1 = pos1.getY(); + x2 = pos2.getX(); + y1 = pos1.getX(); + y2 = pos2.getY(); + } + else if( rotation == 180 ) + { + x1 = -pos1.getX(); + x2 = -pos2.getX(); + y1 = -pos1.getY(); + y2 = -pos2.getY(); + } + else if( rotation == 270 ) + { + x1 = -pos1.getY(); + x2 = -pos2.getY(); + y1 = -pos1.getX(); + y2 = -pos2.getX(); + } + + if( y1 < y2 ) + { + retval = -1; + } + else if( y1 > y2 ) + { + return 1; + } + else + { + if( x1 < x2 ) + { + retval = -1; + } + else if( x1 > x2 ) + { + retval = 1; + } + else + { + retval = 0; + } + } + + return retval; + } + +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/util/XMLUtil.java b/src/main/java/org/pdfbox/util/XMLUtil.java new file mode 100644 index 0000000..1798aa2 --- /dev/null +++ b/src/main/java/org/pdfbox/util/XMLUtil.java @@ -0,0 +1,103 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util; + +import java.io.InputStream; +import java.io.IOException; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.Text; + +/** + * This class with handle some simple XML operations. + * + * @author blitchfield + * @version $Revision: 1.2 $ + */ +public class XMLUtil +{ + /** + * Utility class, should not be instantiated. + * + */ + private XMLUtil() + { + } + + /** + * This will parse an XML stream and create a DOM document. + * + * @param is The stream to get the XML from. + * @return The DOM document. + * @throws IOException It there is an error creating the dom. + */ + public static Document parse( InputStream is ) throws IOException + { + try + { + DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = builderFactory.newDocumentBuilder(); + return builder.parse( is ); + } + catch( Exception e ) + { + IOException thrown = new IOException( e.getMessage() ); + throw thrown; + } + } + + /** + * This will get the text value of an element. + * + * @param node The node to get the text value for. + * @return The text of the node. + */ + public static String getNodeValue( Element node ) + { + String retval = ""; + NodeList children = node.getChildNodes(); + for( int i=0; iTitre : PDFEngine Modification.

    + *

    Description : Structal modification of the PDFEngine class : +* the long sequence of conditions in processOperator is remplaced +* by this strategy pattern

    + *

    Copyright : Copyright (c) 2004

    + *

    Société : DBGS

    + * @author Huault : huault@free.fr + * @version $Revision: 1.3 $ + */ +public class BeginText extends OperatorProcessor +{ + + private static final Logger LOG = Logger.getLogger(BeginText.class); + + /** + * process : BT : Begin text object. + * @param operator The operator that is being executed. + * @param arguments List + */ + public void process(PDFOperator operator, List arguments) + { + if( LOG.isDebugEnabled() ) + { + LOG.debug(" " + this.toString()+ " from " + context.toString()); + } + context.setTextMatrix( new Matrix()); + context.setTextLineMatrix( new Matrix() ); + } +} diff --git a/src/main/java/org/pdfbox/util/operator/Concatenate.java b/src/main/java/org/pdfbox/util/operator/Concatenate.java new file mode 100644 index 0000000..7fc986c --- /dev/null +++ b/src/main/java/org/pdfbox/util/operator/Concatenate.java @@ -0,0 +1,106 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util.operator; + +import java.util.List; +import org.pdfbox.cos.COSNumber; +import org.apache.log4j.Logger; +import org.pdfbox.util.Matrix; +import org.pdfbox.util.PDFOperator; + +/** + * + *

    Titre : PDFEngine Modification.

    + *

    Description : Structal modification of the PDFEngine class : +* the long sequence of conditions in processOperator is remplaced by +* this strategy pattern

    + *

    Copyright : Copyright (c) 2004

    + *

    Société : DBGS

    + * @author Huault : huault@free.fr + * @version $Revision: 1.3 $ + */ + +public class Concatenate extends OperatorProcessor +{ + + private static final Logger LOG = Logger.getLogger(Concatenate.class); + + /** + * process : cm : Concatenate matrix to current transformation matrix. + * @param operator The operator that is being executed. + * @param arguments List + */ + public void process(PDFOperator operator, List arguments) + { + + //concatenate matrix to current transformation matrix + COSNumber a = (COSNumber) arguments.get(0); + COSNumber b = (COSNumber) arguments.get(1); + COSNumber c = (COSNumber) arguments.get(2); + COSNumber d = (COSNumber) arguments.get(3); + COSNumber e = (COSNumber) arguments.get(4); + COSNumber f = (COSNumber) arguments.get(5); + + if( LOG.isDebugEnabled() ) + { + LOG.debug(" " + + this.toString() + " from " + context.toString()); + } + + Matrix newMatrix = new Matrix(); + newMatrix.setValue(0, 0, a.floatValue()); + newMatrix.setValue(0, 1, b.floatValue()); + newMatrix.setValue(1, 0, c.floatValue()); + newMatrix.setValue(1, 1, d.floatValue()); + newMatrix.setValue(2, 0, e.floatValue()); + newMatrix.setValue(2, 1, f.floatValue()); + + // wprinz: BUG Fix: + // In PDF, matrices have to be multiplied from left to right + // (the new matrix is left, the old one(s) are right) + + Matrix old_ctm = context.getGraphicsState().getCurrentTransformationMatrix(); + Matrix matrix_to_concat = newMatrix; + Matrix new_ctm = matrix_to_concat.multiply(old_ctm); + context.getGraphicsState().setCurrentTransformationMatrix( + new_ctm ); + + // :wprinz + + } + +} diff --git a/src/main/java/org/pdfbox/util/operator/EndText.java b/src/main/java/org/pdfbox/util/operator/EndText.java new file mode 100644 index 0000000..2794ccf --- /dev/null +++ b/src/main/java/org/pdfbox/util/operator/EndText.java @@ -0,0 +1,67 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util.operator; + +import java.util.List; +import org.apache.log4j.Logger; +import org.pdfbox.util.PDFOperator; +/** + * + *

    Titre : PDFEngine Modification.

    + *

    Description : Structal modification of the PDFEngine class : the +* long sequence of conditions in processOperator is remplaced by +* this strategy pattern

    + *

    Copyright : Copyright (c) 2004

    + *

    Société : DBGS

    + * @author Huault : huault@free.fr + * @version $Revision: 1.3 $ + */ +public class EndText extends OperatorProcessor +{ + + private static final Logger LOG = Logger.getLogger(EndText.class); + + /** + * process : ET : End text object. + * @param operator The operator that is being executed. + * @param arguments List + */ + public void process(PDFOperator operator, List arguments) + { + if( LOG.isDebugEnabled() ) + { + LOG.debug(" "+ this.toString()); + } + context.setTextMatrix( null); + context.setTextLineMatrix( null); + } + +} diff --git a/src/main/java/org/pdfbox/util/operator/GRestore.java b/src/main/java/org/pdfbox/util/operator/GRestore.java new file mode 100644 index 0000000..c07b8d8 --- /dev/null +++ b/src/main/java/org/pdfbox/util/operator/GRestore.java @@ -0,0 +1,67 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util.operator; + +import org.apache.log4j.Logger; +import java.util.List; + +import org.pdfbox.pdmodel.graphics.PDGraphicsState; +import org.pdfbox.util.PDFOperator; + +/** + * + *

    Titre : PDFEngine Modification.

    + *

    Description : Structal modification of the PDFEngine class : the long sequence of + * conditions in processOperator is remplaced by this strategy pattern

    + *

    Copyright : Copyright (c) 2004

    + *

    Société : DBGS

    + * @author Huault : huault@free.fr + * @version $Revision: 1.3 $ + */ +public class GRestore extends OperatorProcessor +{ + private static final Logger LOG = Logger.getLogger(GRestore.class); + + + /** + * process : Q : Restore graphics state. + * @param operator The operator that is being executed. + * @param arguments List + */ + public void process(PDFOperator operator, List arguments) + { + if( LOG.isDebugEnabled() ) + { + LOG.debug(" - restore state" + this.toString()); + } + context.setGraphicsState( (PDGraphicsState)context.getGraphicsStack().pop() ); + } +} diff --git a/src/main/java/org/pdfbox/util/operator/GSave.java b/src/main/java/org/pdfbox/util/operator/GSave.java new file mode 100644 index 0000000..6a754b6 --- /dev/null +++ b/src/main/java/org/pdfbox/util/operator/GSave.java @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util.operator; + +import java.util.List; +import org.apache.log4j.Logger; +import org.pdfbox.util.PDFOperator; + +/** + * + *

    Titre : PDFEngine Modification.

    + *

    Description : Structal modification of the PDFEngine class : the long sequence of + * conditions in processOperator is remplaced by this strategy pattern

    + *

    Copyright : Copyright (c) 2004

    + *

    Société : DBGS

    + * @author Huault : huault@free.fr + * @version $Revision: 1.3 $ + */ + +public class GSave extends OperatorProcessor +{ + private static final Logger LOG = Logger.getLogger(GSave.class); + + /** + * process : q : Save graphics state. + * @param operator The operator that is being executed. + * @param arguments List + */ + public void process(PDFOperator operator, List arguments) + { + if( LOG.isDebugEnabled() ) + { + LOG.debug(" - save state " + this.toString()); + } + context.getGraphicsStack().push( context.getGraphicsState().clone() ); + } + +} diff --git a/src/main/java/org/pdfbox/util/operator/Invoke.java b/src/main/java/org/pdfbox/util/operator/Invoke.java new file mode 100644 index 0000000..2f8f789 --- /dev/null +++ b/src/main/java/org/pdfbox/util/operator/Invoke.java @@ -0,0 +1,113 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util.operator; + +import org.apache.log4j.Logger; +import org.pdfbox.cos.COSName; +import org.pdfbox.cos.COSStream; +import org.pdfbox.pdmodel.PDPage; +import org.pdfbox.pdmodel.PDResources; +import org.pdfbox.pdmodel.graphics.xobject.PDXObject; +import org.pdfbox.pdmodel.graphics.xobject.PDXObjectForm; +import org.pdfbox.util.PDFOperator; + +import java.io.IOException; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; +import java.util.Map; + +/** + * Invoke named XObject. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @author Mario Ivankovits + * + * @version $Revision: 1.6 $ + */ +public class Invoke extends OperatorProcessor +{ + private static final Logger LOG = Logger.getLogger(Invoke.class); + + private Set inProcess = new TreeSet(); + + /** + * process : Do - Invoke a named xobject. + * @param operator The operator that is being executed. + * @param arguments List + * + * @throws IOException If there is an error processing this operator. + */ + public void process(PDFOperator operator, List arguments) throws IOException + { + COSName name = (COSName) arguments.get( 0 ); + if (LOG.isDebugEnabled()) + { + LOG.debug(""); + } + + // wprinz: allow recursive processing so that nested xobject forms are correctly dealt with +// if (inProcess.contains(name)) +// { +// // avoid recursive loop +// return; +// } + // /wprinz + + inProcess.add(name); + + try + { + //PDResources res = context.getResources(); + + Map xobjects = context.getXObjects(); + PDXObject xobject = (PDXObject) xobjects.get(name.getName()); + + if(xobject instanceof PDXObjectForm) + { + PDXObjectForm form = (PDXObjectForm)xobject; + COSStream invoke = (COSStream)form.getCOSObject(); + PDResources pdResources = form.getResources(); + PDPage page = context.getCurrentPage(); + if(pdResources == null) + { + pdResources = page.findResources(); + } + + getContext().processSubStream( page, pdResources, invoke ); + } + } + finally + { + inProcess.remove(name); + } + } +} diff --git a/src/main/java/org/pdfbox/util/operator/MoveAndShow.java b/src/main/java/org/pdfbox/util/operator/MoveAndShow.java new file mode 100644 index 0000000..ca3a3f9 --- /dev/null +++ b/src/main/java/org/pdfbox/util/operator/MoveAndShow.java @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util.operator; + +import java.util.List; +import org.apache.log4j.Logger; +import org.pdfbox.cos.COSString; +import org.pdfbox.util.PDFOperator; + +import java.io.IOException; + +/** + *

    Titre : PDFEngine Modification.

    + *

    Description : Structal modification of the PDFEngine class : +* the long sequence of conditions in processOperator is remplaced by +* this strategy pattern

    + *

    Copyright : Copyright (c) 2004

    + *

    Société : DBGS

    + * @author Huault : huault@free.fr + * @version $Revision: 1.4 $ + */ +public class MoveAndShow extends OperatorProcessor +{ + + private static final Logger LOG = Logger.getLogger(MoveAndShow.class); + + /** + * ' Move to next line and show text. + * @param arguments List + * @param operator The operator that is being executed. + * @throws IOException If there is an error processing the operator. + */ + public void process(PDFOperator operator, List arguments) throws IOException + { + // Move to start of next text line, and show text + // + if( LOG.isDebugEnabled()) + { + COSString string = (COSString)arguments.get( 0 ); + LOG.debug("<' string=\"" + string.getString() + "\">"); + } + + context.processOperator("T*", null); + context.processOperator("Tj", arguments); + } + +} diff --git a/src/main/java/org/pdfbox/util/operator/MoveText.java b/src/main/java/org/pdfbox/util/operator/MoveText.java new file mode 100644 index 0000000..10360bb --- /dev/null +++ b/src/main/java/org/pdfbox/util/operator/MoveText.java @@ -0,0 +1,76 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util.operator; + +import java.util.List; +import org.apache.log4j.Logger; +import org.pdfbox.cos.COSNumber; +import org.pdfbox.util.Matrix; +import org.pdfbox.util.PDFOperator; + +/** + * + *

    Titre : PDFEngine Modification.

    + *

    Description : Structal modification of the PDFEngine class : + * the long sequence of conditions in processOperator is remplaced by + * this strategy pattern

    + *

    Copyright : Copyright (c) 2004

    + *

    Société : DBGS

    + * @author Huault : huault@free.fr + * @version $Revision: 1.3 $ + */ +public class MoveText extends OperatorProcessor +{ + private static final Logger LOG = Logger.getLogger(MoveText.class); + + + /** + * process : Td : Move text position. + * @param operator The operator that is being executed. + * @param arguments List + */ + public void process(PDFOperator operator, List arguments) + { + COSNumber x = (COSNumber)arguments.get( 0 ); + COSNumber y = (COSNumber)arguments.get( 1 ); + if (LOG.isDebugEnabled()) + { + LOG.debug(""); + } + Matrix td = new Matrix(); + td.setValue( 2, 0, x.floatValue() );//.* textMatrix.getValue(0,0) ); + td.setValue( 2, 1, y.floatValue() );//* textMatrix.getValue(1,1) ); + //log.debug( "textLineMatrix before " + textLineMatrix ); + context.setTextLineMatrix( td.multiply( context.getTextLineMatrix() ) ); //textLineMatrix.multiply( td ); + //log.debug( "textLineMatrix after " + textLineMatrix ); + context.setTextMatrix( context.getTextLineMatrix().copy() ); + } +} diff --git a/src/main/java/org/pdfbox/util/operator/MoveTextSetLeading.java b/src/main/java/org/pdfbox/util/operator/MoveTextSetLeading.java new file mode 100644 index 0000000..e68a1d1 --- /dev/null +++ b/src/main/java/org/pdfbox/util/operator/MoveTextSetLeading.java @@ -0,0 +1,80 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util.operator; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import org.apache.log4j.Logger; +import org.pdfbox.cos.COSFloat; +import org.pdfbox.cos.COSNumber; +import org.pdfbox.util.PDFOperator; + +/** + * + *

    Titre : PDFEngine Modification.

    + *

    Description : Structal modification of the PDFEngine class : + * the long sequence of conditions in processOperator is remplaced by + * this strategy pattern

    + *

    Copyright : Copyright (c) 2004

    + *

    Société : DBGS

    + * @author Huault : huault@free.fr + * @version $Revision: 1.4 $ + */ +public class MoveTextSetLeading extends OperatorProcessor +{ + + private static final Logger LOG = Logger.getLogger(MoveTextSetLeading.class); + + /** + * process : TD Move text position and set leading. + * @param operator The operator that is being executed. + * @param arguments List + * + * @throws IOException If there is an error during processing. + */ + public void process(PDFOperator operator, List arguments) throws IOException + { + //move text position and set leading + COSNumber y = (COSNumber)arguments.get( 1 ); + if (LOG.isDebugEnabled()) + { + COSNumber x = (COSNumber)arguments.get( 0 ); + LOG.debug(""); + } + + ArrayList args = new ArrayList(); + args.add(new COSFloat(-1*y.floatValue())); + context.processOperator("TL", args); + context.processOperator("Td", arguments); + + } +} diff --git a/src/main/java/org/pdfbox/util/operator/NextLine.java b/src/main/java/org/pdfbox/util/operator/NextLine.java new file mode 100644 index 0000000..daa35eb --- /dev/null +++ b/src/main/java/org/pdfbox/util/operator/NextLine.java @@ -0,0 +1,82 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util.operator; + +import org.apache.log4j.Logger; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.pdfbox.cos.COSFloat; +import org.pdfbox.util.PDFOperator; + +/** + * + *

    Titre : PDFEngine Modification.

    + *

    Description : Structal modification of the PDFEngine class : the long sequence of + * conditions in processOperator is remplaced by this strategy pattern

    + *

    Copyright : Copyright (c) 2004

    + *

    Société : DBGS

    + * @author Huault : huault@free.fr + * @version $Revision: 1.4 $ + */ +public class NextLine extends OperatorProcessor +{ + + private static final Logger LOG = Logger.getLogger(NextLine.class); + + /** + * process : T* Move to start of next text line. + * @param operator The operator that is being executed. + * @param arguments List + * + * @throws IOException If there is an error during processing. + */ + public void process(PDFOperator operator, List arguments) throws IOException + { + + if (LOG.isDebugEnabled()) + { + LOG.debug(""); + } + //move to start of next text line + ArrayList args = new ArrayList(); + args.add(new COSFloat(0.0f)); + // this must be -leading instead of just leading as written in the + // specification (p.369) the acrobat reader seems to implement it the same way + args.add(new COSFloat(-1*context.getGraphicsState().getTextState().getLeading())); + // use Td instead of repeating code + context.processOperator("Td", args); + + } +} diff --git a/src/main/java/org/pdfbox/util/operator/OperatorProcessor.java b/src/main/java/org/pdfbox/util/operator/OperatorProcessor.java new file mode 100644 index 0000000..27c21b9 --- /dev/null +++ b/src/main/java/org/pdfbox/util/operator/OperatorProcessor.java @@ -0,0 +1,93 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util.operator; + +import org.pdfbox.util.PDFOperator; +import org.pdfbox.util.PDFStreamEngine; +import java.util.List; +import java.io.IOException; + +/** + * + *

    Titre : OperatorProcessor

    + *

    Description : This class is the strategy abstract class + * in the strategy GOF pattern. After instancated, you must ever call +* the setContext method to initiamise OPeratorProcessor

    + *

    Copyright : Copyright (c) 2004

    + *

    Société : DBGS

    + * @author Huault : huault@free.fr + * @version $Revision: 1.3 $ + */ +public abstract class OperatorProcessor +{ + + /** + * The stream engine processing context. + */ + protected PDFStreamEngine context = null; + + /** + * Constructor. + * + */ + protected OperatorProcessor() + { + } + + /** + * Get the context for processing. + * + * @return The processing context. + */ + protected PDFStreamEngine getContext() + { + return context; + } + + /** + * Set the processing context. + * + * @param ctx The context for processing. + */ + public void setContext(PDFStreamEngine ctx) + { + context = ctx; + } + + /** + * process the operator. + * @param operator The operator that is being processed. + * @param arguments arguments needed by this operator. + * + * @throws IOException If there is an error processing the operator. + */ + public abstract void process(PDFOperator operator, List arguments) throws IOException; +} diff --git a/src/main/java/org/pdfbox/util/operator/SetCharSpacing.java b/src/main/java/org/pdfbox/util/operator/SetCharSpacing.java new file mode 100644 index 0000000..6813dce --- /dev/null +++ b/src/main/java/org/pdfbox/util/operator/SetCharSpacing.java @@ -0,0 +1,79 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util.operator; + +import java.util.List; +import org.apache.log4j.Logger; +import org.pdfbox.cos.COSNumber; +import org.pdfbox.util.PDFOperator; + +/** + * + *

    Titre : PDFEngine Modification.

    + *

    Description : Structal modification of the PDFEngine class : + * the long sequence of conditions in processOperator is remplaced by + * this strategy pattern

    + *

    Copyright : Copyright (c) 2004

    + *

    Société : DBGS

    + * @author Huault : huault@free.fr + * @version $Revision: 1.4 $ + */ +public class SetCharSpacing extends OperatorProcessor +{ + + private static final Logger LOG = Logger.getLogger(SetCharSpacing.class); + + /** + * process : Tc Set character spacing. + * @param operator The operator that is being executed. + * @param arguments List + */ + public void process(PDFOperator operator, List arguments) + { + //set character spacing + if( arguments.size() > 0 ) + { + //There are some documents which are incorrectly structured, and have + //a wrong number of arguments to this, so we will assume the last argument + //in the list + Object charSpacing = arguments.get( arguments.size()-1 ); + if( charSpacing instanceof COSNumber ) + { + COSNumber characterSpacing = (COSNumber)charSpacing; + if (LOG.isDebugEnabled()) + { + LOG.debug(""); + } + context.getGraphicsState().getTextState().setCharacterSpacing( characterSpacing.floatValue() ); + } + } + } +} diff --git a/src/main/java/org/pdfbox/util/operator/SetGraphicsStateParameters.java b/src/main/java/org/pdfbox/util/operator/SetGraphicsStateParameters.java new file mode 100644 index 0000000..e72e05d --- /dev/null +++ b/src/main/java/org/pdfbox/util/operator/SetGraphicsStateParameters.java @@ -0,0 +1,72 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util.operator; + +import java.util.List; +import org.apache.log4j.Logger; +import org.pdfbox.cos.COSName; +import org.pdfbox.pdmodel.graphics.PDExtendedGraphicsState; +import org.pdfbox.util.PDFOperator; + +import java.io.IOException; + +/** + *

    Structal modification of the PDFEngine class : + * the long sequence of conditions in processOperator is remplaced by + * this strategy pattern.

    + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.3 $ + */ + +public class SetGraphicsStateParameters extends OperatorProcessor +{ + private static final Logger LOG = Logger.getLogger(SetTextFont.class); + + /** + * gs Set parameters from graphics state parameter dictionary. + * @param operator The operator that is being executed. + * @param arguments List + * @throws IOException If an error occurs while processing the font. + */ + public void process(PDFOperator operator, List arguments) throws IOException + { + //set parameters from graphics state parameter dictionary + COSName graphicsName = (COSName)arguments.get( 0 ); + + if (LOG.isDebugEnabled()) + { + LOG.debug("" ); + } + PDExtendedGraphicsState gs = (PDExtendedGraphicsState)context.getGraphicsStates().get( graphicsName.getName() ); + gs.copyIntoGraphicsState( context.getGraphicsState() ); + } +} diff --git a/src/main/java/org/pdfbox/util/operator/SetHorizontalTextScaling.java b/src/main/java/org/pdfbox/util/operator/SetHorizontalTextScaling.java new file mode 100644 index 0000000..bfb9ebe --- /dev/null +++ b/src/main/java/org/pdfbox/util/operator/SetHorizontalTextScaling.java @@ -0,0 +1,64 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util.operator; + +import java.util.List; +import org.apache.log4j.Logger; +import org.pdfbox.cos.COSNumber; +import org.pdfbox.util.PDFOperator; + +import java.io.IOException; + +/** + *

    Structal modification of the PDFEngine class : + * the long sequence of conditions in processOperator is remplaced by + * this strategy pattern.

    + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.3 $ + */ + +public class SetHorizontalTextScaling extends OperatorProcessor +{ + private static final Logger LOG = Logger.getLogger(SetTextFont.class); + + /** + * Tz Set horizontal text scaling. + * @param operator The operator that is being executed. + * @param arguments List + * @throws IOException If an error occurs while processing the font. + */ + public void process(PDFOperator operator, List arguments) throws IOException + { + COSNumber scaling = (COSNumber)arguments.get(0); + context.getGraphicsState().getTextState().setHorizontalScalingPercent( scaling.floatValue() ); + } +} diff --git a/src/main/java/org/pdfbox/util/operator/SetLineWidth.java b/src/main/java/org/pdfbox/util/operator/SetLineWidth.java new file mode 100644 index 0000000..de0576d --- /dev/null +++ b/src/main/java/org/pdfbox/util/operator/SetLineWidth.java @@ -0,0 +1,64 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util.operator; + +import java.util.List; +import org.apache.log4j.Logger; +import org.pdfbox.cos.COSNumber; +import org.pdfbox.util.PDFOperator; + +import java.io.IOException; + +/** + *

    Structal modification of the PDFEngine class : + * the long sequence of conditions in processOperator is remplaced by + * this strategy pattern.

    + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.3 $ + */ + +public class SetLineWidth extends OperatorProcessor +{ + private static final Logger LOG = Logger.getLogger(SetTextFont.class); + + /** + * w Set line width. + * @param operator The operator that is being executed. + * @param arguments List + * @throws IOException If an error occurs while processing the font. + */ + public void process(PDFOperator operator, List arguments) throws IOException + { + COSNumber width = (COSNumber)arguments.get( 0 ); + context.getGraphicsState().setLineWidth( width.doubleValue() ); + } +} diff --git a/src/main/java/org/pdfbox/util/operator/SetMatrix.java b/src/main/java/org/pdfbox/util/operator/SetMatrix.java new file mode 100644 index 0000000..5d5f1f5 --- /dev/null +++ b/src/main/java/org/pdfbox/util/operator/SetMatrix.java @@ -0,0 +1,90 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util.operator; + +import java.util.List; +import org.apache.log4j.Logger; +import org.pdfbox.cos.COSNumber; +import org.pdfbox.util.Matrix; +import org.pdfbox.util.PDFOperator; + +/** + *

    Titre : PDFEngine Modification.

    + *

    Description : Structal modification of the PDFEngine class : the long sequence of conditions + * in processOperator is remplaced by this strategy pattern

    + *

    Copyright : Copyright (c) 2004

    + *

    Société : DBGS

    + * @author Huault : huault@free.fr + * @version $Revision: 1.3 $ + */ + +public class SetMatrix extends OperatorProcessor +{ + + private static final Logger LOG = Logger.getLogger(SetMatrix.class); + + /** + * Tm Set text matrix and text line matrix. + * @param operator The operator that is being executed. + * @param arguments List + */ + public void process(PDFOperator operator, List arguments) + { + //Set text matrix and text line matrix + COSNumber a = (COSNumber)arguments.get( 0 ); + COSNumber b = (COSNumber)arguments.get( 1 ); + COSNumber c = (COSNumber)arguments.get( 2 ); + COSNumber d = (COSNumber)arguments.get( 3 ); + COSNumber e = (COSNumber)arguments.get( 4 ); + COSNumber f = (COSNumber)arguments.get( 5 ); + + if (LOG.isDebugEnabled()) + { + LOG.debug(""); + } + + Matrix textMatrix = new Matrix(); + textMatrix.setValue( 0, 0, a.floatValue() ); + textMatrix.setValue( 0, 1, b.floatValue() ); + textMatrix.setValue( 1, 0, c.floatValue() ); + textMatrix.setValue( 1, 1, d.floatValue() ); + textMatrix.setValue( 2, 0, e.floatValue() ); + textMatrix.setValue( 2, 1, f.floatValue() ); + context.setTextMatrix( textMatrix ); + context.setTextLineMatrix( textMatrix.copy() ); + } +} diff --git a/src/main/java/org/pdfbox/util/operator/SetMoveAndShow.java b/src/main/java/org/pdfbox/util/operator/SetMoveAndShow.java new file mode 100644 index 0000000..b49206d --- /dev/null +++ b/src/main/java/org/pdfbox/util/operator/SetMoveAndShow.java @@ -0,0 +1,80 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util.operator; + +import java.util.List; +import org.apache.log4j.Logger; +import org.pdfbox.cos.COSNumber; +import org.pdfbox.cos.COSString; +import org.pdfbox.util.PDFOperator; + +import java.io.IOException; + +/** + *

    Titre : PDFEngine Modification.

    + *

    Description : Structal modification of the PDFEngine class : the long sequence of conditions + * in processOperator is remplaced by this strategy pattern

    + *

    Copyright : Copyright (c) 2004

    + *

    Société : DBGS

    + * @author Huault : huault@free.fr + * @version $Revision: 1.5 $ + */ + +public class SetMoveAndShow extends OperatorProcessor +{ + + private static final Logger LOG = Logger.getLogger(SetMoveAndShow.class); + + /** + * " Set word and character spacing, move to next line, and show text. + * @param operator The operator that is being executed. + * @param arguments List. + * @throws IOException If there is an error processing the operator. + */ + public void process(PDFOperator operator, List arguments) throws IOException + { + //Set word and character spacing, move to next line, and show text + // + if (LOG.isDebugEnabled()) + { + COSNumber wordSpacing = (COSNumber)arguments.get( 0 ); + COSNumber characterSpacing = (COSNumber)arguments.get( 1 ); + COSString string = (COSString)arguments.get( 2 ); + LOG.debug("<\" wordSpacing=\"" + wordSpacing + + "\", characterSpacing=\"" + characterSpacing + + "\", string=\"" + string.getString() + "\">"); + } + + context.processOperator("Tw", arguments.subList(0,1)); + context.processOperator("Tc", arguments.subList(1,2)); + context.processOperator("'", arguments.subList(2,3)); + } +} diff --git a/src/main/java/org/pdfbox/util/operator/SetNonStrokingCMYKColor.java b/src/main/java/org/pdfbox/util/operator/SetNonStrokingCMYKColor.java new file mode 100644 index 0000000..941fcd6 --- /dev/null +++ b/src/main/java/org/pdfbox/util/operator/SetNonStrokingCMYKColor.java @@ -0,0 +1,69 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util.operator; + +import java.util.List; + +import org.pdfbox.cos.COSNumber; +import org.pdfbox.pdmodel.graphics.color.PDColorSpace; +import org.pdfbox.pdmodel.graphics.color.PDColorSpaceInstance; +import org.pdfbox.pdmodel.graphics.color.PDDeviceCMYK; +import org.pdfbox.util.PDFOperator; + +import java.io.IOException; + +/** + *

    Set the non stroking color space.

    + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.2 $ + */ +public class SetNonStrokingCMYKColor extends OperatorProcessor +{ + /** + * cs Set color space for non stroking operations. + * @param operator The operator that is being executed. + * @param arguments List + * @throws IOException If an error occurs while processing the font. + */ + public void process(PDFOperator operator, List arguments) throws IOException + { + PDColorSpace cs = PDDeviceCMYK.INSTANCE; + PDColorSpaceInstance colorInstance = context.getGraphicsState().getNonStrokingColorSpace(); + colorInstance.setColorSpace( cs ); + float[] values = new float[4]; + for( int i=0; iSet the non stroking color space.

    + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.2 $ + */ +public class SetNonStrokingColorSpace extends OperatorProcessor +{ + private static final float[] EMPTY_FLOAT_ARRAY = new float[0]; + + /** + * cs Set color space for non stroking operations. + * @param operator The operator that is being executed. + * @param arguments List + * @throws IOException If an error occurs while processing the font. + */ + public void process(PDFOperator operator, List arguments) throws IOException + { +// (PDF 1.1) Set color space for stroking operations + COSName name = (COSName)arguments.get( 0 ); + PDColorSpace cs = (PDColorSpace)context.getColorSpaces().get( name.getName() ); + if( cs == null ) + { + cs = PDColorSpaceFactory.createColorSpace( name ); + } + PDColorSpaceInstance colorInstance = context.getGraphicsState().getNonStrokingColorSpace(); + colorInstance.setColorSpace( cs ); + int numComponents = cs.getNumberOfComponents(); + float[] values = EMPTY_FLOAT_ARRAY; + if( numComponents >= 0 ) + { + values = new float[numComponents]; + for( int i=0; iSet the non stroking color space.

    + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.2 $ + */ +public class SetNonStrokingRGBColor extends OperatorProcessor +{ + /** + * rg Set color space for non stroking operations. + * @param operator The operator that is being executed. + * @param arguments List + * @throws IOException If an error occurs while processing the font. + */ + public void process(PDFOperator operator, List arguments) throws IOException + { + PDColorSpace cs = PDDeviceRGB.INSTANCE; + PDColorSpaceInstance colorInstance = context.getGraphicsState().getNonStrokingColorSpace(); + colorInstance.setColorSpace( cs ); + float[] values = new float[3]; + for( int i=0; iStructal modification of the PDFEngine class : + * the long sequence of conditions in processOperator is remplaced by + * this strategy pattern.

    + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.2 $ + */ +public class SetStrokingCMYKColor extends OperatorProcessor +{ + /** + * CS Set color space for stroking operations. + * @param operator The operator that is being executed. + * @param arguments List + * @throws IOException If an error occurs while processing the font. + */ + public void process(PDFOperator operator, List arguments) throws IOException + { + PDColorSpace cs = PDDeviceCMYK.INSTANCE; + PDColorSpaceInstance colorInstance = context.getGraphicsState().getStrokingColorSpace(); + colorInstance.setColorSpace( cs ); + float[] values = new float[4]; + for( int i=0; iStructal modification of the PDFEngine class : + * the long sequence of conditions in processOperator is remplaced by + * this strategy pattern.

    + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.3 $ + */ + +public class SetStrokingColorSpace extends OperatorProcessor +{ + private static final float[] EMPTY_FLOAT_ARRAY = new float[0]; + + /** + * CS Set color space for stroking operations. + * @param operator The operator that is being executed. + * @param arguments List + * @throws IOException If an error occurs while processing the font. + */ + public void process(PDFOperator operator, List arguments) throws IOException + { + //(PDF 1.1) Set color space for stroking operations + COSName name = (COSName)arguments.get( 0 ); + PDColorSpace cs = (PDColorSpace)context.getColorSpaces().get( name.getName() ); + if( cs == null ) + { + cs = PDColorSpaceFactory.createColorSpace( name ); + } + PDColorSpaceInstance colorInstance = context.getGraphicsState().getStrokingColorSpace(); + colorInstance.setColorSpace( cs ); + int numComponents = cs.getNumberOfComponents(); + float[] values = EMPTY_FLOAT_ARRAY; + if( numComponents >= 0 ) + { + values = new float[numComponents]; + for( int i=0; iStructal modification of the PDFEngine class : + * the long sequence of conditions in processOperator is remplaced by + * this strategy pattern.

    + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.2 $ + */ +public class SetStrokingRGBColor extends OperatorProcessor +{ + /** + * RG Set color space for stroking operations. + * @param operator The operator that is being executed. + * @param arguments List + * @throws IOException If an error occurs while processing the font. + */ + public void process(PDFOperator operator, List arguments) throws IOException + { + PDColorSpace cs = PDDeviceRGB.INSTANCE; + PDColorSpaceInstance colorInstance = context.getGraphicsState().getStrokingColorSpace(); + colorInstance.setColorSpace( cs ); + float[] values = new float[3]; + for( int i=0; iTitre : PDFEngine Modification.

    + *

    Description : Structal modification of the PDFEngine class : + * the long sequence of conditions in processOperator is remplaced by + * this strategy pattern

    + *

    Copyright : Copyright (c) 2004

    + *

    Société : DBGS

    + * @author Huault : huault@free.fr + * @version $Revision: 1.4 $ + */ + +public class SetTextFont extends OperatorProcessor +{ + private static final Logger LOG = Logger.getLogger(SetTextFont.class); + + /** + * Tf selectfont Set text font and size. + * @param operator The operator that is being executed. + * @param arguments List + * @throws IOException If an error occurs while processing the font. + */ + public void process(PDFOperator operator, List arguments) throws IOException + { + //there are some documents that are incorrectly structured and + //arguments are in the wrong spot, so we will silently ignore them + //if there are no arguments + if( arguments.size() >= 2 ) + { + //set font and size + COSName fontName = (COSName)arguments.get( 0 ); + float fontSize = ((COSNumber)arguments.get( 1 ) ).floatValue(); + context.getGraphicsState().getTextState().setFontSize( fontSize ); + + if (LOG.isDebugEnabled()) + { + LOG.debug(""); + } + + //old way + //graphicsState.getTextState().getFont() = (COSObject)stream.getDictionaryObject( fontName ); + //if( graphicsState.getTextState().getFont() == null ) + //{ + // graphicsState.getTextState().getFont() = (COSObject)graphicsState.getTextState().getFont() + // Dictionary.getItem( fontName ); + //} + context.getGraphicsState().getTextState().setFont( (PDFont)context.getFonts().get( fontName.getName() ) ); + if( context.getGraphicsState().getTextState().getFont() == null ) + { + throw new IOException( "Error: Could not find font(" + fontName + ") in map=" + context.getFonts() ); + } + } + } + +} diff --git a/src/main/java/org/pdfbox/util/operator/SetTextLeading.java b/src/main/java/org/pdfbox/util/operator/SetTextLeading.java new file mode 100644 index 0000000..928172b --- /dev/null +++ b/src/main/java/org/pdfbox/util/operator/SetTextLeading.java @@ -0,0 +1,69 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util.operator; + +import java.util.List; +import org.apache.log4j.Logger; +import org.pdfbox.cos.COSNumber; +import org.pdfbox.util.PDFOperator; + +/** + *

    Titre : PDFEngine Modification.

    + *

    Description : Structal modification of the PDFEngine class : +* the long sequence of conditions in processOperator is remplaced +* by this strategy pattern

    + *

    Copyright : Copyright (c) 2004

    + *

    Société : DBGS

    + * @author Huault : huault@free.fr + * @version $Revision: 1.3 $ + */ + +public class SetTextLeading extends OperatorProcessor +{ + + private static final Logger LOG = Logger.getLogger(SetTextLeading.class); + + /** + * TL Set text leading. + * @param operator The operator that is being executed. + * @param arguments List + */ + public void process(PDFOperator operator, List arguments) + { + COSNumber leading = (COSNumber)arguments.get( 0 ); + context.getGraphicsState().getTextState().setLeading( leading.floatValue() ); + if (LOG.isDebugEnabled()) + { + LOG.debug(""); + } + } + +} diff --git a/src/main/java/org/pdfbox/util/operator/SetTextRenderingMode.java b/src/main/java/org/pdfbox/util/operator/SetTextRenderingMode.java new file mode 100644 index 0000000..19da1e2 --- /dev/null +++ b/src/main/java/org/pdfbox/util/operator/SetTextRenderingMode.java @@ -0,0 +1,64 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util.operator; + +import java.util.List; +import org.apache.log4j.Logger; +import org.pdfbox.cos.COSNumber; +import org.pdfbox.util.PDFOperator; + +import java.io.IOException; + +/** + *

    Structal modification of the PDFEngine class : + * the long sequence of conditions in processOperator is remplaced by + * this strategy pattern.

    + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.3 $ + */ + +public class SetTextRenderingMode extends OperatorProcessor +{ + private static final Logger LOG = Logger.getLogger(SetTextFont.class); + + /** + * Tr Set text rendering mode. + * @param operator The operator that is being executed. + * @param arguments List + * @throws IOException If an error occurs while processing the font. + */ + public void process(PDFOperator operator, List arguments) throws IOException + { + COSNumber mode = (COSNumber)arguments.get( 0 ); + context.getGraphicsState().getTextState().setRenderingMode( mode.intValue() ); + } +} diff --git a/src/main/java/org/pdfbox/util/operator/SetTextRise.java b/src/main/java/org/pdfbox/util/operator/SetTextRise.java new file mode 100644 index 0000000..0d1e884 --- /dev/null +++ b/src/main/java/org/pdfbox/util/operator/SetTextRise.java @@ -0,0 +1,64 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util.operator; + +import java.util.List; +import org.apache.log4j.Logger; +import org.pdfbox.cos.COSNumber; +import org.pdfbox.util.PDFOperator; + +import java.io.IOException; + +/** + *

    Structal modification of the PDFEngine class : + * the long sequence of conditions in processOperator is remplaced by + * this strategy pattern.

    + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.3 $ + */ + +public class SetTextRise extends OperatorProcessor +{ + private static final Logger LOG = Logger.getLogger(SetTextFont.class); + + /** + * Ts Set text rise. + * @param operator The operator that is being executed. + * @param arguments List + * @throws IOException If an error occurs while processing the font. + */ + public void process(PDFOperator operator, List arguments) throws IOException + { + COSNumber rise = (COSNumber)arguments.get(0); + context.getGraphicsState().getTextState().setRise( rise.floatValue() ); + } +} diff --git a/src/main/java/org/pdfbox/util/operator/SetWordSpacing.java b/src/main/java/org/pdfbox/util/operator/SetWordSpacing.java new file mode 100644 index 0000000..3a1e176 --- /dev/null +++ b/src/main/java/org/pdfbox/util/operator/SetWordSpacing.java @@ -0,0 +1,68 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util.operator; + +import java.util.List; +import org.apache.log4j.Logger; +import org.pdfbox.cos.COSNumber; +import org.pdfbox.util.PDFOperator; + +/** + *

    Titre : PDFEngine Modification.

    + *

    Description : Structal modification of the PDFEngine class : the long sequence of + * conditions in processOperator is remplaced by this strategy pattern

    + *

    Copyright : Copyright (c) 2004

    + *

    Société : DBGS

    + * @author Huault : huault@free.fr + * @version $Revision: 1.3 $ + */ + +public class SetWordSpacing extends OperatorProcessor +{ + private static final Logger LOG = Logger.getLogger(SetWordSpacing.class); + + /** + * Tw Set word spacing. + * @param operator The operator that is being executed. + * @param arguments List + */ + public void process(PDFOperator operator, List arguments) + { + //set word spacing + COSNumber wordSpacing = (COSNumber)arguments.get( 0 ); + if (LOG.isDebugEnabled()) + { + LOG.debug(""); + } + context.getGraphicsState().getTextState().setWordSpacing( wordSpacing.floatValue() ); + } + +} diff --git a/src/main/java/org/pdfbox/util/operator/ShowText.java b/src/main/java/org/pdfbox/util/operator/ShowText.java new file mode 100644 index 0000000..1889259 --- /dev/null +++ b/src/main/java/org/pdfbox/util/operator/ShowText.java @@ -0,0 +1,73 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util.operator; + +import java.util.List; +import org.apache.log4j.Logger; +import org.pdfbox.cos.COSString; +import org.pdfbox.util.PDFOperator; + +import java.io.IOException; + +/** + *

    Titre : PDFEngine Modification.

    + *

    Description : Structal modification of the PDFEngine class : + * the long sequence of conditions in processOperator + * is remplaced by this strategy pattern

    + *

    Copyright : Copyright (c) 2004

    + *

    Société : DBGS

    + * @author Huault : huault@free.fr + * @version $Revision: 1.3 $ + */ + +public class ShowText extends OperatorProcessor +{ + + private static final Logger LOG = Logger.getLogger(ShowText.class); + + /** + * Tj show Show text. + * @param operator The operator that is being executed. + * @param arguments List + * + * @throws IOException If there is an error processing this operator. + */ + public void process(PDFOperator operator, List arguments) throws IOException + { + COSString string = (COSString)arguments.get( 0 ); + context.showString( string.getBytes() ); + if (LOG.isDebugEnabled()) + { + LOG.debug(""); + } + } + +} diff --git a/src/main/java/org/pdfbox/util/operator/ShowTextGlyph.java b/src/main/java/org/pdfbox/util/operator/ShowTextGlyph.java new file mode 100644 index 0000000..cf22e11 --- /dev/null +++ b/src/main/java/org/pdfbox/util/operator/ShowTextGlyph.java @@ -0,0 +1,99 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util.operator; + +import java.util.List; +import org.apache.log4j.Logger; +import org.pdfbox.util.Matrix; +import org.pdfbox.util.PDFOperator; +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSNumber; +import java.io.IOException; +import org.pdfbox.cos.COSString; + +/** + *

    Titre : PDFEngine Modification.

    + *

    Description : Structal modification of the PDFEngine class : the long sequence of + * conditions in processOperator is remplaced by this strategy pattern

    + *

    Copyright : Copyright (c) 2004

    + *

    Société : DBGS

    + * @author Huault : huault@free.fr + * @version $Revision: 1.5 $ + */ + +public class ShowTextGlyph extends OperatorProcessor +{ + private static final Logger LOG = Logger.getLogger(ShowTextGlyph.class); + + /** + * TJ Show text, allowing individual glyph positioning. + * @param operator The operator that is being executed. + * @param arguments List + * @throws IOException If there is an error processing this operator. + */ + public void process(PDFOperator operator, List arguments) throws IOException + { + COSArray array = (COSArray)arguments.get( 0 ); + float adjustment=0; + for( int i=0; i + + + + + +This package contains implementations of all of the PDF operators. + + diff --git a/src/main/java/org/pdfbox/util/operator/pagedrawer/AppendRectangleToPath.java b/src/main/java/org/pdfbox/util/operator/pagedrawer/AppendRectangleToPath.java new file mode 100644 index 0000000..7d2d49f --- /dev/null +++ b/src/main/java/org/pdfbox/util/operator/pagedrawer/AppendRectangleToPath.java @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util.operator.pagedrawer; + +import java.awt.geom.Rectangle2D; +import java.util.List; + +import org.pdfbox.cos.COSNumber; +import org.pdfbox.pdfviewer.PageDrawer; +import org.pdfbox.util.PDFOperator; +import org.pdfbox.util.operator.OperatorProcessor; + +/** + * Implementation of content stream operator for page drawer. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.1 $ + */ +public class AppendRectangleToPath extends OperatorProcessor +{ + + + /** + * process : re : append rectangle to path. + * @param operator The operator that is being executed. + * @param arguments List + */ + public void process(PDFOperator operator, List arguments) + { + PageDrawer drawer = (PageDrawer)context; + + COSNumber x = (COSNumber)arguments.get( 0 ); + COSNumber y = (COSNumber)arguments.get( 1 ); + COSNumber w = (COSNumber)arguments.get( 2 ); + COSNumber h = (COSNumber)arguments.get( 3 ); + Rectangle2D rect = new Rectangle2D.Double( + x.doubleValue(), + drawer.fixY( x.doubleValue(), y.doubleValue())-h.doubleValue(), + w.doubleValue()+1, + h.doubleValue()+1); + drawer.getLinePath().reset(); + + drawer.getLinePath().append( rect, false ); + //graphics.drawRect((int)x.doubleValue(), (int)(pageSize.getHeight() - y.doubleValue()), + // (int)w.doubleValue(),(int)h.doubleValue() ); + //System.out.println( "" ); + } +} diff --git a/src/main/java/org/pdfbox/util/operator/pagedrawer/BeginInlineImage.java b/src/main/java/org/pdfbox/util/operator/pagedrawer/BeginInlineImage.java new file mode 100644 index 0000000..9031345 --- /dev/null +++ b/src/main/java/org/pdfbox/util/operator/pagedrawer/BeginInlineImage.java @@ -0,0 +1,114 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util.operator.pagedrawer; + +import java.awt.Graphics2D; +import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.util.List; + +import org.pdfbox.pdfviewer.PageDrawer; +import org.pdfbox.pdmodel.graphics.xobject.PDInlinedImage; +import org.pdfbox.util.ImageParameters; +import org.pdfbox.util.Matrix; +import org.pdfbox.util.PDFOperator; +import org.pdfbox.util.operator.OperatorProcessor; + +/** + * Implementation of content stream operator for page drawer. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.1 $ + */ +public class BeginInlineImage extends OperatorProcessor +{ + + + /** + * process : BI : begin inline image. + * @param operator The operator that is being executed. + * @param arguments List + * @throws IOException If there is an error displaying the inline image. + */ + public void process(PDFOperator operator, List arguments) throws IOException + { + PageDrawer drawer = (PageDrawer)context; + Graphics2D graphics = drawer.getGraphics(); + //begin inline image object + ImageParameters params = operator.getImageParameters(); + PDInlinedImage image = new PDInlinedImage(); + image.setImageParameters( params ); + image.setImageData( operator.getImageData() ); + BufferedImage awtImage = image.createImage(); + + Matrix ctm = drawer.getGraphicsState().getCurrentTransformationMatrix(); + + int width = awtImage.getWidth(); + int height = awtImage.getHeight(); + + + AffineTransform at = new AffineTransform( + ctm.getValue(0,0)/width, + ctm.getValue(0,1), + ctm.getValue(1,0), + ctm.getValue(1,1)/height, + ctm.getValue(2,0), + ctm.getValue(2,1) + ); + //at.setToRotation((double)page.getRotation()); + + + // The transformation should be done + // 1 - Translation + // 2 - Rotation + // 3 - Scale or Skew + //AffineTransform at = new AffineTransform(); + + // Translation + //at = new AffineTransform(); + //at.setToTranslation((double)ctm.getValue(0,0), + // (double)ctm.getValue(0,1)); + + // Rotation + //AffineTransform toAdd = new AffineTransform(); + //toAdd.setToRotation(1.5705); + //toAdd.setToRotation(ctm.getValue(2,0)*(Math.PI/180)); + //at.concatenate(toAdd); + + // Scale / Skew? + //toAdd.setToScale(width, height); + //at.concatenate(toAdd); + //at.setToScale( width, height ); + graphics.drawImage( awtImage, at, null ); + //graphics.drawImage( awtImage,0,0, width,height,null); + } +} diff --git a/src/main/java/org/pdfbox/util/operator/pagedrawer/ClosePath.java b/src/main/java/org/pdfbox/util/operator/pagedrawer/ClosePath.java new file mode 100644 index 0000000..418af6d --- /dev/null +++ b/src/main/java/org/pdfbox/util/operator/pagedrawer/ClosePath.java @@ -0,0 +1,59 @@ +/** + * Copyright (c) 2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util.operator.pagedrawer; + +import java.util.List; + +import org.pdfbox.pdfviewer.PageDrawer; +import org.pdfbox.util.PDFOperator; +import org.pdfbox.util.operator.OperatorProcessor; + +/** + * Implementation of content stream operator for page drawer. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.1 $ + */ +public class ClosePath extends OperatorProcessor +{ + + + /** + * process : h : Close path. + * @param operator The operator that is being executed. + * @param arguments List + */ + public void process(PDFOperator operator, List arguments) + { + PageDrawer drawer = (PageDrawer)context; + drawer.getLinePath().closePath(); + } +} diff --git a/src/main/java/org/pdfbox/util/operator/pagedrawer/CurveTo.java b/src/main/java/org/pdfbox/util/operator/pagedrawer/CurveTo.java new file mode 100644 index 0000000..c056b91 --- /dev/null +++ b/src/main/java/org/pdfbox/util/operator/pagedrawer/CurveTo.java @@ -0,0 +1,73 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util.operator.pagedrawer; + +import java.util.List; + +import org.pdfbox.cos.COSNumber; +import org.pdfbox.pdfviewer.PageDrawer; +import org.pdfbox.util.PDFOperator; +import org.pdfbox.util.operator.OperatorProcessor; + +/** + * Implementation of content stream operator for page drawer. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.1 $ + */ +public class CurveTo extends OperatorProcessor +{ + + + /** + * process : c : Append curved segment to path. + * @param operator The operator that is being executed. + * @param arguments List + */ + public void process(PDFOperator operator, List arguments) + { + PageDrawer drawer = (PageDrawer)context; + + COSNumber x1 = (COSNumber)arguments.get( 0 ); + COSNumber y1 = (COSNumber)arguments.get( 1 ); + COSNumber x2 = (COSNumber)arguments.get( 2 ); + COSNumber y2 = (COSNumber)arguments.get( 3 ); + COSNumber x3 = (COSNumber)arguments.get( 4 ); + COSNumber y3 = (COSNumber)arguments.get( 5 ); + float x1f = x1.floatValue(); + float y1f = (float)drawer.fixY( x1f, y1.floatValue() ); + float x2f = x2.floatValue(); + float y2f = (float)drawer.fixY( x2f, y2.floatValue() ); + float x3f = x3.floatValue(); + float y3f = (float)drawer.fixY( x3f, y3.floatValue() ); + drawer.getLinePath().curveTo(x1f,y1f,x2f,y2f,x3f,y3f); + } +} diff --git a/src/main/java/org/pdfbox/util/operator/pagedrawer/CurveToReplicateFinalPoint.java b/src/main/java/org/pdfbox/util/operator/pagedrawer/CurveToReplicateFinalPoint.java new file mode 100644 index 0000000..670cdb3 --- /dev/null +++ b/src/main/java/org/pdfbox/util/operator/pagedrawer/CurveToReplicateFinalPoint.java @@ -0,0 +1,69 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util.operator.pagedrawer; + +import java.util.List; + +import org.pdfbox.cos.COSNumber; +import org.pdfbox.pdfviewer.PageDrawer; +import org.pdfbox.util.PDFOperator; +import org.pdfbox.util.operator.OperatorProcessor; + +/** + * Implementation of content stream operator for page drawer. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.1 $ + */ +public class CurveToReplicateFinalPoint extends OperatorProcessor +{ + + + /** + * process : y : Append curved segment to path (final point replicated). + * @param operator The operator that is being executed. + * @param arguments List + */ + public void process(PDFOperator operator, List arguments) + { + PageDrawer drawer = (PageDrawer)context; + + COSNumber x1 = (COSNumber)arguments.get( 0 ); + COSNumber y1 = (COSNumber)arguments.get( 1 ); + COSNumber x3 = (COSNumber)arguments.get( 2 ); + COSNumber y3 = (COSNumber)arguments.get( 3 ); + float x1f = x1.floatValue(); + float y1f = (float)drawer.fixY( x1f, y1.floatValue() ); + float x3f = x3.floatValue(); + float y3f = (float)drawer.fixY( x3f, y3.floatValue() ); + drawer.getLinePath().curveTo(x1f,y1f,x3f,y3f,x3f,y3f); + } +} diff --git a/src/main/java/org/pdfbox/util/operator/pagedrawer/CurveToReplicateInitialPoint.java b/src/main/java/org/pdfbox/util/operator/pagedrawer/CurveToReplicateInitialPoint.java new file mode 100644 index 0000000..ff354d0 --- /dev/null +++ b/src/main/java/org/pdfbox/util/operator/pagedrawer/CurveToReplicateInitialPoint.java @@ -0,0 +1,76 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util.operator.pagedrawer; + +import java.awt.geom.GeneralPath; +import java.awt.geom.Point2D; +import java.util.List; + +import org.pdfbox.cos.COSNumber; +import org.pdfbox.pdfviewer.PageDrawer; +import org.pdfbox.util.PDFOperator; +import org.pdfbox.util.operator.OperatorProcessor; + +/** + * Implementation of content stream operator for page drawer. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.1 $ + */ +public class CurveToReplicateInitialPoint extends OperatorProcessor +{ + + + /** + * process : v : Append curved segment to path (initial point replicated). + * @param operator The operator that is being executed. + * @param arguments List + */ + public void process(PDFOperator operator, List arguments) + { + PageDrawer drawer = (PageDrawer)context; + + COSNumber x2 = (COSNumber)arguments.get( 0 ); + COSNumber y2 = (COSNumber)arguments.get( 1 ); + COSNumber x3 = (COSNumber)arguments.get( 2 ); + COSNumber y3 = (COSNumber)arguments.get( 3 ); + float x2f = x2.floatValue(); + float y2f = (float)drawer.fixY( x2f, y2.floatValue() ); + float x3f = x3.floatValue(); + float y3f = (float)drawer.fixY( x3f, y3.floatValue() ); + + GeneralPath path = drawer.getLinePath(); + Point2D currentPoint = path.getCurrentPoint(); + float currentX = (float)currentPoint.getX(); + float currentY = (float)currentPoint.getY(); + drawer.getLinePath().curveTo(currentX,currentY,x2f,y2f,x3f,y3f); + } +} diff --git a/src/main/java/org/pdfbox/util/operator/pagedrawer/FillEvenOddRule.java b/src/main/java/org/pdfbox/util/operator/pagedrawer/FillEvenOddRule.java new file mode 100644 index 0000000..da9e834 --- /dev/null +++ b/src/main/java/org/pdfbox/util/operator/pagedrawer/FillEvenOddRule.java @@ -0,0 +1,71 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util.operator.pagedrawer; + +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.geom.GeneralPath; +import java.util.List; + +import org.pdfbox.pdfviewer.PageDrawer; +import org.pdfbox.util.PDFOperator; +import org.pdfbox.util.operator.OperatorProcessor; + +/** + * Implementation of content stream operator for page drawer. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.1 $ + */ +public class FillEvenOddRule extends OperatorProcessor +{ + + + /** + * process : f* : fill path using even odd rule. + * @param operator The operator that is being executed. + * @param arguments List + */ + public void process(PDFOperator operator, List arguments) + { +// NOTE:changes here should probably also be made to FillNonZeroRule + PageDrawer drawer = (PageDrawer)context; + Graphics2D graphics = drawer.getGraphics(); + //linePath.closePath(); + graphics.setColor( drawer.getNonStrokingColor() ); + drawer.getLinePath().setWindingRule( GeneralPath.WIND_EVEN_ODD ); + graphics.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF ); + //else + //{ + graphics.fill( drawer.getLinePath() ); + //} + } +} diff --git a/src/main/java/org/pdfbox/util/operator/pagedrawer/FillNonZeroRule.java b/src/main/java/org/pdfbox/util/operator/pagedrawer/FillNonZeroRule.java new file mode 100644 index 0000000..56efa33 --- /dev/null +++ b/src/main/java/org/pdfbox/util/operator/pagedrawer/FillNonZeroRule.java @@ -0,0 +1,71 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util.operator.pagedrawer; + +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.geom.GeneralPath; +import java.util.List; + +import org.pdfbox.pdfviewer.PageDrawer; +import org.pdfbox.util.PDFOperator; +import org.pdfbox.util.operator.OperatorProcessor; + +/** + * Implementation of content stream operator for page drawer. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.1 $ + */ +public class FillNonZeroRule extends OperatorProcessor +{ + + + /** + * process : F/f : fill path using non zero winding rule. + * @param operator The operator that is being executed. + * @param arguments List + */ + public void process(PDFOperator operator, List arguments) + { + //NOTE:changes here should probably also be made to FillEvenOddRule + PageDrawer drawer = (PageDrawer)context; + Graphics2D graphics = drawer.getGraphics(); + //linePath.closePath(); + graphics.setColor( drawer.getNonStrokingColor() ); + drawer.getLinePath().setWindingRule( GeneralPath.WIND_NON_ZERO ); + graphics.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF ); + //else + //{ + graphics.fill( drawer.getLinePath() ); + //} + } +} diff --git a/src/main/java/org/pdfbox/util/operator/pagedrawer/Invoke.java b/src/main/java/org/pdfbox/util/operator/pagedrawer/Invoke.java new file mode 100644 index 0000000..3d99b74 --- /dev/null +++ b/src/main/java/org/pdfbox/util/operator/pagedrawer/Invoke.java @@ -0,0 +1,180 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util.operator.pagedrawer; + +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import org.apache.log4j.Logger; +import org.pdfbox.cos.COSName; +import org.pdfbox.pdfviewer.PageDrawer; +import org.pdfbox.pdmodel.PDPage; +import org.pdfbox.pdmodel.graphics.xobject.PDXObject; +import org.pdfbox.pdmodel.graphics.xobject.PDXObjectImage; +import org.pdfbox.util.Matrix; +import org.pdfbox.util.PDFOperator; +import org.pdfbox.util.operator.OperatorProcessor; + +/** + * Implementation of content stream operator for page drawer. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.1 $ + */ +public class Invoke extends OperatorProcessor +{ + private static Logger log = Logger.getLogger( Invoke.class ); + + /** + * process : re : append rectangle to path. + * @param operator The operator that is being executed. + * @param arguments List + * @throws IOException If there is an error invoking the sub object. + */ + public void process(PDFOperator operator, List arguments) throws IOException + { + PageDrawer drawer = (PageDrawer)context; + PDPage page = drawer.getPage(); + Dimension pageSize = drawer.getPageSize(); + Graphics2D graphics = drawer.getGraphics(); + COSName objectName = (COSName)arguments.get( 0 ); + Map xobjects = drawer.getResources().getXObjects(); + PDXObject xobject = (PDXObject)xobjects.get( objectName.getName() ); + if( xobject instanceof PDXObjectImage ) + { + PDXObjectImage image = (PDXObjectImage)xobject; + try + { + BufferedImage awtImage = image.getRGBImage(); + Matrix ctm = drawer.getGraphicsState().getCurrentTransformationMatrix(); + + int width = awtImage.getWidth(); + int height = awtImage.getHeight(); + + double rotationInRadians =(page.findRotation() * Math.PI)/180; + + + AffineTransform rotation = new AffineTransform(); + rotation.setToRotation( rotationInRadians ); + AffineTransform rotationInverse = rotation.createInverse(); + Matrix rotationInverseMatrix = new Matrix(); + rotationInverseMatrix.setFromAffineTransform( rotationInverse ); + Matrix rotationMatrix = new Matrix(); + rotationMatrix.setFromAffineTransform( rotation ); + + Matrix unrotatedCTM = ctm.multiply( rotationInverseMatrix ); + + Matrix scalingParams = unrotatedCTM.extractScaling(); + Matrix scalingMatrix = Matrix.getScaleInstance(1f/width,1f/height); + scalingParams = scalingParams.multiply( scalingMatrix ); + + Matrix translationParams = unrotatedCTM.extractTranslating(); + Matrix translationMatrix = null; + int pageRotation = page.findRotation(); + if( pageRotation == 0 ) + { + translationParams.setValue(2,1, -translationParams.getValue( 2,1 )); + translationMatrix = Matrix.getTranslatingInstance( + 0, (float)pageSize.getHeight()-height*scalingParams.getYScale() ); + } + else if( pageRotation == 90 ) + { + translationMatrix = Matrix.getTranslatingInstance( 0, (float)pageSize.getHeight() ); + } + else + { + //TODO need to figure out other cases + } + translationParams = translationParams.multiply( translationMatrix ); + + AffineTransform at = new AffineTransform( + scalingParams.getValue( 0,0), 0, + 0, scalingParams.getValue( 1, 1), + translationParams.getValue(2,0), translationParams.getValue( 2,1 ) + ); + + + + + //at.setToTranslation( pageSize.getHeight()-ctm.getValue(2,0),ctm.getValue(2,1) ); + //at.setToScale( ctm.getValue(0,0)/width, ctm.getValue(1,1)/height); + //at.setToRotation( (page.findRotation() * Math.PI)/180 ); + + + + //AffineTransform rotation = new AffineTransform(); + //rotation.rotate( (90*Math.PI)/180); + + /* + + // The transformation should be done + // 1 - Translation + // 2 - Rotation + // 3 - Scale or Skew + AffineTransform at = new AffineTransform(); + + // Translation + at = new AffineTransform(); + //at.setToTranslation((double)ctm.getValue(0,0), + // (double)ctm.getValue(0,1)); + + // Rotation + //AffineTransform toAdd = new AffineTransform(); + toAdd.setToRotation(1.5705); + toAdd.setToRotation(ctm.getValue(2,0)*(Math.PI/180)); + at.concatenate(toAdd); + */ + + // Scale / Skew? + //toAdd.setToScale(1, 1); + //at.concatenate(toAdd); + + graphics.drawImage( awtImage, at, null ); + } + catch( Exception e ) + { + e.printStackTrace(); + } + } + else + { + log.warn( "Unknown xobject type:" + xobject ); + } + + + //invoke named object. + } +} diff --git a/src/main/java/org/pdfbox/util/operator/pagedrawer/LineTo.java b/src/main/java/org/pdfbox/util/operator/pagedrawer/LineTo.java new file mode 100644 index 0000000..a70099b --- /dev/null +++ b/src/main/java/org/pdfbox/util/operator/pagedrawer/LineTo.java @@ -0,0 +1,65 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util.operator.pagedrawer; + +import java.util.List; + +import org.pdfbox.cos.COSNumber; +import org.pdfbox.pdfviewer.PageDrawer; +import org.pdfbox.util.PDFOperator; +import org.pdfbox.util.operator.OperatorProcessor; + +/** + * Implementation of content stream operator for page drawer. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.1 $ + */ +public class LineTo extends OperatorProcessor +{ + + + /** + * process : l : Append straight line segment to path. + * @param operator The operator that is being executed. + * @param arguments List + */ + public void process(PDFOperator operator, List arguments) + { + PageDrawer drawer = (PageDrawer)context; + + //append straight line segment from the current point to the point. + COSNumber x = (COSNumber)arguments.get( 0 ); + COSNumber y = (COSNumber)arguments.get( 1 ); + + drawer.getLinePath().lineTo( x.floatValue(), (float)drawer.fixY( x.doubleValue(), y.doubleValue()) ); + } +} diff --git a/src/main/java/org/pdfbox/util/operator/pagedrawer/MoveTo.java b/src/main/java/org/pdfbox/util/operator/pagedrawer/MoveTo.java new file mode 100644 index 0000000..e1c8f1e --- /dev/null +++ b/src/main/java/org/pdfbox/util/operator/pagedrawer/MoveTo.java @@ -0,0 +1,68 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util.operator.pagedrawer; + +import java.awt.geom.GeneralPath; +import java.util.List; + +import org.pdfbox.cos.COSNumber; +import org.pdfbox.pdfviewer.PageDrawer; +import org.pdfbox.util.PDFOperator; +import org.pdfbox.util.operator.OperatorProcessor; + +/** + * Implementation of content stream operator for page drawer. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.1 $ + */ +public class MoveTo extends OperatorProcessor +{ + + + /** + * process : m : Begin new subpath. + * @param operator The operator that is being executed. + * @param arguments List + */ + public void process(PDFOperator operator, List arguments) + { + PageDrawer drawer = (PageDrawer)context; + + COSNumber x = (COSNumber)arguments.get( 0 ); + COSNumber y = (COSNumber)arguments.get( 1 ); + + drawer.getLineSubPaths().add( drawer.getLinePath() ); + GeneralPath newPath = new GeneralPath(); + newPath.moveTo( x.floatValue(), (float)drawer.fixY( x.doubleValue(), y.doubleValue()) ); + drawer.setLinePath( newPath ); + } +} diff --git a/src/main/java/org/pdfbox/util/operator/pagedrawer/SetLineWidth.java b/src/main/java/org/pdfbox/util/operator/pagedrawer/SetLineWidth.java new file mode 100644 index 0000000..4217451 --- /dev/null +++ b/src/main/java/org/pdfbox/util/operator/pagedrawer/SetLineWidth.java @@ -0,0 +1,65 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util.operator.pagedrawer; + +import java.util.List; +import org.pdfbox.pdfviewer.PageDrawer; +import org.pdfbox.util.PDFOperator; + +import java.awt.BasicStroke; +import java.io.IOException; + +/** + * Implementation of content stream operator for page drawer. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.1 $ + */ +public class SetLineWidth extends org.pdfbox.util.operator.SetLineWidth +{ + + /** + * w Set line width. + * @param operator The operator that is being executed. + * @param arguments List + * @throws IOException If an error occurs while processing the font. + */ + public void process(PDFOperator operator, List arguments) throws IOException + { + super.process( operator, arguments ); + float lineWidth = (float)context.getGraphicsState().getLineWidth(); + if( lineWidth == 0 ) + { + lineWidth = 1; + } + ((PageDrawer)context).getGraphics().setStroke( new BasicStroke( lineWidth ) ); + } +} diff --git a/src/main/java/org/pdfbox/util/operator/pagedrawer/SetNonStrokingCMYKColor.java b/src/main/java/org/pdfbox/util/operator/pagedrawer/SetNonStrokingCMYKColor.java new file mode 100644 index 0000000..d1c37fe --- /dev/null +++ b/src/main/java/org/pdfbox/util/operator/pagedrawer/SetNonStrokingCMYKColor.java @@ -0,0 +1,64 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util.operator.pagedrawer; + +import java.util.List; + +import java.awt.Color; +import java.io.IOException; + +import org.pdfbox.pdfviewer.PageDrawer; +import org.pdfbox.pdmodel.graphics.color.PDColorSpaceInstance; +import org.pdfbox.util.PDFOperator; + +/** + * Implementation of content stream operator for page drawer. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.1 $ + */ +public class SetNonStrokingCMYKColor extends org.pdfbox.util.operator.SetNonStrokingCMYKColor +{ + /** + * k Set color space for non stroking operations. + * @param operator The operator that is being executed. + * @param arguments List + * @throws IOException If an error occurs while processing the font. + */ + public void process(PDFOperator operator, List arguments) throws IOException + { + super.process( operator, arguments ); + PageDrawer drawer = (PageDrawer)context; + PDColorSpaceInstance colorInstance = drawer.getGraphicsState().getNonStrokingColorSpace(); + Color color = colorInstance.createColor(); + drawer.setNonStrokingColor( color ); + } +} diff --git a/src/main/java/org/pdfbox/util/operator/pagedrawer/SetNonStrokingColorSpace.java b/src/main/java/org/pdfbox/util/operator/pagedrawer/SetNonStrokingColorSpace.java new file mode 100644 index 0000000..e5abae8 --- /dev/null +++ b/src/main/java/org/pdfbox/util/operator/pagedrawer/SetNonStrokingColorSpace.java @@ -0,0 +1,71 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util.operator.pagedrawer; + +import java.util.List; +import org.pdfbox.pdfviewer.PageDrawer; +import org.pdfbox.pdmodel.graphics.color.PDColorSpaceInstance; +import org.pdfbox.util.PDFOperator; + + +import java.awt.Color; +import java.io.IOException; + +/** + * Implementation of content stream operator for page drawer. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.1 $ + */ +public class SetNonStrokingColorSpace extends org.pdfbox.util.operator.SetNonStrokingColorSpace +{ + /** + * cs Set color space for non stroking operations. + * @param operator The operator that is being executed. + * @param arguments List + * @throws IOException If an error occurs while processing the font. + */ + public void process(PDFOperator operator, List arguments) throws IOException + { + try + { + super.process( operator, arguments ); + PageDrawer drawer = (PageDrawer)context; + PDColorSpaceInstance colorInstance = drawer.getGraphicsState().getNonStrokingColorSpace(); + Color color = colorInstance.createColor(); + drawer.setNonStrokingColor( color ); + } + catch( IOException e ) + { + //ignore for now and continue drawing + } + } +} diff --git a/src/main/java/org/pdfbox/util/operator/pagedrawer/SetNonStrokingRGBColor.java b/src/main/java/org/pdfbox/util/operator/pagedrawer/SetNonStrokingRGBColor.java new file mode 100644 index 0000000..f816d1f --- /dev/null +++ b/src/main/java/org/pdfbox/util/operator/pagedrawer/SetNonStrokingRGBColor.java @@ -0,0 +1,65 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util.operator.pagedrawer; + +import java.util.List; + +import java.awt.Color; +import java.io.IOException; + +import org.pdfbox.cos.COSNumber; +import org.pdfbox.pdfviewer.PageDrawer; +import org.pdfbox.util.PDFOperator; + +/** + * Implementation of content stream operator for page drawer. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.1 $ + */ +public class SetNonStrokingRGBColor extends org.pdfbox.util.operator.SetNonStrokingRGBColor +{ + /** + * rg Set color space for non stroking operations. + * @param operator The operator that is being executed. + * @param arguments List + * @throws IOException If an error occurs while processing the font. + */ + public void process(PDFOperator operator, List arguments) throws IOException + { + super.process( operator, arguments ); + PageDrawer drawer = (PageDrawer)context; + COSNumber r = (COSNumber)arguments.get( 0 ); + COSNumber g = (COSNumber)arguments.get( 1 ); + COSNumber b = (COSNumber)arguments.get( 2 ); + drawer.setNonStrokingColor( new Color( r.floatValue(), g.floatValue(), b.floatValue() ) ); + } +} diff --git a/src/main/java/org/pdfbox/util/operator/pagedrawer/SetStrokingCMYKColor.java b/src/main/java/org/pdfbox/util/operator/pagedrawer/SetStrokingCMYKColor.java new file mode 100644 index 0000000..81fcef3 --- /dev/null +++ b/src/main/java/org/pdfbox/util/operator/pagedrawer/SetStrokingCMYKColor.java @@ -0,0 +1,64 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util.operator.pagedrawer; + +import java.util.List; + +import java.awt.Color; +import java.io.IOException; + +import org.pdfbox.pdfviewer.PageDrawer; +import org.pdfbox.pdmodel.graphics.color.PDColorSpaceInstance; +import org.pdfbox.util.PDFOperator; + +/** + * Implementation of content stream operator for page drawer. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.1 $ + */ +public class SetStrokingCMYKColor extends org.pdfbox.util.operator.SetStrokingCMYKColor +{ + /** + * CS Set color space for stroking operations. + * @param operator The operator that is being executed. + * @param arguments List + * @throws IOException If an error occurs while processing the font. + */ + public void process(PDFOperator operator, List arguments) throws IOException + { + super.process( operator, arguments ); + PageDrawer drawer = (PageDrawer)context; + PDColorSpaceInstance colorInstance = drawer.getGraphicsState().getNonStrokingColorSpace(); + Color color = colorInstance.createColor(); + drawer.setStrokingColor( color ); + } +} diff --git a/src/main/java/org/pdfbox/util/operator/pagedrawer/SetStrokingColorSpace.java b/src/main/java/org/pdfbox/util/operator/pagedrawer/SetStrokingColorSpace.java new file mode 100644 index 0000000..22c9c5c --- /dev/null +++ b/src/main/java/org/pdfbox/util/operator/pagedrawer/SetStrokingColorSpace.java @@ -0,0 +1,70 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util.operator.pagedrawer; + +import java.util.List; +import org.pdfbox.pdfviewer.PageDrawer; +import org.pdfbox.pdmodel.graphics.color.PDColorSpaceInstance; +import org.pdfbox.util.PDFOperator; + +import java.awt.Color; +import java.io.IOException; + +/** + * Implementation of content stream operator for page drawer. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.1 $ + */ +public class SetStrokingColorSpace extends org.pdfbox.util.operator.SetNonStrokingColorSpace +{ + /** + * CS Set color space for stroking operations. + * @param operator The operator that is being executed. + * @param arguments List + * @throws IOException If an error occurs while processing the font. + */ + public void process(PDFOperator operator, List arguments) throws IOException + { + super.process( operator, arguments ); + try + { + PageDrawer drawer = (PageDrawer)context; + PDColorSpaceInstance colorInstance = drawer.getGraphicsState().getNonStrokingColorSpace(); + Color color = colorInstance.createColor(); + drawer.setStrokingColor( color ); + } + catch( IOException e ) + { + //ignore for now and continue drawing + } + } +} diff --git a/src/main/java/org/pdfbox/util/operator/pagedrawer/SetStrokingRGBColor.java b/src/main/java/org/pdfbox/util/operator/pagedrawer/SetStrokingRGBColor.java new file mode 100644 index 0000000..8d7099e --- /dev/null +++ b/src/main/java/org/pdfbox/util/operator/pagedrawer/SetStrokingRGBColor.java @@ -0,0 +1,65 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util.operator.pagedrawer; + +import java.util.List; + +import java.awt.Color; +import java.io.IOException; + +import org.pdfbox.cos.COSNumber; +import org.pdfbox.pdfviewer.PageDrawer; +import org.pdfbox.util.PDFOperator; + +/** + * Implementation of content stream operator for page drawer. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.1 $ + */ +public class SetStrokingRGBColor extends org.pdfbox.util.operator.SetStrokingRGBColor +{ + /** + * RG Set color space for stroking operations. + * @param operator The operator that is being executed. + * @param arguments List + * @throws IOException If an error occurs while processing the font. + */ + public void process(PDFOperator operator, List arguments) throws IOException + { + super.process( operator, arguments ); + PageDrawer drawer = (PageDrawer)context; + COSNumber r = (COSNumber)arguments.get( 0 ); + COSNumber g = (COSNumber)arguments.get( 1 ); + COSNumber b = (COSNumber)arguments.get( 2 ); + drawer.setStrokingColor( new Color( r.floatValue(), g.floatValue(), b.floatValue() ) ); + } +} diff --git a/src/main/java/org/pdfbox/util/operator/pagedrawer/StrokePath.java b/src/main/java/org/pdfbox/util/operator/pagedrawer/StrokePath.java new file mode 100644 index 0000000..31a489c --- /dev/null +++ b/src/main/java/org/pdfbox/util/operator/pagedrawer/StrokePath.java @@ -0,0 +1,73 @@ +/** + * Copyright (c) 2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 REGENTS 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. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.util.operator.pagedrawer; + +import java.util.List; +import org.pdfbox.pdfviewer.PageDrawer; +import org.pdfbox.util.PDFOperator; + +import java.awt.Graphics2D; +import java.awt.geom.GeneralPath; +import java.io.IOException; + +/** + * Implementation of content stream operator for page drawer. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.1 $ + */ +public class StrokePath extends org.pdfbox.util.operator.SetLineWidth +{ + + /** + * S stroke the path. + * @param operator The operator that is being executed. + * @param arguments List + * + * @throws IOException If an error occurs while processing the font. + */ + public void process(PDFOperator operator, List arguments) throws IOException + { + PageDrawer drawer = (PageDrawer)context; + Graphics2D graphics = ((PageDrawer)context).getGraphics(); + graphics.setColor( drawer.getStrokingColor() ); + List subPaths = drawer.getLineSubPaths(); + for( int i=0; i + + + + + +This package contains implementations of all of the PDF operators. + + diff --git a/src/main/java/org/pdfbox/util/package.html b/src/main/java/org/pdfbox/util/package.html new file mode 100644 index 0000000..f8948fb --- /dev/null +++ b/src/main/java/org/pdfbox/util/package.html @@ -0,0 +1,9 @@ + + + + + + +This package contains utility classes that are used by the PDFBox project. + + -- cgit v1.2.3