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 --- .../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 + 170 files changed, 34770 insertions(+) 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 (limited to 'src/main/java/org/pdfbox/pdmodel') 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 -- cgit v1.2.3